Engine-Pong/Game/Network/NetworkBase.cs

160 lines
6.1 KiB
C#

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<uint, INetworkEntity> networkEntities = [];
protected BehaviourCollector<INetworkEntity> 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<Pong.Behaviours.PaddleBehaviour.PaddleInputs>();
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<object, NetPeer> handler = (packet, peer) =>
{
method = method.MakeGenericMethod(packetType);
method.Invoke(this, [packet, peer]);
};
genericSubscribe.Invoke(netPacketProcessor, [handler]);
}
}
// private void RegisterPackets()
// {
// IEnumerable<Type> 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<object, NetPeer> 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<T>(NetworkPacket<T> packet, NetPeer peer) where T : INetworkPacket//OnPacketArrived<T>(NetworkPacket<T> 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<INetworkEntity> 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<INetworkEntity> 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<T>(NetworkPacket<T> packet);
}