From b83887cb2a52a264b81e11872bf6500f69e824a6 Mon Sep 17 00:00:00 2001 From: "derek.holloway" Date: Mon, 3 Aug 2026 10:57:17 -0700 Subject: [PATCH] Change manual packet numbering to a dictionary --- MistoxServer/Client/TCPClient.cs | 4 +- MistoxServer/Client/UDPReceiver.cs | 4 +- MistoxServer/Server/ServerConnection.cs | 4 +- MistoxServer/mPacket/DataPacket.cs | 12 ++---- .../mPacket/NetworkPacketDictionary.cs | 41 ++++++++++++++----- MistoxServer/mPacket/PacketAttribute.cs | 16 +------- MistoxServer/mPacket/ResevedPackets.cs | 13 ++++-- Todo.txt | 3 ++ 8 files changed, 53 insertions(+), 44 deletions(-) diff --git a/MistoxServer/Client/TCPClient.cs b/MistoxServer/Client/TCPClient.cs index 7259361..110d6fa 100644 --- a/MistoxServer/Client/TCPClient.cs +++ b/MistoxServer/Client/TCPClient.cs @@ -34,8 +34,8 @@ namespace Mistox.Client { // Parse the header DataPacketHeader Header = new DataPacketHeader { - Type = headerBuffer[0], - DataLength = (ushort)((headerBuffer[1] << 8) | headerBuffer[2]) + Type = (ushort)((headerBuffer[0] << 8) | headerBuffer[1]), + DataLength = (ushort)((headerBuffer[2] << 8) | headerBuffer[3]) }; // Make sure the data looks valid diff --git a/MistoxServer/Client/UDPReceiver.cs b/MistoxServer/Client/UDPReceiver.cs index c8b776f..166cd31 100644 --- a/MistoxServer/Client/UDPReceiver.cs +++ b/MistoxServer/Client/UDPReceiver.cs @@ -31,8 +31,8 @@ namespace Mistox.Client { // Create the packet header DataPacketHeader Header = new DataPacketHeader { - Type = dataPacket[0], - DataLength = (ushort)((dataPacket[1] << 8) | dataPacket[2]) + Type = (ushort)((dataPacket[0] << 8) | dataPacket[1]), + DataLength = (ushort)((dataPacket[2] << 8) | dataPacket[3]) }; // Slice out the data part of the packet diff --git a/MistoxServer/Server/ServerConnection.cs b/MistoxServer/Server/ServerConnection.cs index 75fb230..7775be9 100644 --- a/MistoxServer/Server/ServerConnection.cs +++ b/MistoxServer/Server/ServerConnection.cs @@ -43,8 +43,8 @@ namespace Mistox.Server { // Pack the header variables for faster memory passing DataPacketHeader Header = new DataPacketHeader { - Type = headerBuffer[0], - DataLength = (ushort)((headerBuffer[1] << 8) | headerBuffer[2]) + Type = (ushort)((headerBuffer[0] << 8) | headerBuffer[1]), + DataLength = (ushort)((headerBuffer[2] << 8) | headerBuffer[3]) }; // Make sure the data looks valid diff --git a/MistoxServer/mPacket/DataPacket.cs b/MistoxServer/mPacket/DataPacket.cs index 59baed0..e4034c9 100644 --- a/MistoxServer/mPacket/DataPacket.cs +++ b/MistoxServer/mPacket/DataPacket.cs @@ -10,7 +10,7 @@ namespace Mistox { [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct DataPacketHeader { - public byte Type { get; set; } + public ushort Type { get; set; } public ushort DataLength { get; set; } } @@ -24,12 +24,6 @@ namespace Mistox { // Helper classes public static byte[] Serialize( T Object ) { - - // Get the attribute ID - mPacket attribute = typeof(T).GetCustomAttribute(false); - if (attribute == null) { - throw new Exception($"The datastructure {typeof(T).Name} is not an mPacket"); - } // Use an expandable buffer writer from the system stack var writer = new ArrayBufferWriter(256); @@ -42,7 +36,7 @@ namespace Mistox { // Build our header struct on the stack DataPacketHeader header = new DataPacketHeader { - Type = attribute.ID, + Type = NetworkPacketDictionary.PacketIDTable[typeof(T)], DataLength = (ushort)(writer.WrittenCount - HeaderLength) }; @@ -59,7 +53,7 @@ namespace Mistox { public static object Deserialize( DataPacketHeader Header, ReadOnlyMemory Data ) { // Get the type from the tag - if (!NetworkPacketDictionary.ServerToClientPackets.TryGetValue(Header.Type, out Type resolvedType)) { + if (!NetworkPacketDictionary.PacketLookupTable.TryGetValue(Header.Type, out Type resolvedType)) { throw new Exception($"Unknown packet type ID: {Header.Type}"); } diff --git a/MistoxServer/mPacket/NetworkPacketDictionary.cs b/MistoxServer/mPacket/NetworkPacketDictionary.cs index b7c8efe..cac32f2 100644 --- a/MistoxServer/mPacket/NetworkPacketDictionary.cs +++ b/MistoxServer/mPacket/NetworkPacketDictionary.cs @@ -7,17 +7,38 @@ namespace Mistox.Attributes { public class NetworkPacketDictionary { // Fills out the NetworkPacket Lookup Dictionary - public static readonly Dictionary ClientToClientPackets = new(); - public static readonly Dictionary ServerToClientPackets = new(); + public static readonly Dictionary PacketLookupTable = new(); + public static readonly Dictionary PacketIDTable = new(); + + // Have a way to assign a number to the packet that will run the same ever time + static ushort GetDeterministicHashCode(string str) { + unchecked { + uint hash = 2166136261; + foreach (char c in str) { + hash = (hash ^ c) * 16777619; + } + return (ushort)(hash % 0xFFFF); + } + } + + // Map all packets to a number [ Error on packet collisions ] public static void BuildNetworkPacketList() { - Type[] allClasses = Assembly.GetExecutingAssembly().GetTypes(); - foreach( Type cur in allClasses) { - mPacket attribute = cur.GetCustomAttribute(false); - if (attribute != null) { - if ( attribute.PacketUse.HasFlag(PacketUsage.ClientToClient) ) { - ClientToClientPackets[attribute.ID] = cur; - } else if ( attribute.PacketUse.HasFlag(PacketUsage.ClientToServer) ) { - ServerToClientPackets[attribute.ID] = cur; + Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); + foreach (Assembly assembly in assemblies) { + Type[] allClasses = assembly.GetTypes(); + foreach( Type cur in allClasses) { + mPacket attribute = cur.GetCustomAttribute(false); + if (attribute != null) { + + // Generate a deterministic 16-bit ID based on the Type's FullName + string identifier = cur.FullName ?? cur.Name; + ushort packetId = GetDeterministicHashCode(identifier); + + if (PacketLookupTable.ContainsKey(packetId)) { + throw new Exception($"CRITICAL: Duplicate Packet ID detected! ID {packetId} is used by both {PacketLookupTable[packetId].Name} and {cur.Name}"); + } + PacketLookupTable[packetId] = cur; + PacketIDTable[cur] = packetId; } } } diff --git a/MistoxServer/mPacket/PacketAttribute.cs b/MistoxServer/mPacket/PacketAttribute.cs index 853fc0a..6bcd634 100644 --- a/MistoxServer/mPacket/PacketAttribute.cs +++ b/MistoxServer/mPacket/PacketAttribute.cs @@ -4,21 +4,7 @@ namespace Mistox.Attributes { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false, AllowMultiple = false)] public sealed class mPacket : Attribute { - public byte ID { get; } - public PacketUsage PacketUse { get; } - public mPacket(byte id) { - ID = id; - PacketUse = PacketUsage.ClientToClient | PacketUsage.ClientToServer; - } - public mPacket(byte id, PacketUsage packetUse) { - ID = id; - PacketUse = packetUse; - } - } - - public enum PacketUsage { - ClientToClient = 0x01, - ClientToServer = 0x10, + public mPacket() {} } } \ No newline at end of file diff --git a/MistoxServer/mPacket/ResevedPackets.cs b/MistoxServer/mPacket/ResevedPackets.cs index 7ff7d5a..931c862 100644 --- a/MistoxServer/mPacket/ResevedPackets.cs +++ b/MistoxServer/mPacket/ResevedPackets.cs @@ -4,27 +4,32 @@ using Mistox.Attributes; namespace Mistox.ResevedPackets { - [mPacket(0xFF)] + [mPacket] public class UserConnectedPacket { public string UserName { get; set; } public IPAddress ClientIPAddress { get; set; } public int ClientPort { get; set; } } - [mPacket(0xFE)] + [mPacket] public class UserAuthPacket { public string UserName { get; set; } = ""; public string ConnectionKey { get; set; } = ""; public int AuthSuccessful { get; set; } = 0; // 0 is standard, -1 is auth failure, 1 is auth success } - [mPacket(0xFD)] + [mPacket] public class EntityPacket { + + // Tag to make sure the object on the other side is the same object i want to update here + // Need to map these Object ID's to a dictionary to make sure I only send network updates when there is a change public ushort ObjectId { get; set; } + + // Packet payload data that im matching for in the dictionary public byte[] InnerPayload { get; set; } } - [mPacket(0xFC)] + [mPacket] public class UserDisconnectedPacket { public string UserName { get; set; } } diff --git a/Todo.txt b/Todo.txt index 3bf1a06..1f1ab0b 100644 --- a/Todo.txt +++ b/Todo.txt @@ -25,6 +25,9 @@ when the server connection closes Use the Server TCP connection to notify all clients when a user disconnects +Only send updates across the network. Dont send same state events +Need to setup a network buffer for Tagged Objects. ID + Connection Flow: 1. Connection to server is made working