citizenfx / fivem

The source code for the Cfx.re modification frameworks, such as FiveM, RedM and LibertyM, as well as FXServer.
https://cfx.re/
3.41k stars 2.01k forks source link

feat(clrcore-v2): Move to custom MsgPack serializer #2546

Closed thorium-cfx closed 1 month ago

thorium-cfx commented 2 months ago

Goal of this PR

Enable (de)serialization to and from custom types on events, exports, nui callbacks, and other refFuncs within the mono rt2 runtime. A highly requested feature for the C# environments, as a lot of extra work and workarounds are currently applied to compensate for the lack there-of.

  1. Optional parameters are also supported with this update.
  2. Performance is roughly 30% faster for single listeners, making it slower for 3+ listeners for each event (why would you even do this?).

Notes:

  1. This is the last big update for the mono rt2 scripting runtime before we exit the pilot stage.
  2. Issues are expected; unit tests are put in place for some situations, but not all and/or unforeseen use-cases are tested yet.

How is this PR achieving the goal

Allows for in place conversion of serialized data.

Example:

[EventHandler("myEvent")]
public static async Coroutine GimmeAll(int a)
    => Debug.WriteLine($"GimmeAll1 {a}");

[EventHandler("myEvent")]
public static async Coroutine GimmeAll(string a, int b)
    => Debug.WriteLine($"GimmeAll2 {a} {b}");

[EventHandler("myEvent")]
public static async Coroutine GimmeAll(string a, int b, string c = "Hey")
    => Debug.WriteLine($"GimmeAll3 {a} {b} {c}");

[EventHandler("myEvent")]
public static async Coroutine GimmeAll(int a, string b, string c = "Oh", int d = 678)
    => Debug.WriteLine($"GimmeAll4 {a} {b} {c} {d}");

[EventHandler("myEvent")]
public static async Coroutine GimmeAll(int a, Player b, string c = "Oh", int d = 678)
    => Debug.WriteLine($"GimmeAll5 {a} {b} {c} {d}");

// Trigger it!
[Command("Gimme")]
public async Coroutine Gimme(uint source, object[] objects, string raw)
    => Events.TriggerServerEvent("myEvent", 1234, "5678");

gives the following output:

[    script:csharp_v2] GimmeAll1 1234
[    script:csharp_v2] GimmeAll2 1234 5678
[    script:csharp_v2] GimmeAll3 1234 5678 Hey
[    script:csharp_v2] GimmeAll4 1234 5678 Oh 678
[    script:csharp_v2] GimmeAll5 1234 Player(5678) Oh 678

This PR applies to the following area(s)

ScRT: C#

Successfully tested on

FXServer and

Game builds: N/A

Platforms: Windows

Checklist

Fixes issues

closes thorium-cfx/mono_v2_get_started#20

Thanks / Contributors

A big thanks goes out @manups4e, showing me how his FxEvents project used a completely different approach, this became the base and eventually the way forward on MsgPack (de)serialization for the mono v2 scripting environment.

IllInuz commented 2 months ago

Ooo fancy!

schuster19uk commented 1 month ago

Is it possible to provide an example of how to use the API.EventManagerPeekEvent as i am seeing this as still requiring an object to be passed as a reference ?

DaniGP17 commented 1 month ago

@thorium-cfx Looks like this has broken the export system and every time an export is executed an error is thrown.

Example code:

