40 lines
No EOL
1.2 KiB
C#
40 lines
No EOL
1.2 KiB
C#
using System.Collections.Immutable;
|
|
using System.Reflection;
|
|
|
|
namespace Server.Packets;
|
|
|
|
public class PacketForwardingService
|
|
{
|
|
private ImmutableDictionary<PacketId, System.Reflection.ConstructorInfo> _packets = null!;
|
|
|
|
public PacketForwardingService()
|
|
{
|
|
InitializePackets(typeof(IPacket).Assembly);
|
|
}
|
|
|
|
private void InitializePackets(Assembly assembly)
|
|
{
|
|
// Get all types that implement IPacket and have a PacketIdAttribute
|
|
_packets = assembly.GetTypes()
|
|
.Select(x => (attr: x.GetCustomAttribute<PacketIdAttribute>(), ctor: x.GetConstructor(Type.EmptyTypes)))
|
|
.Where(x => x.attr != null && x.ctor != null && x.GetType().IsAssignableFrom(typeof(IPacket)))
|
|
.ToImmutableDictionary(x => x.attr!.PacketId, x => x.ctor)!;
|
|
}
|
|
|
|
public IPacket Dispatch(Span<Byte> bytes)
|
|
{
|
|
// Get constructor according to packet id
|
|
IPacket packet = _packets[GetPacketId(bytes)].Invoke(Array.Empty<object>()) as IPacket ??
|
|
throw new InvalidOperationException();
|
|
// Slice off packet id
|
|
packet.Deserialize(bytes.Slice(2));
|
|
return packet;
|
|
}
|
|
|
|
private PacketId GetPacketId(Span<Byte> bytes)
|
|
{
|
|
PacketId id = 0;
|
|
id = (PacketId)BitConverter.ToUInt16(new[] { bytes[0], bytes[1] });
|
|
return id;
|
|
}
|
|
} |