feat: engine data type packers
This commit is contained in:
133
Shared/Network/LiteNetLib/LiteNetLibCommunicatorBase.cs
Normal file
133
Shared/Network/LiteNetLib/LiteNetLibCommunicatorBase.cs
Normal file
@@ -0,0 +1,133 @@
|
||||
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 LiteNetLibCommunicatorBase : UniverseObject, INetworkCommunicator
|
||||
{
|
||||
protected readonly NetPacketProcessor netPacketProcessor = new();
|
||||
|
||||
private readonly Dictionary<Type, List<Delegate>> listeners = [];
|
||||
|
||||
public EventBasedNetListener Listener { get; private set; } = null!;
|
||||
public NetManager Manager { get; private set; } = null!;
|
||||
|
||||
public INetworkCommunicator Stop()
|
||||
{
|
||||
Manager.Stop();
|
||||
return this;
|
||||
}
|
||||
|
||||
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();
|
||||
protected virtual void OnPacketArrived<T>(T packet, NetPeer peer) where T : INetworkPacket
|
||||
{
|
||||
if (!listeners.TryGetValue(typeof(T), out List<Delegate>? delegates))
|
||||
return;
|
||||
|
||||
foreach (Delegate @delegate in delegates)
|
||||
@delegate.InvokeSafe(packet);
|
||||
}
|
||||
|
||||
private void NetworkReceiveEvent(NetPeer peer, NetPacketReader reader, byte channel, DeliveryMethod deliveryMethod)
|
||||
{
|
||||
try { netPacketProcessor.ReadAllPackets(reader, peer); }
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void SetupPackets()
|
||||
{
|
||||
// Find network packets implementing INetworkPacket
|
||||
IEnumerable<Type> packetTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes())
|
||||
.Where(t => typeof(INetworkPacket).IsAssignableFrom(t) && !t.IsInterface);
|
||||
|
||||
MethodInfo subscribeReusableMethod = typeof(NetPacketProcessor)
|
||||
.GetMethods()
|
||||
.FirstOrDefault(m => m.Name == nameof(NetPacketProcessor.SubscribeReusable) &&
|
||||
m.GetParameters().Length == 1 &&
|
||||
m.GetParameters()[0].ParameterType.GetGenericTypeDefinition() == typeof(Action<,>)
|
||||
)!;
|
||||
|
||||
MethodInfo onPacketArrivedMethod = typeof(LiteNetLibCommunicatorBase)
|
||||
.GetMethod(nameof(OnPacketArrived), BindingFlags.NonPublic | BindingFlags.Instance)!;
|
||||
|
||||
// Register all network packets by calling the method bellow where T is our found network packet type
|
||||
// NetPacketProcessor.SubscribeReusable<T, NetPeer>(Action<T, NetPeer> onReceive)
|
||||
foreach (var packetType in packetTypes)
|
||||
{
|
||||
var genericOnPacketArrivedMethod = onPacketArrivedMethod.MakeGenericMethod(packetType);
|
||||
|
||||
var delegateType = typeof(Action<,>).MakeGenericType(packetType, typeof(NetPeer));
|
||||
var delegateHandler = Delegate.CreateDelegate(delegateType, this, genericOnPacketArrivedMethod);
|
||||
|
||||
var genericSubscribeReusableMethod = subscribeReusableMethod.MakeGenericMethod(packetType, typeof(NetPeer));
|
||||
genericSubscribeReusableMethod.Invoke(netPacketProcessor, [delegateHandler]);
|
||||
}
|
||||
}
|
||||
|
||||
public LiteNetLibCommunicatorBase()
|
||||
{
|
||||
Listener = new EventBasedNetListener();
|
||||
Manager = new NetManager(Listener);
|
||||
|
||||
Listener.NetworkReceiveEvent += NetworkReceiveEvent;
|
||||
|
||||
SetupEnginePackets();
|
||||
SetupPackets();
|
||||
}
|
||||
|
||||
private void SetupEnginePackets()
|
||||
{
|
||||
// I know, ugly af. I need to find a better way
|
||||
netPacketProcessor.RegisterNestedType(AABBNetPacker.Write, AABBNetPacker.Read);
|
||||
netPacketProcessor.RegisterNestedType(CircleNetPacker.Write, CircleNetPacker.Read);
|
||||
netPacketProcessor.RegisterNestedType(ColorHSVNetPacker.Write, ColorHSVNetPacker.Read);
|
||||
netPacketProcessor.RegisterNestedType(ColorRGBANetPacker.Write, ColorRGBANetPacker.Read);
|
||||
netPacketProcessor.RegisterNestedType(ColorRGBNetPacker.Write, ColorRGBNetPacker.Read);
|
||||
netPacketProcessor.RegisterNestedType(Line2DEquationNetPacker.Write, Line2DEquationNetPacker.Read);
|
||||
netPacketProcessor.RegisterNestedType(Line2DNetPacker.Write, Line2DNetPacker.Read);
|
||||
netPacketProcessor.RegisterNestedType(Projection1DNetPacker.Write, Projection1DNetPacker.Read);
|
||||
netPacketProcessor.RegisterNestedType(QuaternionNetPacker.Write, QuaternionNetPacker.Read);
|
||||
netPacketProcessor.RegisterNestedType(Shape2DNetPacker.Write, Shape2DNetPacker.Read);
|
||||
netPacketProcessor.RegisterNestedType(TriangleNetPacker.Write, TriangleNetPacker.Read);
|
||||
netPacketProcessor.RegisterNestedType(Vector2DNetPacker.Write, Vector2DNetPacker.Read);
|
||||
netPacketProcessor.RegisterNestedType(Vector3DNetPacker.Write, Vector3DNetPacker.Read);
|
||||
}
|
||||
|
||||
public void SubscribeToPackets<T>(Action<T> callback)
|
||||
{
|
||||
if (!listeners.TryGetValue(typeof(T), out List<Delegate>? delegates))
|
||||
{
|
||||
delegates = [];
|
||||
listeners.Add(typeof(T), delegates);
|
||||
}
|
||||
|
||||
delegates.Add(callback);
|
||||
}
|
||||
|
||||
public void UnsubscribeFromPackets<T>(Action<T> callback)
|
||||
{
|
||||
if (!listeners.TryGetValue(typeof(T), out List<Delegate>? delegates))
|
||||
return;
|
||||
|
||||
delegates.Remove(callback);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user