diff --git a/.gitmodules b/.gitmodules
index b95ace0aa4..6e808b3753 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -441,3 +441,7 @@
[submodule "vendor/boost-submodules/boost-tokenizer"]
path = vendor/boost-submodules/boost-tokenizer
url = https://github.com/boostorg/tokenizer
+[submodule "vendor/msgpack-cs"]
+ path = vendor/msgpack-cs
+ url = https://github.com/citizenfx/msgpack-cs.git
+ branch = production
diff --git a/code/client/clrcore-v2/Attributes.cs b/code/client/clrcore-v2/Attributes.cs
index b282b20adf..3e19e6f54f 100644
--- a/code/client/clrcore-v2/Attributes.cs
+++ b/code/client/clrcore-v2/Attributes.cs
@@ -49,7 +49,7 @@ public class CommandAttribute : Attribute
public bool Restricted { get; set; }
///
- ///
+ ///
public bool RemapParameters { get; set; } = false;
public CommandAttribute(string command, bool restricted = false)
{
@@ -77,7 +77,7 @@ public class KeyMapAttribute : Attribute
public string InputParameter { get; }
///
- ///
+ ///
public bool RemapParameters { get; set; } = false;
///
diff --git a/code/client/clrcore-v2/BaseScript.cs b/code/client/clrcore-v2/BaseScript.cs
index bd4ea15e38..fa90272cf3 100644
--- a/code/client/clrcore-v2/BaseScript.cs
+++ b/code/client/clrcore-v2/BaseScript.cs
@@ -1,6 +1,8 @@
+using CitizenFX.MsgPack;
using System;
using System.Collections.Generic;
using System.ComponentModel;
+using System.Linq;
using System.Reflection;
using System.Security;
@@ -33,9 +35,9 @@ protected event Func Tick
remove => UnregisterTick(value);
}
- private readonly List> m_commands = new List>();
+ private readonly List> m_commands = new List>();
- private readonly Dictionary m_nuiCallbacks = new Dictionary();
+ private readonly Dictionary m_nuiCallbacks = new Dictionary();
#if REMOTE_FUNCTION_ENABLED
private readonly List m_persistentFunctions = new List();
@@ -92,22 +94,30 @@ internal void Initialize()
break;
case EventHandlerAttribute eventHandler:
- RegisterEventHandler(eventHandler.Event, Func.Create(this, method), eventHandler.Binding);
+ RegisterEventHandler(eventHandler.Event, MsgPackDeserializer.CreateDelegate(this, method), eventHandler.Binding);
break;
case CommandAttribute command:
- RegisterCommand(command.Command, Func.CreateCommand(this, method, command.RemapParameters), command.Restricted);
+ {
+ // Automatically remap methods with [Source] parameters
+ bool remap = command.RemapParameters || method.GetParameters().Any(p => Attribute.GetCustomAttribute(p, typeof(SourceAttribute)) != null);
+ RegisterCommand(command.Command, MsgPackDeserializer.CreateCommandDelegate(this, method, remap), command.Restricted);
+ }
break;
#if !IS_FXSERVER
case KeyMapAttribute keyMap:
- RegisterKeyMap(keyMap.Command, keyMap.Description, keyMap.InputMapper, keyMap.InputParameter, Func.CreateCommand(this, method, keyMap.RemapParameters));
+ {
+ // Automatically remap methods with [Source] parameters
+ bool remap = keyMap.RemapParameters || method.GetParameters().Any(p => Attribute.GetCustomAttribute(p, typeof(SourceAttribute)) != null);
+ RegisterKeyMap(keyMap.Command, keyMap.Description, keyMap.InputMapper, keyMap.InputParameter, MsgPackDeserializer.CreateCommandDelegate(this, method, remap));
+ }
break;
case NuiCallbackAttribute nuiCallback:
RegisterNuiCallback(nuiCallback.CallbackName, Func.Create(this, method));
break;
#endif
case ExportAttribute export:
- Exports.Add(export.Export, Func.Create(this, method), export.Binding);
+ Exports.Add(export.Export, MsgPackDeserializer.CreateDelegate(this, method), export.Binding);
break;
}
}
@@ -179,7 +189,7 @@ public void Disable()
// commands
for (int i = 0; i < m_commands.Count; ++i)
{
- ReferenceFunctionManager.SetDelegate(m_commands[i].Key, (_0, _1) => null);
+ ReferenceFunctionManager.SetDelegate(m_commands[i].Key, delegate(Remote _0, ref MsgPackDeserializer _1) { return null; });
}
foreach (var nuiCallback in m_nuiCallbacks)
@@ -280,13 +290,13 @@ public void UnregisterTick(Func tick)
#endregion
#region Events & Command registration
- internal void RegisterEventHandler(string eventName, DynFunc deleg, Binding binding = Binding.Local) => EventHandlers[eventName].Add(deleg, binding);
- internal void UnregisterEventHandler(string eventName, DynFunc deleg) => EventHandlers[eventName].Remove(deleg);
+ internal void RegisterEventHandler(string eventName, MsgPackFunc deleg, Binding binding = Binding.Local) => EventHandlers[eventName].Add(deleg, binding);
+ internal void UnregisterEventHandler(string eventName, MsgPackFunc deleg) => EventHandlers[eventName].Remove(deleg);
- internal void RegisterCommand(string command, DynFunc dynFunc, bool isRestricted = true)
- => m_commands.Add(new KeyValuePair(ReferenceFunctionManager.CreateCommand(command, dynFunc, isRestricted), dynFunc));
+ internal void RegisterCommand(string command, MsgPackFunc dynFunc, bool isRestricted = true)
+ => m_commands.Add(new KeyValuePair(ReferenceFunctionManager.CreateCommand(command, dynFunc, isRestricted), dynFunc));
- internal void RegisterKeyMap(string command, string description, string inputMapper, string inputParameter, DynFunc dynFunc)
+ internal void RegisterKeyMap(string command, string description, string inputMapper, string inputParameter, MsgPackFunc dynFunc)
{
#if !GTA_FIVE
throw new NotImplementedException();
@@ -295,7 +305,7 @@ internal void RegisterKeyMap(string command, string description, string inputMap
{
Native.CoreNatives.RegisterKeyMapping(command, description, inputMapper, inputParameter);
}
- m_commands.Add(new KeyValuePair(ReferenceFunctionManager.CreateCommand(command, dynFunc, false), dynFunc));
+ m_commands.Add(new KeyValuePair(ReferenceFunctionManager.CreateCommand(command, dynFunc, false), dynFunc));
#endif
}
@@ -303,7 +313,7 @@ internal void RegisterKeyMap(string command, string description, string inputMap
#region NUI Callback registration
- internal void RegisterNuiCallback(string callbackName, DynFunc dynFunc)
+ internal void RegisterNuiCallback(string callbackName, MsgPackFunc dynFunc)
{
#if IS_FXSERVER
throw new NotImplementedException();
@@ -326,7 +336,7 @@ public void RegisterNuiCallback(string callbackName, Delegate delegateFn)
#if IS_FXSERVER
throw new NotImplementedException();
#endif
- DynFunc dynFunc = Func.Create(delegateFn);
+ MsgPackFunc dynFunc = MsgPackDeserializer.CreateDelegate(delegateFn);
m_nuiCallbacks.Add(callbackName, dynFunc);
Native.CoreNatives.RegisterNuiCallback(callbackName, dynFunc);
}
diff --git a/code/client/clrcore-v2/DynFunc.cs b/code/client/clrcore-v2/DynFunc.cs
index 330d1f79f3..71b3e31cfd 100644
--- a/code/client/clrcore-v2/DynFunc.cs
+++ b/code/client/clrcore-v2/DynFunc.cs
@@ -102,10 +102,6 @@ public static DynFunc Create(object target, MethodInfo method)
// no need to recreate it
public static DynFunc Create(DynFunc deleg) => deleg;
- [SecurityCritical]
- internal static DynFunc CreateCommand(object target, MethodInfo method, bool remap)
- => remap ? ConstructCommandRemapped(target, method) : Construct(target, method);
-
[SecurityCritical]
private static DynFunc Construct(object target, MethodInfo method)
{
@@ -216,140 +212,6 @@ private static DynFunc Construct(object target, MethodInfo method)
}
}
-#if DYN_FUNC_CALLI
- g.Emit(OpCodes.Ldc_I8, (long)method.MethodHandle.GetFunctionPointer());
- g.EmitCalli(OpCodes.Calli, method.CallingConvention, method.ReturnType, parameterTypes, null);
-#else
- g.EmitCall(OpCodes.Call, method, null);
-#endif
-
- if (method.ReturnType == typeof(void))
- g.Emit(OpCodes.Ldnull);
- else
- g.Emit(OpCodes.Box, method.ReturnType);
-
- g.Emit(OpCodes.Ret);
-
- Delegate dynFunc = lambda.CreateDelegate(typeof(DynFunc), target);
-
- s_wrappedMethods.Add(method, dynFunc.Method);
- s_dynfuncMethods.Add(dynFunc.Method, method);
-
- return (DynFunc)dynFunc;
- }
-
- ///
- /// If enabled creates a that remaps input ( source, [] arguments, raw) to known types:
- /// source: , , , , , or any type constructable from including Player types.
- /// arguments: [] or [].
- /// raw:
- ///
- /// Method's associated instance
- /// Method to wrap
- /// Dynamic invocable with remapping and conversion support.
- /// When is used on a non supported type.
- /// When any requested parameter isn't supported.
- [SecurityCritical]
- private static DynFunc ConstructCommandRemapped(object target, MethodInfo method)
- {
- if (s_wrappedMethods.TryGetValue(method, out var existingMethod))
- {
- return (DynFunc)existingMethod.CreateDelegate(typeof(DynFunc), target);
- }
-
- ParameterInfo[] parameters = method.GetParameters();
-#if DYN_FUNC_CALLI
- Type[] parameterTypes = new Type[parameters.Length];
-#endif
- bool hasThis = (method.CallingConvention & CallingConventions.HasThis) != 0;
-
- var lambda = new DynamicMethod($"{method.DeclaringType.FullName}.{method.Name}", typeof(object),
- hasThis ? new[] { typeof(object), typeof(Remote), typeof(object[]) } : new[] { typeof(Remote), typeof(object[]) });
-
- ILGenerator g = lambda.GetILGenerator();
-
- OpCode ldarg_args;
- if (hasThis)
- {
- g.Emit(OpCodes.Ldarg_0);
- ldarg_args = OpCodes.Ldarg_2;
- }
- else
- {
- target = null;
- ldarg_args = OpCodes.Ldarg_1;
- }
-
- for (int i = 0; i < parameters.Length; ++i)
- {
- var parameter = parameters[i];
- var t = parameter.ParameterType;
-
-#if DYN_FUNC_CALLI
- parameterTypes[i] = t;
-#endif
- if (Attribute.IsDefined(parameter, typeof(SourceAttribute), true)) // source
- {
- g.Emit(ldarg_args);
- g.Emit(OpCodes.Ldc_I4_0);
- g.Emit(OpCodes.Ldelem_Ref);
- g.Emit(OpCodes.Call, GetMethodInfo