[Export("test")]
public static string ExportE2()
{
    return "yeahh";
}
[    c-scripting-mono] Exception in Mono script environment: System.NotSupportedException: Requested serializer for MethodInfo.CustomAttributes of type System.Collections.Generic.IEnumerable`1[System.Reflection.CustomAttributeData] could not be found.
[    c-scripting-mono]   at CitizenFX.MsgPack.Formatters.TypeFormatter.BuildSerializeMapBody (System.Type type, System.Reflection.Emit.ILGenerator g, CitizenFX.MsgPack.Detail.DynamicArray`1[T] members, System.Reflection.MethodInfo currentSerializer) [0x0023f] in C:\gl\builds\cfx-fivem\master\fxserver\vendor\msgpack-cs\MsgPack\Formatters\TypeFormatter.cs:323
[    c-scripting-mono]   at CitizenFX.MsgPack.Formatters.TypeFormatter.BuildSerializer (System.Type type, System.Reflection.Emit.TypeBuilder typeBuilder) [0x00117] in C:\gl\builds\cfx-fivem\master\fxserver\vendor\msgpack-cs\MsgPack\Formatters\TypeFormatter.cs:170
[    c-scripting-mono]   at CitizenFX.MsgPack.Formatters.TypeFormatter.Build (System.Type type) [0x000ce] in C:\gl\builds\cfx-fivem\master\fxserver\vendor\msgpack-cs\MsgPack\Formatters\TypeFormatter.cs:79
[    c-scripting-mono]   at CitizenFX.MsgPack.MsgPackRegistry.CreateSerializer (System.Type type) [0x0008e] in C:\gl\builds\cfx-fivem\master\fxserver\vendor\msgpack-cs\MsgPack\MsgPackRegistry.cs:214
[    c-scripting-mono]   at CitizenFX.MsgPack.MsgPackRegistry.GetOrCreateSerializer (System.Type type) [0x00000] in C:\gl\builds\cfx-fivem\master\fxserver\vendor\msgpack-cs\MsgPack\MsgPackRegistry.cs:167
[    c-scripting-mono]   at CitizenFX.MsgPack.Formatters.TypeFormatter.BuildSerializeMapBody (System.Type type, System.Reflection.Emit.ILGenerator g, CitizenFX.MsgPack.Detail.DynamicArray`1[T] members, System.Reflection.MethodInfo currentSerializer) [0x0015b] in C:\gl\builds\cfx-fivem\master\fxserver\vendor\msgpack-cs\MsgPack\Formatters\TypeFormatter.cs:293
[    c-scripting-mono]   at CitizenFX.MsgPack.Formatters.TypeFormatter.BuildSerializer (System.Type type, System.Reflection.Emit.TypeBuilder typeBuilder) [0x00117] in C:\gl\builds\cfx-fivem\master\fxserver\vendor\msgpack-cs\MsgPack\Formatters\TypeFormatter.cs:170
[    c-scripting-mono]   at CitizenFX.MsgPack.Formatters.TypeFormatter.Build (System.Type type) [0x000ce] in C:\gl\builds\cfx-fivem\master\fxserver\vendor\msgpack-cs\MsgPack\Formatters\TypeFormatter.cs:79
[    c-scripting-mono]   at CitizenFX.MsgPack.MsgPackRegistry.CreateSerializer (System.Type type) [0x0008e] in C:\gl\builds\cfx-fivem\master\fxserver\vendor\msgpack-cs\MsgPack\MsgPackRegistry.cs:214
[    c-scripting-mono]   at CitizenFX.MsgPack.MsgPackRegistry.Serialize (CitizenFX.MsgPack.MsgPackSerializer serializer, System.Object obj) [0x0018a] in C:\gl\builds\cfx-fivem\master\fxserver\vendor\msgpack-cs\MsgPack\MsgPackRegistry.cs:143

[    c-scripting-mono]   at CitizenFX.MsgPack.MsgPackSerializer.Serialize (System.Object v) [0x00000] in C:\gl\builds\cfx-fivem\master\fxserver\vendor\msgpack-cs\MsgPack\MsgPackSerializer.cs:70
[    c-scripting-mono]   at CitizenFX.MsgPack.MsgPackSerializer.Serialize (System.Object[] v) [0x0000d] in C:\gl\builds\cfx-fivem\master\fxserver\vendor\msgpack-cs\MsgPack\MsgPackSerializer.cs:256
[    c-scripting-mono]   at (wrapper dynamic-method) System.Object.MsgPackSerializer(CitizenFX.MsgPack.MsgPackSerializer,object)
[    c-scripting-mono]   at CitizenFX.MsgPack.MsgPackRegistry.Serialize (CitizenFX.MsgPack.MsgPackSerializer serializer, System.Object obj) [0x0017b] in C:\gl\builds\cfx-fivem\master\fxserver\vendor\msgpack-cs\MsgPack\MsgPackRegistry.cs:139

[    c-scripting-mono]   at CitizenFX.MsgPack.MsgPackSerializer.Serialize (System.Object v) [0x00000] in C:\gl\builds\cfx-fivem\master\fxserver\vendor\msgpack-cs\MsgPack\MsgPackSerializer.cs:70
[    c-scripting-mono]   at CitizenFX.MsgPack.MsgPackSerializer.SerializeToByteArray (System.Object value) [0x00005] in C:\gl\builds\cfx-fivem\master\fxserver\vendor\msgpack-cs\MsgPack\MsgPackSerializer.cs:59
[    c-scripting-mono]   at CitizenFX.Core.Native.InPacket..ctor (System.Object obj) [0x00000] in C:\gl\builds\cfx-fivem\master\fxserver\code\client\clrcore-v2\Native\Types\NativeTypes.cs:80
[    c-scripting-mono]   at CitizenFX.Core.Native.InPacket.Serialize (System.Object obj) [0x00000] in C:\gl\builds\cfx-fivem\master\fxserver\code\client\clrcore-v2\Native\Types\NativeTypes.cs:81
[    c-scripting-mono]   at CitizenFX.Core.Native.InPacket.op_Implicit (System.Object[] obj) [0x00000] in C:\gl\builds\cfx-fivem\master\fxserver\code\client\clrcore-v2\Native\Types\NativeTypes.cs:82
[    c-scripting-mono]   at CitizenFX.Core._LocalFunction.Invoke (System.Object[] args) [0x00000] in C:\gl\builds\cfx-fivem\master\fxserver\code\client\clrcore-v2\Interop\LocalFunction.cs:46
[    c-scripting-mono]   at CitizenFX.Core.ExportsManager.IncomingRequest (System.String eventName, System.String sourceString, CitizenFX.Core.Binding origin, System.Byte* argsSerialized, System.Int32 serializedSize) [0x0003b] in C:\gl\builds\cfx-fivem\master\fxserver\code\client\clrcore-v2\Interop\ExportsManager.cs:34
[    c-scripting-mono]   at CitizenFX.Core.ScriptInterface.TriggerEvent (System.String eventName, System.Byte* argsSerialized, System.Int32 serializedSize, System.String sourceString, System.UInt64 hostTime, System.Boolean profiling) [0x0003c] in C:\gl\builds\cfx-fivem\master\fxserver\code\client\clrcore-v2\ScriptInterface.cs:151
[    c-scripting-mono]   at (wrapper native-to-managed) CitizenFX.Core.ScriptInterface.TriggerEvent(string,byte*,int,string,ulong,bool,System.Exception&)
[    c-scripting-mono]   at CitizenFX.MsgPack.Formatters.TypeFormatter.BuildSerializeMapBody (System.Type type, System.Reflection.Emit.ILGenerator g, CitizenFX.MsgPack.Detail.DynamicArray`1[T] members, System.Reflection.MethodInfo currentSerializer) [0x0023f] in C:\gl\builds\cfx-fivem\master\fxserver\vendor\msgpack-cs\MsgPack\Formatters\TypeFormatter.cs:323
[    c-scripting-mono]   at CitizenFX.MsgPack.Formatters.TypeFormatter.BuildSerializer (System.Type type, System.Reflection.Emit.TypeBuilder typeBuilder) [0x00117] in C:\gl\builds\cfx-fivem\master\fxserver\vendor\msgpack-cs\MsgPack\Formatters\TypeFormatter.cs:170
[    c-scripting-mono]   at CitizenFX.MsgPack.Formatters.TypeFormatter.Build (System.Type type) [0x000ce] in C:\gl\builds\cfx-fivem\master\fxserver\vendor\msgpack-cs\MsgPack\Formatters\TypeFormatter.cs:79
[    c-scripting-mono]   at CitizenFX.MsgPack.MsgPackRegistry.CreateSerializer (System.Type type) [0x0008e] in C:\gl\builds\cfx-fivem\master\fxserver\vendor\msgpack-cs\MsgPack\MsgPackRegistry.cs:214
[    c-scripting-mono]   at CitizenFX.MsgPack.MsgPackRegistry.GetOrCreateSerializer (System.Type type) [0x00000] in C:\gl\builds\cfx-fivem\master\fxserver\vendor\msgpack-cs\MsgPack\MsgPackRegistry.cs:167
[    c-scripting-mono]   at CitizenFX.MsgPack.Formatters.TypeFormatter.BuildSerializeMapBody (System.Type type, System.Reflection.Emit.ILGenerator g, CitizenFX.MsgPack.Detail.DynamicArray`1[T] members, System.Reflection.MethodInfo currentSerializer) [0x0015b] in C:\gl\builds\cfx-fivem\master\fxserver\vendor\msgpack-cs\MsgPack\Formatters\TypeFormatter.cs:293
[    c-scripting-mono]   at CitizenFX.MsgPack.Formatters.TypeFormatter.BuildSerializer (System.Type type, System.Reflection.Emit.TypeBuilder typeBuilder) [0x00117] in C:\gl\builds\cfx-fivem\master\fxserver\vendor\msgpack-cs\MsgPack\Formatters\TypeFormatter.cs:170
[    c-scripting-mono]   at CitizenFX.MsgPack.Formatters.TypeFormatter.Build (System.Type type) [0x000ce] in C:\gl\builds\cfx-fivem\master\fxserver\vendor\msgpack-cs\MsgPack\Formatters\TypeFormatter.cs:79
[    c-scripting-mono]   at CitizenFX.MsgPack.MsgPackRegistry.CreateSerializer (System.Type type) [0x0008e] in C:\gl\builds\cfx-fivem\master\fxserver\vendor\msgpack-cs\MsgPack\MsgPackRegistry.cs:214
[    c-scripting-mono]   at CitizenFX.MsgPack.MsgPackRegistry.Serialize (CitizenFX.MsgPack.MsgPackSerializer serializer, System.Object obj) [0x0018a] in C:\gl\builds\cfx-fivem\master\fxserver\vendor\msgpack-cs\MsgPack\MsgPackRegistry.cs:143

[    c-scripting-mono]   at CitizenFX.MsgPack.MsgPackSerializer.Serialize (System.Object v) [0x00000] in C:\gl\builds\cfx-fivem\master\fxserver\vendor\msgpack-cs\MsgPack\MsgPackSerializer.cs:70
[    c-scripting-mono]   at CitizenFX.MsgPack.MsgPackSerializer.Serialize (System.Object[] v) [0x0000d] in C:\gl\builds\cfx-fivem\master\fxserver\vendor\msgpack-cs\MsgPack\MsgPackSerializer.cs:256
[    c-scripting-mono]   at (wrapper dynamic-method) System.Object.MsgPackSerializer(CitizenFX.MsgPack.MsgPackSerializer,object)
[    c-scripting-mono]   at CitizenFX.MsgPack.MsgPackRegistry.Serialize (CitizenFX.MsgPack.MsgPackSerializer serializer, System.Object obj) [0x0017b] in C:\gl\builds\cfx-fivem\master\fxserver\vendor\msgpack-cs\MsgPack\MsgPackRegistry.cs:139

[    c-scripting-mono]   at CitizenFX.MsgPack.MsgPackSerializer.Serialize (System.Object v) [0x00000] in C:\gl\builds\cfx-fivem\master\fxserver\vendor\msgpack-cs\MsgPack\MsgPackSerializer.cs:70
[    c-scripting-mono]   at CitizenFX.MsgPack.MsgPackSerializer.SerializeToByteArray (System.Object value) [0x00005] in C:\gl\builds\cfx-fivem\master\fxserver\vendor\msgpack-cs\MsgPack\MsgPackSerializer.cs:59
[    c-scripting-mono]   at CitizenFX.Core.Native.InPacket..ctor (System.Object obj) [0x00000] in C:\gl\builds\cfx-fivem\master\fxserver\code\client\clrcore-v2\Native\Types\NativeTypes.cs:80
[    c-scripting-mono]   at CitizenFX.Core.Native.InPacket.Serialize (System.Object obj) [0x00000] in C:\gl\builds\cfx-fivem\master\fxserver\code\client\clrcore-v2\Native\Types\NativeTypes.cs:81
[    c-scripting-mono]   at CitizenFX.Core.Native.InPacket.op_Implicit (System.Object[] obj) [0x00000] in C:\gl\builds\cfx-fivem\master\fxserver\code\client\clrcore-v2\Native\Types\NativeTypes.cs:82
[    c-scripting-mono]   at CitizenFX.Core._LocalFunction.Invoke (System.Object[] args) [0x00000] in C:\gl\builds\cfx-fivem\master\fxserver\code\client\clrcore-v2\Interop\LocalFunction.cs:46
[    c-scripting-mono]   at CitizenFX.Core.ExportsManager.IncomingRequest (System.String eventName, System.String sourceString, CitizenFX.Core.Binding origin, System.Byte* argsSerialized, System.Int32 serializedSize) [0x0003b] in C:\gl\builds\cfx-fivem\master\fxserver\code\client\clrcore-v2\Interop\ExportsManager.cs:34
[    c-scripting-mono]   at CitizenFX.Core.ScriptInterface.TriggerEvent (System.String eventName, System.Byte* argsSerialized, System.Int32 serializedSize, System.String sourceString, System.UInt64 hostTime, System.Boolean profiling) [0x0003c] in C:\gl\builds\cfx-fivem\master\fxserver\code\client\clrcore-v2\ScriptInterface.cs:151
[    c-scripting-mono]   at (wrapper native-to-managed) CitizenFX.Core.ScriptInterface.TriggerEvent(string,byte*,int,string,ulong,bool,System.Exception&)Failed to execute event __cfx_export_monodb_testt - 80070057.