diff --git a/FxEvents/FxEvents.Client/EventDispatcher.cs b/FxEvents/FxEvents.Client/EventDispatcher.cs index f8e0e2b..e4b4595 100644 --- a/FxEvents/FxEvents.Client/EventDispatcher.cs +++ b/FxEvents/FxEvents.Client/EventDispatcher.cs @@ -1,5 +1,5 @@ global using CitizenFX.Core; -using CitizenFX.FiveM.Native; +using CitizenFX.Shared.Native; using FxEvents.EventSystem; using FxEvents.Shared; using Logger; @@ -19,7 +19,7 @@ public EventDispatcher() { Logger = new Log(); Instance = this; - string debugMode = Natives.GetResourceMetadata(Natives.GetCurrentResourceName(), "fxevents_debug_mode", 0); + string debugMode = Natives.GetResourceMetadata((CString)Natives.GetCurrentResourceName(), "fxevents_debug_mode", 0); Debug = debugMode == "yes" || debugMode == "true" || Convert.ToInt32(debugMode) > 0; } @@ -71,14 +71,14 @@ public static void Initalize(string inboundEvent, string outboundEvent, string s } /// - /// registra un evento client (TriggerEvent) + /// Register an Event (TriggerEvent) /// - /// Nome evento - /// Azione legata all'evento - internal async void AddEventHandler(string eventName, Delegate action) + /// Event Name + /// Event-related action + internal async void AddEventHandler(string eventName, DynFunc action) { while (!Initialized) await BaseScript.Delay(0); - EventHandlers[eventName].Add(Func.Create(action)); + EventHandlers[eventName].Add(action, Binding.All); } public static void Send(string endpoint, params object[] args) @@ -99,7 +99,7 @@ public static async Coroutine Get(string endpoint, params object[] args) } return await Events.Get(endpoint, args); } - public static void Mount(string endpoint, Delegate @delegate) + public static void Mount(string endpoint, DynFunc @delegate) { if (!Initialized) { diff --git a/FxEvents/FxEvents.Client/EventSystem/ClientGateway.cs b/FxEvents/FxEvents.Client/EventSystem/ClientGateway.cs index b99f85c..cd652d0 100644 --- a/FxEvents/FxEvents.Client/EventSystem/ClientGateway.cs +++ b/FxEvents/FxEvents.Client/EventSystem/ClientGateway.cs @@ -25,19 +25,9 @@ public ClientGateway() internal void AddEvents() { - EventDispatcher.Instance.AddEventHandler(InboundPipeline, new Action(async serialized => - { - try - { - await ProcessInboundAsync(new ServerId().Handle, serialized); - } - catch (Exception ex) - { - Logger.Error("InboundPipeline:" + ex.ToString()); - } - })); + EventDispatcher.Instance.AddEventHandler(InboundPipeline, Func.Create(OnInboundPipelineHandler)); - EventDispatcher.Instance.AddEventHandler(OutboundPipeline, new Action(serialized => + EventDispatcher.Instance.AddEventHandler(OutboundPipeline, Func.Create(serialized => { try { @@ -49,16 +39,28 @@ internal void AddEvents() } })); - EventDispatcher.Instance.AddEventHandler(SignaturePipeline, new Action(signature => _signature = signature)); + EventDispatcher.Instance.AddEventHandler(SignaturePipeline, Func.Create(signature => _signature = signature)); Events.TriggerServerEvent(SignaturePipeline); } + private async void OnInboundPipelineHandler([Source] Remote remote, byte[] serialized) + { + try + { + await ProcessInboundAsync(remote, serialized); + } + catch (Exception ex) + { + Logger.Error("InboundPipeline:" + ex.ToString()); + } + } + public async Coroutine PrepareAsync(string pipeline, int source, IMessage message) { if (string.IsNullOrWhiteSpace(_signature)) { StopwatchUtil stopwatch = StopwatchUtil.StartNew(); - while (_signature == null) await BaseScript.Delay(0); + while (_signature == null) await BaseScript.Yield(); if (EventDispatcher.Debug) { Logger.Debug($"[{message}] Halted {stopwatch.Elapsed.TotalMilliseconds}ms due to signature retrieval."); diff --git a/FxEvents/FxEvents.Client/FxEvents.Client.csproj b/FxEvents/FxEvents.Client/FxEvents.Client.csproj index c1c9b3b..408c4e5 100644 --- a/FxEvents/FxEvents.Client/FxEvents.Client.csproj +++ b/FxEvents/FxEvents.Client/FxEvents.Client.csproj @@ -17,10 +17,9 @@ Properties FxEvents.Client FxEvents.Client - v4.5.2 512 true - net452 + net462;net472;net48 latest ..\CompiledLibs\Client FxEvents.Client @@ -35,7 +34,7 @@ False - 1.0.2 + 2.0.0-beta3-monov2 true @@ -54,13 +53,8 @@ - L:\FiveM_gioco\FiveM.app\citizen\clr2\lib\mono\4.5\v2\CitizenFX.Core.dll - - - L:\FiveM_gioco\FiveM.app\citizen\clr2\lib\mono\4.5\v2\CitizenFX.FiveM.dll - - - L:\FiveM_gioco\FiveM.app\citizen\clr2\lib\mono\4.5\v2\Native\CitizenFX.FiveM.Native.dll + ..\dependencies\FiveM\Client\CitizenFX.Core.dll + False ..\FiveMMsgPack\MsgPack.dll diff --git a/FxEvents/FxEvents.Server/EventDispatcher.cs b/FxEvents/FxEvents.Server/EventDispatcher.cs index 79ce2d6..1d81dce 100644 --- a/FxEvents/FxEvents.Server/EventDispatcher.cs +++ b/FxEvents/FxEvents.Server/EventDispatcher.cs @@ -1,5 +1,6 @@ global using CitizenFX.Core; global using CitizenFX.Server.Native; +using CitizenFX.Server; using FxEvents.EventSystem; using FxEvents.Shared; using FxEvents.Shared.EventSubsystem; @@ -25,7 +26,7 @@ public EventDispatcher() GetPlayers = new PlayerList(); Logger = new Log(); Instance = this; - string debugMode = Natives.GetResourceMetadata(Natives.GetCurrentResourceName(), "fxevents_debug_mode", 0); + string debugMode = Natives.GetResourceMetadata((CString)Natives.GetCurrentResourceName(), "fxevents_debug_mode", 0); Debug = debugMode == "yes" || debugMode == "true" || Convert.ToInt32(debugMode) > 0; } @@ -77,14 +78,14 @@ public static void Initalize(string inboundEvent, string outboundEvent, string s } /// - /// registra un evento (TriggerEvent) + /// Register an Event (TriggerEvent) /// - /// Nome evento - /// Azione legata all'evento - internal async void AddEventHandler(string eventName, Delegate action) + /// Event Name + /// Event-related action + internal async void AddEventHandler(string eventName, DynFunc action) { while (!Initialized) await Delay(0); - EventHandlers[eventName].Add(Func.Create(action)); + EventHandlers[eventName].Add(action, Binding.All); } public static void Send(Player player, string endpoint, params object[] args) @@ -141,7 +142,7 @@ public static Coroutine Get(ISource client, string endpoint, params object } return Events.Get(client.Handle, endpoint, args); } - public static void Mount(string endpoint, Delegate @delegate) + public static void Mount(string endpoint, DynFunc @delegate) { if (!Initialized) { diff --git a/FxEvents/FxEvents.Server/EventSystem/ServerGateway.cs b/FxEvents/FxEvents.Server/EventSystem/ServerGateway.cs index 8b6cbdb..c897d88 100644 --- a/FxEvents/FxEvents.Server/EventSystem/ServerGateway.cs +++ b/FxEvents/FxEvents.Server/EventSystem/ServerGateway.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; +using Player = CitizenFX.Server.Player; namespace FxEvents.EventSystem { @@ -27,9 +28,9 @@ public ServerGateway() internal void AddEvents() { - EventDispatcher.Instance.AddEventHandler(SignaturePipeline, new Action(GetSignature)); - EventDispatcher.Instance.AddEventHandler(InboundPipeline, new Action(Inbound)); - EventDispatcher.Instance.AddEventHandler(OutboundPipeline, new Action(Outbound)); + EventDispatcher.Instance.AddEventHandler(SignaturePipeline, Func.Create(GetSignature)); + EventDispatcher.Instance.AddEventHandler(InboundPipeline, Func.Create(Inbound)); + EventDispatcher.Instance.AddEventHandler(OutboundPipeline, Func.Create(Outbound)); } public void Push(string pipeline, int source, byte[] buffer) @@ -40,12 +41,11 @@ public void Push(string pipeline, int source, byte[] buffer) Events.TriggerAllClientsEvent(pipeline, buffer); } - - private void GetSignature(Remote source) + private void GetSignature([Source] Player source) { try { - int client = int.Parse(source.ToString().Substring(7, source.ToString().Length - 1)); + int client = source.Handle; if (_signatures.ContainsKey(client)) { @@ -63,7 +63,7 @@ private void GetSignature(Remote source) string signature = BitConverter.ToString(holder).Replace("-", "").ToLower(); _signatures.Add(client, signature); - Events.TriggerClientEvent(SignaturePipeline, EventDispatcher.Instance.GetPlayers[client], signature); + Events.TriggerClientEvent(SignaturePipeline, source, signature); } catch (Exception ex) { @@ -71,13 +71,17 @@ private void GetSignature(Remote source) } } - private async void Inbound(Remote source, byte[] buffer) + private async void Inbound([Source] Remote source, byte[] buffer) { try { - int client = int.Parse(source.ToString().Substring(7, source.ToString().Length - 1)); + int client = ((Player)source).Handle; - if (!_signatures.TryGetValue(client, out string signature)) return; + if (!_signatures.TryGetValue(client, out string signature)) + { + Logger.Error($"Client {(string)Natives.GetPlayerName("" + client)}[{client}] tried sending an event without a signature."); + return; + } using SerializationContext context = new SerializationContext(InboundPipeline, null, Serialization, buffer); @@ -88,7 +92,7 @@ private async void Inbound(Remote source, byte[] buffer) try { - await ProcessInboundAsync(message, client); + await ProcessInboundAsync(message, source); } catch (TimeoutException) { @@ -112,11 +116,11 @@ public bool VerifySignature(int source, IMessage message, string signature) return false; } - private void Outbound(Remote source, byte[] buffer) + private void Outbound([Source] Player source, byte[] buffer) { try { - int client = int.Parse(source.ToString().Substring(7, source.ToString().Length - 1)); + int client = source.Handle; if (!_signatures.TryGetValue(client, out string signature)) return; diff --git a/FxEvents/FxEvents.Server/FxEvents.Server.csproj b/FxEvents/FxEvents.Server/FxEvents.Server.csproj index f076108..a863ae3 100644 --- a/FxEvents/FxEvents.Server/FxEvents.Server.csproj +++ b/FxEvents/FxEvents.Server/FxEvents.Server.csproj @@ -2,7 +2,7 @@ FxEvents Server - FxEvents an advanced event subsystem for FiveM C# Resources. + FxEvents an advanced event subsystem for CFX C# Resources. LICENSE.txt README.md FxEvents.Server @@ -19,7 +19,7 @@ Debug;Release False False - 1.0.2 + 2.0.0-beta3-monov2 @@ -41,10 +41,12 @@ - L:\FiveM\ManuGamemode\citizen\clr2\lib\mono\4.5\v2\CitizenFX.Core.dll + ..\dependencies\FiveM\Server\CitizenFX.Core.dll + False - L:\FiveM\ManuGamemode\citizen\clr2\lib\mono\4.5\v2\CitizenFX.Server.dll + ..\dependencies\FiveM\Server\CitizenFX.Server.dll + False ..\FiveMMsgPack\MsgPack.dll diff --git a/FxEvents/Shared/EventSubsystem/BaseGateway.cs b/FxEvents/Shared/EventSubsystem/BaseGateway.cs index 022a7c8..730a095 100644 --- a/FxEvents/Shared/EventSubsystem/BaseGateway.cs +++ b/FxEvents/Shared/EventSubsystem/BaseGateway.cs @@ -13,10 +13,10 @@ using System.Threading; using System.Threading.Tasks; #if SERVER -using CitizenFX.Server.Native; -using CitizenFX.Server; +using Player = CitizenFX.Server.Player; #elif CLIENT -using CitizenFX.FiveM.Native; +using CitizenFX.Shared.Native; +using Player = CitizenFX.Shared.Player; #endif namespace FxEvents.Shared.EventSubsystem @@ -42,7 +42,7 @@ public abstract class BaseGateway public EventMessagePreparation? PrepareDelegate { get; set; } public EventMessagePush? PushDelegate { get; set; } - public async Coroutine ProcessInboundAsync(int source, byte[] serialized) + public async Coroutine ProcessInboundAsync(Remote? source, byte[] serialized) { using SerializationContext context = new SerializationContext(InboundPipeline, "(Process) In", Serialization, serialized); EventMessage message = context.Deserialize(); @@ -50,12 +50,12 @@ public async Coroutine ProcessInboundAsync(int source, byte[] serialized) await ProcessInboundAsync(message, source); } - public async Coroutine ProcessInboundAsync(EventMessage message, int source) + public async Coroutine ProcessInboundAsync(EventMessage message, Remote? source) { object InvokeDelegate(EventHandler subscription) { List parameters = new List(); - Delegate @delegate = subscription.Delegate; + DynFunc @delegate = subscription.Delegate; MethodInfo method = @delegate.Method; bool takesSource = method.GetParameters().FirstOrDefault(self => self.GetType() == typeof(Remote) || #if SERVER @@ -66,7 +66,8 @@ object InvokeDelegate(EventHandler subscription) object CallInternalDelegate() { - return @delegate.DynamicInvoke(parameters.ToArray()); + object[] objectArray = new object[parameters.Count]; + return @delegate.DynamicInvoke(source, objectArray); } #if SERVER @@ -75,7 +76,7 @@ object CallInternalDelegate() if (method.GetParameters().Where(self => self.GetType() == typeof(Remote)).Count() > 1) throw new Exception($"{message.Endpoint} cannot have more than 1 \"Remote\" parameter."); if (method.GetParameters().ToList().IndexOf(method.GetParameters().FirstOrDefault(self => self.GetType() == typeof(Remote))) != 0) - throw new Exception($"{message.Endpoint} \"FromSource\" attribute can ONLY be applied to first parameter."); + throw new Exception($"{message.Endpoint} \"Source\" attribute can ONLY be applied to first parameter."); ParameterInfo param = method.GetParameters().FirstOrDefault(self => typeof(ISource).IsAssignableFrom(self.ParameterType) || typeof(Remote).IsAssignableFrom(self.ParameterType) || @@ -105,14 +106,14 @@ object CallInternalDelegate() ConstructorCustomActivator activator = (ConstructorCustomActivator)Expression .Lambda(typeof(ConstructorCustomActivator), expression, parameter).Compile(); - ISource objectInstance = activator.Invoke(source); + ISource objectInstance = activator.Invoke(((Player)source).Handle); parameters.Add(objectInstance); } } else if (typeof(Player).IsAssignableFrom(type)) { - parameters.Add(EventDispatcher.Instance.GetPlayers[source]); + parameters.Add((Player)source); } else if (typeof(string).IsAssignableFrom(type)) { @@ -124,6 +125,7 @@ object CallInternalDelegate() } } #endif + if (message.Parameters == null) { return CallInternalDelegate(); @@ -146,7 +148,17 @@ object CallInternalDelegate() parameters.AddRange(holder.ToArray()); - return @delegate.DynamicInvoke(parameters.ToArray()); + foreach (var p in holder) + { + Logger.Info($"Parameter: {p}"); + Logger.Info($"Parameter: {p.GetType()}"); + } + + if (holder.Count == 0) + return CallInternalDelegate(); + + + return @delegate.DynamicInvoke(source, holder.ToArray()); } if (message.Flow == EventFlowType.Circular) @@ -154,22 +166,31 @@ object CallInternalDelegate() StopwatchUtil stopwatch = StopwatchUtil.StartNew(); EventHandler subscription = _handlers.SingleOrDefault(self => self.Endpoint == message.Endpoint) ?? throw new Exception($"Could not find a handler for endpoint '{message.Endpoint}'"); - object result = InvokeDelegate(subscription); + object result = null; + try + { + result = InvokeDelegate(subscription); + } + catch (Exception ex) + { + Logger.Error($"InvokeDelegate Exception:\n{ex}"); + } - if (result.GetType().GetGenericTypeDefinition() == typeof(Task<>)) + if (result.GetType().GetGenericTypeDefinition() == typeof(Coroutine<>)) { using CancellationTokenSource token = new CancellationTokenSource(); Coroutine task = (Coroutine)result; Coroutine timeout = DelayDelegate!(10000); + + await task; // await the Coroutine task, once its completed then we can use IsCompleted to check if it was cancelled or not + bool completed = task.IsCompleted; if (completed) { token.Cancel(); - await task; - result = ((dynamic)task).Result; } else @@ -197,7 +218,12 @@ object CallInternalDelegate() { stopwatch.Stop(); - await PrepareDelegate(response.Endpoint, source, response); +#if SERVER + await PrepareDelegate(response.Endpoint, ((Player)source).Handle, response); +#else + await PrepareDelegate(response.Endpoint, new ServerId().Handle, response); +#endif + stopwatch.Start(); } @@ -207,7 +233,12 @@ object CallInternalDelegate() byte[] data = context.GetData(); - PushDelegate(OutboundPipeline, source, data); +#if SERVER + PushDelegate(OutboundPipeline, ((Player)source).Handle, data); +#else + PushDelegate(OutboundPipeline, new ServerId().Handle, data); +#endif + if (EventDispatcher.Debug) Logger.Debug($"[{message.Endpoint}] Responded to {source} with {data.Length} byte(s) in {stopwatch.Elapsed.TotalMilliseconds}ms"); } @@ -234,6 +265,10 @@ public void ProcessOutbound(EventResponseMessage response) EventObservable waiting = _queue.SingleOrDefault(self => self.Message.Id == response.Id) ?? throw new Exception($"No request matching {response.Id} was found."); _queue.Remove(waiting); + + if (EventDispatcher.Debug) + Logger.Debug($"[{response.Endpoint}] Received response from {waiting.Message} with {response.Data.Length} byte(s)"); + waiting.Callback.Invoke(response.Data); } @@ -274,7 +309,7 @@ protected async Task SendInternal(EventFlowType flow, int source, { #if CLIENT - Logger.Debug($"[{endpoint} {flow}] Sent {data.Length} byte(s) to {(source == -1 ? "Server" : Natives.GetPlayerName(source))} in {stopwatch.Elapsed.TotalMilliseconds}ms"); + Logger.Debug($"[{endpoint} {flow}] Sent {data.Length} byte(s) to {(source == -1 ? "Server" : ((Player)source).Name)} in {stopwatch.Elapsed.TotalMilliseconds}ms"); #elif SERVER Logger.Debug($"[{endpoint} {flow}] Sent {data.Length} byte(s) to {(source == -1 ? "Server" : Natives.GetPlayerName("" + source))} in {stopwatch.Elapsed.TotalMilliseconds}ms"); #endif @@ -307,7 +342,7 @@ protected async Task GetInternal(int source, string endpoint, params objec if (EventDispatcher.Debug) { #if CLIENT - Logger.Debug($"[{message.Endpoint} {EventFlowType.Circular}] Received response from {(source == -1 ? "Server" : Natives.GetPlayerName(source))} of {holder.Data.Length} byte(s) in {elapsed}ms"); + Logger.Debug($"[{message.Endpoint} {EventFlowType.Circular}] Received response from {(source == -1 ? "Server" : ((Player)source).Name)} of {holder.Data.Length} byte(s) in {elapsed}ms"); #elif SERVER Logger.Debug($"[{message.Endpoint} {EventFlowType.Circular}] Received response from {(source == -1 ? "Server" : Natives.GetPlayerName("" + source))} of {holder.Data.Length} byte(s) in {elapsed}ms"); #endif @@ -315,7 +350,7 @@ protected async Task GetInternal(int source, string endpoint, params objec return holder.Value; } - public void Mount(string endpoint, Delegate @delegate) + public void Mount(string endpoint, DynFunc @delegate) { if (EventDispatcher.Debug) Logger.Debug($"Mounted: {endpoint}"); diff --git a/FxEvents/Shared/EventSubsystem/EventHandler.cs b/FxEvents/Shared/EventSubsystem/EventHandler.cs index eaea561..8ea3b92 100644 --- a/FxEvents/Shared/EventSubsystem/EventHandler.cs +++ b/FxEvents/Shared/EventSubsystem/EventHandler.cs @@ -1,5 +1,4 @@ using FxEvents.Shared.Snowflakes; -using System; namespace FxEvents.Shared.EventSubsystem { @@ -7,9 +6,9 @@ public class EventHandler { public Snowflake Id { get; set; } public string Endpoint { get; set; } - public Delegate Delegate { get; set; } + public DynFunc Delegate { get; set; } - public EventHandler(string endpoint, Delegate @delegate) + public EventHandler(string endpoint, DynFunc @delegate) { Id = Snowflake.Next(); Endpoint = endpoint; diff --git a/FxEvents/Shared/EventSubsystem/Message/EventMessage.cs b/FxEvents/Shared/EventSubsystem/Message/EventMessage.cs index 4523e45..32c7c8a 100644 --- a/FxEvents/Shared/EventSubsystem/Message/EventMessage.cs +++ b/FxEvents/Shared/EventSubsystem/Message/EventMessage.cs @@ -1,10 +1,7 @@ using FxEvents.Shared.EventSubsystem; using FxEvents.Shared.Payload; using FxEvents.Shared.Snowflakes; -using System; using System.Collections.Generic; -using System.IO; -using System.Linq; namespace FxEvents.Shared.Message { diff --git a/FxEvents/Shared/EventSubsystem/Message/EventParameter.cs b/FxEvents/Shared/EventSubsystem/Message/EventParameter.cs index 26aef22..88cf89c 100644 --- a/FxEvents/Shared/EventSubsystem/Message/EventParameter.cs +++ b/FxEvents/Shared/EventSubsystem/Message/EventParameter.cs @@ -1,6 +1,4 @@ -using System.IO; - -namespace FxEvents.Shared.Payload +namespace FxEvents.Shared.Payload { public class EventParameter { diff --git a/FxEvents/Shared/Logger/ILogger.cs b/FxEvents/Shared/Logger/ILogger.cs index 0ab3d87..758b8e9 100644 --- a/FxEvents/Shared/Logger/ILogger.cs +++ b/FxEvents/Shared/Logger/ILogger.cs @@ -1,6 +1,3 @@ -using FxEvents; -using System; - namespace Logger { public interface ILogger diff --git a/FxEvents/Shared/Logger/LoggerColors.cs b/FxEvents/Shared/Logger/LoggerColors.cs index 395bd65..b310c19 100644 --- a/FxEvents/Shared/Logger/LoggerColors.cs +++ b/FxEvents/Shared/Logger/LoggerColors.cs @@ -1,6 +1,3 @@ -using FxEvents; -using System; - namespace Logger { public static class LoggerColors diff --git a/FxEvents/dependencies/FiveM/Client/CitizenFX.Core.dll b/FxEvents/dependencies/FiveM/Client/CitizenFX.Core.dll new file mode 100644 index 0000000..de40ffc Binary files /dev/null and b/FxEvents/dependencies/FiveM/Client/CitizenFX.Core.dll differ diff --git a/FxEvents/dependencies/FiveM/Server/CitizenFX.Core.dll b/FxEvents/dependencies/FiveM/Server/CitizenFX.Core.dll new file mode 100644 index 0000000..7db7e54 Binary files /dev/null and b/FxEvents/dependencies/FiveM/Server/CitizenFX.Core.dll differ diff --git a/FxEvents/dependencies/FiveM/Server/CitizenFX.Server.dll b/FxEvents/dependencies/FiveM/Server/CitizenFX.Server.dll new file mode 100644 index 0000000..438c1a0 Binary files /dev/null and b/FxEvents/dependencies/FiveM/Server/CitizenFX.Server.dll differ