using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using LiteNetLib; using LiteNetLib.Utils; using Syntriax.Engine.Core; using Syntriax.Engine.Network.Abstract; namespace Syntriax.Engine.Network; public abstract class NetworkBase : BehaviourOverride, INetworkCommunicator { public event INetworkCommunicator.OnPacketReceivedDelegate? OnPacketReceived = null; protected readonly NetPacketProcessor netPacketProcessor = new(); protected readonly Dictionary networkEntities = []; protected BehaviourCollector networkEntityCollector = null!; public EventBasedNetListener Listener { get; private set; } = null!; public NetManager Manager { get; private set; } = null!; public NetworkBase() { Priority = 10; Listener = new EventBasedNetListener(); Manager = new NetManager(Listener); Listener.NetworkReceiveEvent += NetworkReceiveEvent; netPacketProcessor.RegisterNestedType(); RegisterPackets(); } public void RegisterPackets() { var packetTypes = Assembly.GetExecutingAssembly().GetTypes() .Where(t => typeof(INetworkPacket).IsAssignableFrom(t) && !t.IsInterface) .ToList(); // MethodInfo subscribeMethod = netPacketProcessor.GetType() // .GetMethod(nameof(NetPacketProcessor.SubscribeReusable), [typeof(Action<,>)]); MethodInfo[] subscribeMethods = netPacketProcessor.GetType() .GetMethods() .Where(m => m.Name == nameof(NetPacketProcessor.SubscribeReusable)) .ToArray(); MethodInfo subscribeMethod = subscribeMethods .FirstOrDefault(m => m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType.GetGenericTypeDefinition() == typeof(Action<,>)); MethodInfo[] methodInfos = typeof(NetworkBase) .GetMethods(BindingFlags.NonPublic | BindingFlags.Instance); MethodInfo method = methodInfos .FirstOrDefault(m => m.Name == "OnPacketArrived" && m.IsGenericMethod); // .GetMethod(nameof(OnPacketArrived), BindingFlags.NonPublic | BindingFlags.Instance) ?? throw new Exception(); foreach (var packetType in packetTypes) { var networkPacketType = typeof(NetworkPacket<>).MakeGenericType(packetType); MethodInfo genericSubscribe = subscribeMethod.MakeGenericMethod(networkPacketType, typeof(NetPeer)); Action handler = (packet, peer) => { method = method.MakeGenericMethod(packetType); method.Invoke(this, [packet, peer]); }; genericSubscribe.Invoke(netPacketProcessor, [handler]); } } // private void RegisterPackets() // { // IEnumerable packetTypes = Assembly.GetExecutingAssembly().GetTypes().Where( // t => t.GetInterfaces().Contains(typeof(INetworkPacket)) // ); // MethodInfo subscribeMethod = netPacketProcessor.GetType() // .GetMethod(nameof(NetPacketProcessor.SubscribeReusable), [typeof(Action<,>)]) ?? throw new Exception(); // foreach (var packetType in packetTypes) // { // MethodInfo genericSubscribe = subscribeMethod.MakeGenericMethod(packetType, typeof(NetPeer)); // Action handler = (packet, peer) => // { // MethodInfo method = GetType() // .GetMethod(nameof(OnPacketArrived), BindingFlags.NonPublic | BindingFlags.Instance) ?? throw new Exception(); // method = method.MakeGenericMethod(packetType.GetGenericArguments()[0]); // method.Invoke(this, [packet, peer]); // }; // genericSubscribe.Invoke(netPacketProcessor, [handler]); // } // } private void OnPacketArrived(NetworkPacket packet, NetPeer peer) where T : INetworkPacket//OnPacketArrived(NetworkPacket packet, NetPeer peer) { // Handle packet Console.WriteLine($"Packet of type {typeof(T)} arrived with data: {packet.Data}"); if (networkEntities.TryGetValue(packet.NetworkId, out INetworkEntity? entity)) entity.ReceiveData(packet.Data); OnPacketReceived?.Invoke(this, packet); } protected override void OnInitialize() { base.OnInitialize(); networkEntityCollector = new(GameObject.GameManager); networkEntityCollector.OnCollected += OnNetworkEntityCollected; networkEntityCollector.OnRemoved += OnNetworkEntityRemoved; } protected override void OnFinalize() { networkEntityCollector.OnCollected -= OnNetworkEntityCollected; networkEntityCollector.OnRemoved -= OnNetworkEntityRemoved; Stop(); } private void OnNetworkEntityCollected(BehaviourCollector sender, INetworkEntity behaviourCollected) { if (behaviourCollected.NetworkId != 0) networkEntities.Add(behaviourCollected.NetworkId, behaviourCollected); behaviourCollected.OnNetworkIdChanged += OnNetworkIdChanged; } private void OnNetworkIdChanged(INetworkEntity sender, uint previousId) { if (networkEntities.TryGetValue(previousId, out INetworkEntity? networkEntity) && sender == networkEntity) networkEntities.Remove(previousId); networkEntities.Add(sender.NetworkId, sender); } private void OnNetworkEntityRemoved(BehaviourCollector sender, INetworkEntity behaviourRemoved) { networkEntities.Remove(behaviourRemoved.NetworkId); behaviourRemoved.OnNetworkIdChanged -= OnNetworkIdChanged; } private void NetworkReceiveEvent(NetPeer peer, NetPacketReader reader, byte channel, DeliveryMethod deliveryMethod) { netPacketProcessor.ReadAllPackets(reader, peer); } public void PollEvents() => Manager.PollEvents(); public void Stop() => Manager.Stop(); protected override void OnUpdate() => PollEvents(); public abstract void Send(NetworkPacket packet); }