From 8901a5469f538510c18b19a7ef7e15c5197cfda6 Mon Sep 17 00:00:00 2001 From: Syntriax Date: Sat, 31 May 2025 20:25:30 +0300 Subject: [PATCH] perf: improved networking code to use the new events --- Engine | 2 +- Shared/Behaviours/PaddleBehaviour.cs | 2 +- Shared/Behaviours/PongManagerBehaviour.cs | 2 +- .../Network/Abstract/INetworkCommunicator.cs | 6 +-- .../Network/Abstract/IPacketListenerServer.cs | 2 +- .../LiteNetLib/LiteNetLibCommunicatorBase.cs | 25 ++++----- Shared/Network/NetworkManager.cs | 51 +++++++++---------- 7 files changed, 45 insertions(+), 45 deletions(-) diff --git a/Engine b/Engine index 61e2761..86c9ed2 160000 --- a/Engine +++ b/Engine @@ -1 +1 @@ -Subproject commit 61e276158001cac85dc5758546fa839e091c0299 +Subproject commit 86c9ed2ba98e05f21a952b58c49af5954207e006 diff --git a/Shared/Behaviours/PaddleBehaviour.cs b/Shared/Behaviours/PaddleBehaviour.cs index be98468..0b78366 100644 --- a/Shared/Behaviours/PaddleBehaviour.cs +++ b/Shared/Behaviours/PaddleBehaviour.cs @@ -71,7 +71,7 @@ public class PaddleBehaviour(Keys Up, Keys Down, float High, float Low, float Sp rigidBody.Velocity = Vector2D.Zero; } - public void OnServerPacketArrived(PaddleKeyStatePacket packet, string from) + public void OnServerPacketArrived(string sender, PaddleKeyStatePacket packet) { isUpPressed = packet.IsUpPressed; isDownPressed = packet.IsDownPressed; diff --git a/Shared/Behaviours/PongManagerBehaviour.cs b/Shared/Behaviours/PongManagerBehaviour.cs index aa83874..7e4392f 100644 --- a/Shared/Behaviours/PongManagerBehaviour.cs +++ b/Shared/Behaviours/PongManagerBehaviour.cs @@ -89,7 +89,7 @@ public class PongManagerBehaviour : Behaviour, INetworkEntity, return Vector2D.Right.Rotate(isBackwards ? rotation + Syntriax.Engine.Core.Math.PI : rotation); } - void IPacketListenerServer.OnServerPacketArrived(RequestStartPacket packet, string from) + void IPacketListenerServer.OnServerPacketArrived(string sender, RequestStartPacket packet) { if (ball.RigidBody.Velocity.MagnitudeSquared > 0.01f) return; diff --git a/Shared/Network/Abstract/INetworkCommunicator.cs b/Shared/Network/Abstract/INetworkCommunicator.cs index 93e2945..e99ba7b 100644 --- a/Shared/Network/Abstract/INetworkCommunicator.cs +++ b/Shared/Network/Abstract/INetworkCommunicator.cs @@ -1,4 +1,4 @@ -using System; +using Syntriax.Engine.Core; namespace Syntriax.Engine.Network; @@ -6,8 +6,8 @@ public interface INetworkCommunicator { INetworkCommunicator Stop(); - INetworkCommunicator SubscribeToPackets(Action callback); - INetworkCommunicator UnsubscribeFromPackets(Action callback); + INetworkCommunicator SubscribeToPackets(Event.EventHandler callback); + INetworkCommunicator UnsubscribeFromPackets(Event.EventHandler callback); } public interface INetworkCommunicatorClient : INetworkCommunicator diff --git a/Shared/Network/Abstract/IPacketListenerServer.cs b/Shared/Network/Abstract/IPacketListenerServer.cs index e83cbbc..a7cfbb2 100644 --- a/Shared/Network/Abstract/IPacketListenerServer.cs +++ b/Shared/Network/Abstract/IPacketListenerServer.cs @@ -2,5 +2,5 @@ namespace Syntriax.Engine.Network; public interface IPacketListenerServer : INetworkEntity { - void OnServerPacketArrived(T packet, string from); + void OnServerPacketArrived(string sender, T packet); } diff --git a/Shared/Network/LiteNetLib/LiteNetLibCommunicatorBase.cs b/Shared/Network/LiteNetLib/LiteNetLibCommunicatorBase.cs index d70bd41..1625acb 100644 --- a/Shared/Network/LiteNetLib/LiteNetLibCommunicatorBase.cs +++ b/Shared/Network/LiteNetLib/LiteNetLibCommunicatorBase.cs @@ -14,7 +14,7 @@ public abstract class LiteNetLibCommunicatorBase : UniverseObject, INetworkCommu { protected readonly NetPacketProcessor netPacketProcessor = new(); - private readonly Dictionary> listeners = []; + private readonly Dictionary> listeners = []; public EventBasedNetListener Listener { get; private set; } = null!; public NetManager Manager { get; private set; } = null!; @@ -33,11 +33,10 @@ public abstract class LiteNetLibCommunicatorBase : UniverseObject, INetworkCommu protected virtual void OnPacketArrived(T packet, NetPeer peer) where T : INetworkPacket { - if (!listeners.TryGetValue(typeof(T), out List? delegates)) + if (!listeners.TryGetValue(typeof(T), out Event? @event)) return; - foreach (Delegate @delegate in delegates) - @delegate.DynamicInvoke(packet, peer.Id.ToString()); + @event.Invoke(peer.Id.ToString(), packet); } private void NetworkReceiveEvent(NetPeer peer, NetPacketReader reader, byte channel, DeliveryMethod deliveryMethod) @@ -119,26 +118,28 @@ public abstract class LiteNetLibCommunicatorBase : UniverseObject, INetworkCommu netPacketProcessor.RegisterNestedType(Vector3DNetPacker.Write, Vector3DNetPacker.Read); } - public INetworkCommunicator SubscribeToPackets(Action callback) + public INetworkCommunicator SubscribeToPackets(Event.EventHandler callback) { Type type = typeof(T); - if (!listeners.TryGetValue(type, out List? delegates)) + if (!listeners.TryGetValue(type, out Event? @event)) { - delegates = []; - listeners.Add(type, delegates); + @event = new(); + listeners.Add(type, @event); } - delegates.Add(callback); + @event.AddListener(EventDelegateWrapper(callback)); return this; } - public INetworkCommunicator UnsubscribeFromPackets(Action callback) + public INetworkCommunicator UnsubscribeFromPackets(Event.EventHandler callback) { Type type = typeof(T); - if (!listeners.TryGetValue(type, out List? delegates)) + if (!listeners.TryGetValue(type, out Event? @event)) return this; - delegates.Remove(callback); + @event.RemoveListener(EventDelegateWrapper(callback)); return this; } + + private static Event.EventHandler EventDelegateWrapper(Event.EventHandler callback) => (sender, @object) => callback.Invoke(sender, (T)@object); } diff --git a/Shared/Network/NetworkManager.cs b/Shared/Network/NetworkManager.cs index 03a4e8f..912de13 100644 --- a/Shared/Network/NetworkManager.cs +++ b/Shared/Network/NetworkManager.cs @@ -28,8 +28,8 @@ public class NetworkManager : UniverseObject, INetworkManager } } - private readonly Dictionary> clientPacketListeners = []; - private readonly Dictionary> serverPacketListeners = []; + private readonly Dictionary>> clientPacketListeners = []; + private readonly Dictionary>> serverPacketListeners = []; private readonly Dictionary _networkEntities = []; public IReadOnlyDictionary NetworkEntities => _networkEntities; @@ -44,6 +44,7 @@ public class NetworkManager : UniverseObject, INetworkManager _networkEntityCollector.OnCollected.AddListener(OnCollected); _networkEntityCollector.OnRemoved.AddListener(OnRemoved); } + private void CacheDelegates() { // Find network packets implementing INetworkPacket @@ -57,7 +58,7 @@ public class NetworkManager : UniverseObject, INetworkManager { MethodInfo genericOnPacketArrivedMethod = onPacketArrivedMethod.MakeGenericMethod(packetType); - Type genericDelegateType = typeof(Action<,>).MakeGenericType(packetType, typeof(string)); + Type genericDelegateType = typeof(Event<,>.EventHandler).MakeGenericType(typeof(string), packetType); Delegate genericPacketReceivedDelegate = Delegate.CreateDelegate(genericDelegateType, this, genericOnPacketArrivedMethod); delegates.Add((packetType, genericPacketReceivedDelegate)); @@ -90,34 +91,34 @@ public class NetworkManager : UniverseObject, INetworkManager } } - private void OnPacketReceived(T entityDataPacket, string fromClientId) + private void OnPacketReceived(string senderClientId, T entityDataPacket) { Type packetType = typeof(T); if (entityDataPacket is IEntityNetworkPacket entityPacket) { if (networkCommunicator is INetworkCommunicatorClient) - if (clientPacketListeners.TryGetValue(packetType, out Dictionary? clientListeners)) - if (clientListeners.TryGetValue(entityPacket.EntityId, out PacketListenerData clientListenerData)) - clientListenerData.ListenerMethod.Invoke(clientListenerData.Object, [entityDataPacket]); + if (clientPacketListeners.TryGetValue(packetType, out Dictionary>? clientListeners)) + if (clientListeners.TryGetValue(entityPacket.EntityId, out Event? clientListenerData)) + clientListenerData.Invoke(senderClientId, entityDataPacket!); if (networkCommunicator is INetworkCommunicatorServer) - if (serverPacketListeners.TryGetValue(packetType, out Dictionary? serverListeners)) - if (serverListeners.TryGetValue(entityPacket.EntityId, out PacketListenerData serverListenerData)) - serverListenerData.ListenerMethod.Invoke(serverListenerData.Object, [entityDataPacket, fromClientId]); + if (serverPacketListeners.TryGetValue(packetType, out Dictionary>? serverListeners)) + if (serverListeners.TryGetValue(entityPacket.EntityId, out Event? serverListenerData)) + serverListenerData.Invoke(senderClientId, entityDataPacket!); return; } if (networkCommunicator is INetworkCommunicatorClient) - if (clientPacketListeners.TryGetValue(packetType, out Dictionary? clientListeners)) - foreach ((string id, PacketListenerData clientListenerData) in clientListeners) - clientListenerData.ListenerMethod.Invoke(clientListenerData.Object, [entityDataPacket]); + if (clientPacketListeners.TryGetValue(packetType, out Dictionary>? clientListeners)) + foreach ((string id, Event clientListenerData) in clientListeners) + clientListenerData.Invoke(senderClientId, entityDataPacket!); if (networkCommunicator is INetworkCommunicatorServer) - if (serverPacketListeners.TryGetValue(packetType, out Dictionary? serverListeners)) - foreach ((string id, PacketListenerData serverListenerData) in serverListeners) - serverListenerData.ListenerMethod.Invoke(serverListenerData.Object, [entityDataPacket, fromClientId]); + if (serverPacketListeners.TryGetValue(packetType, out Dictionary>? serverListeners)) + foreach ((string id, Event serverListenerData) in serverListeners) + serverListenerData.Invoke(senderClientId, entityDataPacket!); } private void OnCollected(IBehaviourCollector sender, IBehaviourCollector.BehaviourCollectedArguments args) @@ -132,13 +133,15 @@ public class NetworkManager : UniverseObject, INetworkManager Type clientListenerParameterType = clientListenerType.GetGenericArguments().First(); MethodInfo clientListenerReceiveMethod = clientListenerType.GetMethods().First(m => m.Name == nameof(IPacketListenerClient.OnClientPacketArrived)); - if (!clientPacketListeners.TryGetValue(clientListenerParameterType, out Dictionary? clientListeners)) + if (!clientPacketListeners.TryGetValue(clientListenerParameterType, out Dictionary>? clientListeners)) { clientListeners = []; clientPacketListeners.Add(clientListenerParameterType, clientListeners); } - clientListeners.Add(collectedBehaviour.Id, new(collectedBehaviour, clientListenerReceiveMethod)); + Event clientListenerEvent = new(); + clientListenerEvent.AddListener((sender, @object) => clientListenerReceiveMethod.Invoke(collectedBehaviour, [@object])); + clientListeners.Add(collectedBehaviour.Id, clientListenerEvent); } foreach (Type serverListenerType in collectedBehaviour.GetType().GetInterfaces().Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IPacketListenerServer<>))) @@ -146,13 +149,15 @@ public class NetworkManager : UniverseObject, INetworkManager Type serverListenerParameterType = serverListenerType.GetGenericArguments().First(); MethodInfo serverListenerReceiveMethod = serverListenerType.GetMethods().First(m => m.Name == nameof(IPacketListenerServer.OnServerPacketArrived)); - if (!serverPacketListeners.TryGetValue(serverListenerParameterType, out Dictionary? serverListeners)) + if (!serverPacketListeners.TryGetValue(serverListenerParameterType, out Dictionary>? serverListeners)) { serverListeners = []; serverPacketListeners.Add(serverListenerParameterType, serverListeners); } - serverListeners.Add(collectedBehaviour.Id, new(collectedBehaviour, serverListenerReceiveMethod)); + Event serverListenerEvent = new(); + serverListenerEvent.AddListener((sender, @object) => serverListenerReceiveMethod.Invoke(collectedBehaviour, [sender, @object])); + serverListeners.Add(collectedBehaviour.Id, serverListenerEvent); } } @@ -167,10 +172,4 @@ public class NetworkManager : UniverseObject, INetworkManager _networkEntityCollector.Assign(universe); NetworkCommunicator = this.GetRequiredUniverseObjectInParent(); } - - private record struct PacketListenerData(object Object, MethodInfo ListenerMethod) - { - public static implicit operator (object @object, MethodInfo listenerMethod)(PacketListenerData value) => (value.Object, value.ListenerMethod); - public static implicit operator PacketListenerData((object @object, MethodInfo listenerMethod) value) => new(value.@object, value.listenerMethod); - } }