99 lines
3.3 KiB
C#
99 lines
3.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
|
|
using LiteNetLib;
|
|
using LiteNetLib.Utils;
|
|
|
|
using Syntriax.Engine.Core;
|
|
|
|
namespace Syntriax.Engine.Network;
|
|
|
|
public abstract class NetworkBase : UniverseObject, INetworkCommunicator
|
|
{
|
|
public event INetworkCommunicator.OnPacketReceivedDelegate? OnPacketReceived = null;
|
|
|
|
protected readonly NetPacketProcessor netPacketProcessor = new();
|
|
|
|
public EventBasedNetListener Listener { get; private set; } = null!;
|
|
public NetManager Manager { get; private set; } = null!;
|
|
|
|
public void Stop() => Manager.Stop();
|
|
|
|
protected override void OnEnteringUniverse(IUniverse universe)
|
|
{
|
|
universe.OnPreUpdate += PollEvents;
|
|
}
|
|
|
|
protected override void OnExitingUniverse(IUniverse universe)
|
|
{
|
|
universe.OnPreUpdate -= PollEvents;
|
|
|
|
Stop();
|
|
}
|
|
|
|
private void PollEvents(IUniverse sender, UniverseTime engineTime) => Manager.PollEvents();
|
|
|
|
private void OnPacketArrived(INetworkPacket packet, NetPeer peer)
|
|
{
|
|
OnPacketReceived?.Invoke(this, packet, peer.Id.ToString());
|
|
}
|
|
|
|
private void NetworkReceiveEvent(NetPeer peer, NetPacketReader reader, byte channel, DeliveryMethod deliveryMethod)
|
|
{
|
|
try { netPacketProcessor.ReadAllPackets(reader, peer); }
|
|
catch { }
|
|
}
|
|
|
|
private void SetupPackets()
|
|
{
|
|
#region Packet Types Registration
|
|
IEnumerable<Type> packetTypes = Assembly.GetExecutingAssembly().GetTypes()
|
|
.Where(t => typeof(INetworkPacket).IsAssignableFrom(t) && !t.IsInterface);
|
|
|
|
MethodInfo registerPacketTypeMethodInfo = typeof(NetPacketProcessor).GetMethod(nameof(NetPacketProcessor.RegisterNestedType), BindingFlags.Instance)!;
|
|
foreach (Type packetType in packetTypes)
|
|
{
|
|
MethodInfo genericRegisterPacketTypeMethodInfo = registerPacketTypeMethodInfo?.MakeGenericMethod(packetType)!;
|
|
genericRegisterPacketTypeMethodInfo.Invoke(netPacketProcessor, null);
|
|
}
|
|
#endregion
|
|
|
|
#region Deserialization Callback via netPacketProcessor.SubscribeReusable<T> to OnPacketArrived
|
|
MethodInfo subscribeMethod = netPacketProcessor.GetType()
|
|
.GetMethods()
|
|
.Where(m => m.Name == nameof(NetPacketProcessor.SubscribeReusable))
|
|
.FirstOrDefault(m =>
|
|
m.GetParameters().Length == 1 &&
|
|
m.GetParameters()[0].ParameterType.GetGenericTypeDefinition() == typeof(Action<,>)
|
|
)!;
|
|
|
|
MethodInfo packetArrivedMethod = typeof(NetworkBase)
|
|
.GetMethod(nameof(OnPacketArrived), BindingFlags.NonPublic | BindingFlags.Instance)!;
|
|
|
|
foreach (var packetType in packetTypes)
|
|
{
|
|
MethodInfo genericSubscribeMethod = subscribeMethod.MakeGenericMethod(packetType, typeof(NetPeer));
|
|
|
|
Action<object, NetPeer> handler = (packet, peer) =>
|
|
{
|
|
MethodInfo handlerMethod = packetArrivedMethod.MakeGenericMethod(packetType);
|
|
handlerMethod.Invoke(this, [packet, peer]);
|
|
};
|
|
genericSubscribeMethod.Invoke(netPacketProcessor, [handler]);
|
|
}
|
|
#endregion
|
|
}
|
|
|
|
public NetworkBase()
|
|
{
|
|
Listener = new EventBasedNetListener();
|
|
Manager = new NetManager(Listener);
|
|
|
|
Listener.NetworkReceiveEvent += NetworkReceiveEvent;
|
|
|
|
SetupPackets();
|
|
}
|
|
}
|