From efda5ec2652bb792826b946eee14e883de3a3f26 Mon Sep 17 00:00:00 2001 From: Timothy Schenk Date: Thu, 29 Dec 2022 11:23:24 +0100 Subject: [PATCH] Implement base level packet interface --- Server.Packets/IPacket.cs | 7 ++++ Server.Packets/PacketForwardingService.cs | 40 +++++++++++++++++++++++ Server.Packets/PacketId.cs | 6 ++++ Server.Packets/PacketIdAttribute.cs | 12 +++++++ 4 files changed, 65 insertions(+) create mode 100644 Server.Packets/IPacket.cs create mode 100644 Server.Packets/PacketForwardingService.cs create mode 100644 Server.Packets/PacketId.cs create mode 100644 Server.Packets/PacketIdAttribute.cs diff --git a/Server.Packets/IPacket.cs b/Server.Packets/IPacket.cs new file mode 100644 index 0000000..e424a16 --- /dev/null +++ b/Server.Packets/IPacket.cs @@ -0,0 +1,7 @@ +namespace Server.Packets; + +public interface IPacket +{ + Span Serialize(); + void Deserialize(Span bytes); +} \ No newline at end of file diff --git a/Server.Packets/PacketForwardingService.cs b/Server.Packets/PacketForwardingService.cs new file mode 100644 index 0000000..794af3e --- /dev/null +++ b/Server.Packets/PacketForwardingService.cs @@ -0,0 +1,40 @@ +using System.Collections.Immutable; +using System.Reflection; + +namespace Server.Packets; + +public class PacketForwardingService +{ + private ImmutableDictionary _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(), 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 bytes) + { + // Get constructor according to packet id + IPacket packet = _packets[GetPacketId(bytes)].Invoke(Array.Empty()) as IPacket ?? + throw new InvalidOperationException(); + // Slice off packet id + packet.Deserialize(bytes.Slice(2)); + return packet; + } + + private PacketId GetPacketId(Span bytes) + { + PacketId id = 0; + id = (PacketId)BitConverter.ToUInt16(new[] { bytes[0], bytes[1] }); + return id; + } +} \ No newline at end of file diff --git a/Server.Packets/PacketId.cs b/Server.Packets/PacketId.cs new file mode 100644 index 0000000..b6263a0 --- /dev/null +++ b/Server.Packets/PacketId.cs @@ -0,0 +1,6 @@ +namespace Server.Packets; + +public enum PacketId : ushort +{ + +} \ No newline at end of file diff --git a/Server.Packets/PacketIdAttribute.cs b/Server.Packets/PacketIdAttribute.cs new file mode 100644 index 0000000..37c8eb5 --- /dev/null +++ b/Server.Packets/PacketIdAttribute.cs @@ -0,0 +1,12 @@ +namespace Server.Packets; +[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] +[JetBrains.Annotations.BaseTypeRequiredAttribute(typeof(IPacket))] +public class PacketIdAttribute : Attribute +{ + public PacketIdAttribute(PacketId packetId) + { + PacketId = packetId; + } + + public PacketId PacketId { get; private set; } +} \ No newline at end of file