diff --git a/code/client/clrcore-v2/Attributes.cs b/code/client/clrcore-v2/Attributes.cs
index c7faa66c28..dc681e19b1 100644
--- a/code/client/clrcore-v2/Attributes.cs
+++ b/code/client/clrcore-v2/Attributes.cs
@@ -116,6 +116,32 @@ public EventHandlerAttribute(string name, Binding binding = Binding.All)
Binding = binding;
}
}
+
+#if !IS_FXSERVER
+ ///
+ /// Register this method to listen for the given when this is loaded
+ /// if is specified this will use a raw NUI callback instead
+ ///
+ /// Only works on inherited class methods
+#else
+ /// Does nothing on server side
+ [EditorBrowsable(EditorBrowsableState.Never)]
+#endif
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
+ public class NuiCallbackAttribute : Attribute
+ {
+ public string CallbackName { get; }
+ public bool IsRawCallback { get; }
+ public NuiCallbackAttribute(string callbackName, bool isRawCallback = false)
+ {
+ CallbackName = callbackName;
+ if (isRawCallback)
+ {
+ throw new NotImplementedException("Raw Nui Callbacks are not currently implemented");
+ }
+ IsRawCallback = isRawCallback;
+ }
+ }
///
/// Register this method to listen for the given when this is loaded
diff --git a/code/client/clrcore-v2/BaseScript.cs b/code/client/clrcore-v2/BaseScript.cs
index cc604661ec..7e38edac56 100644
--- a/code/client/clrcore-v2/BaseScript.cs
+++ b/code/client/clrcore-v2/BaseScript.cs
@@ -34,6 +34,8 @@ protected event Func Tick
}
private readonly List> m_commands = new List>();
+
+ private readonly Dictionary m_nuiCallbacks = new Dictionary();
#if REMOTE_FUNCTION_ENABLED
private readonly List m_persistentFunctions = new List();
@@ -100,6 +102,9 @@ internal void Initialize()
case KeyMapAttribute keyMap:
RegisterKeyMap(keyMap.Command, keyMap.Description, keyMap.InputMapper, keyMap.InputParameter, Func.CreateCommand(this, method, keyMap.RemapParameters));
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);
@@ -140,6 +145,11 @@ public void Enable()
ReferenceFunctionManager.SetDelegate(m_commands[i].Key, m_commands[i].Value);
}
+ foreach (var nuiCallback in m_nuiCallbacks)
+ {
+ Native.CoreNatives.RegisterNuiCallback(nuiCallback.Key, nuiCallback.Value);
+ }
+
EventHandlers.Enable();
Exports.Enable();
@@ -171,6 +181,11 @@ public void Disable()
{
ReferenceFunctionManager.SetDelegate(m_commands[i].Key, (_0, _1) => null);
}
+
+ foreach (var nuiCallback in m_nuiCallbacks)
+ {
+ Native.CoreNatives.RemoveNuiCallback(nuiCallback.Key);
+ }
EventHandlers.Disable();
Exports.Disable();
@@ -283,7 +298,90 @@ internal void RegisterKeyMap(string command, string description, string inputMap
m_commands.Add(new KeyValuePair(ReferenceFunctionManager.CreateCommand(command, dynFunc, false), dynFunc));
#endif
}
+
+ #endregion
+
+ #region NUI Callback registration
+
+ internal void RegisterNuiCallback(string callbackName, DynFunc dynFunc)
+ {
+#if IS_FXSERVER
+ throw new NotImplementedException();
+#endif
+ m_nuiCallbacks.Add(callbackName, dynFunc);
+ Native.CoreNatives.RegisterNuiCallback(callbackName, dynFunc);
+ }
+
+ ///
+ /// Registers the NUI callback and binds it to the the
+ ///
+ /// the NUI callback to add
+ /// The function to bind the callback to, the callback will be invoked with an ExpandoObject containing the data and a
+#if IS_FXSERVER
+ /// Does nothing on server side
+ [EditorBrowsable(EditorBrowsableState.Never)]
+#endif
+ public void RegisterNuiCallback(string callbackName, Delegate delegateFn)
+ {
+#if IS_FXSERVER
+ throw new NotImplementedException();
+#endif
+ DynFunc dynFunc = Func.Create(delegateFn);
+ m_nuiCallbacks.Add(callbackName, dynFunc);
+ Native.CoreNatives.RegisterNuiCallback(callbackName, dynFunc);
+ }
+
+ ///
+ /// Unregisters the NUI callback from the
+ ///
+ /// the NUI callback to remove
+#if IS_FXSERVER
+ /// Does nothing on server side
+ [EditorBrowsable(EditorBrowsableState.Never)]
+#endif
+ public void UnregisterNuiCallback(string callbackName)
+ {
+#if IS_FXSERVER
+ throw new NotImplementedException();
+#endif
+ m_nuiCallbacks.Remove(callbackName);
+ Native.CoreNatives.RemoveNuiCallback(callbackName);
+ }
+
+ ///
+ /// Registers a NUI callback to the specified
+ ///
+ /// the event that the callback will bind to
+ /// The function to bind the callback to, the callback will be invoked with an ExpandoObject containing the data and a
+#if IS_FXSERVER
+ /// Does nothing on server side
+ [EditorBrowsable(EditorBrowsableState.Never)]
+#endif
+ public static void AddNuiCallback(string callbackName, Delegate delegateFn)
+ {
+#if IS_FXSERVER
+ throw new NotImplementedException();
+#endif
+ Native.CoreNatives.RegisterNuiCallback(callbackName, delegateFn);
+ }
+ ///
+ /// Removes the NUI callback for the specified
+ ///
+ /// the callback event that will be removed
+#if IS_FXSERVER
+ /// Does nothing on server side
+ [EditorBrowsable(EditorBrowsableState.Never)]
+#endif
+ public static void RemoveNuiCallback(string callbackName)
+ {
+#if IS_FXSERVER
+ throw new NotImplementedException();
+#else
+ Native.CoreNatives.RemoveNuiCallback(callbackName);
+#endif
+ }
+
#endregion
#region Script loading
diff --git a/code/client/clrcore-v2/Native/Native.cs b/code/client/clrcore-v2/Native/Native.cs
index c9a00f995b..69f4b2d54c 100644
--- a/code/client/clrcore-v2/Native/Native.cs
+++ b/code/client/clrcore-v2/Native/Native.cs
@@ -15,6 +15,8 @@ internal static class CoreNatives
private static UIntPtr s_0x637f4c75;
private static UIntPtr s_0x8d50e33a;
private static UIntPtr s_0x91310870;
+ private static UIntPtr s_registerNuiCallback; // 0xc59b980c
+ private static UIntPtr s_unregisterRawNuiCallback; // 0x7fb46432
#if IS_FXSERVER
private static UIntPtr s_0x2f7a49e6;
private static UIntPtr s_0x70b35890;
@@ -34,12 +36,23 @@ internal static unsafe void RegisterResourceAsEventHandler(CString eventName)
}
[SecuritySafeCritical]
- internal static unsafe void RegisterCommand(CString commandName, InFunc handler, bool restricted)
+ internal static unsafe void RegisterNuiCallback(CString callbackName, InFunc handler)
{
- fixed (byte* p_commandName = commandName?.value, p_handler = &handler.value[0])
+ fixed (byte* p_callbackType = callbackName?.value, p_handler = &handler.value[0])
{
- ulong* __data = stackalloc ulong[] { (ulong)p_commandName, (ulong)p_handler, N64.Val(restricted) };
- ScriptContext.InvokeNative(ref s_0x5fa79b0f, 0x5fa79b0f, __data, 3); // REGISTER_COMMAND
+ ulong* __data = stackalloc ulong[] { (ulong)p_callbackType, (ulong)p_handler };
+ ScriptContext.InvokeNative(ref s_registerNuiCallback, 0xc59b980c, __data, 2); // REGISTER_NUI_CALLBACK
+ }
+ }
+
+
+ [SecuritySafeCritical]
+ internal static unsafe void RemoveNuiCallback(CString callbackName)
+ {
+ fixed (byte* p_callbackType = callbackName?.value)
+ {
+ ulong* __data = stackalloc ulong[] { (ulong)p_callbackType };
+ ScriptContext.InvokeNative(ref s_unregisterRawNuiCallback, 0x7fb46432, __data, 1); // UNREGISTER_RAW_NUI_CALLBACK
}
}
@@ -55,6 +68,16 @@ public static unsafe void RegisterKeyMapping(CString commandString, CString desc
ScriptContext.InvokeNative(ref s_0xd7664fd1, 0xd7664fd1, __data, 4);
}
}
+
+ [SecuritySafeCritical]
+ internal static unsafe void RegisterCommand(CString commandName, InFunc handler, bool restricted)
+ {
+ fixed (byte* p_commandName = commandName?.value, p_handler = &handler.value[0])
+ {
+ ulong* __data = stackalloc ulong[] { (ulong)p_commandName, (ulong)p_handler, N64.Val(restricted) };
+ ScriptContext.InvokeNative(ref s_0x5fa79b0f, 0x5fa79b0f, __data, 3); // REGISTER_COMMAND
+ }
+ }
[SecuritySafeCritical]
internal static unsafe object GetStateBagValue(CString bagName, CString key)