From f24b98f8e238256585c776253040b9e93f85a2f1 Mon Sep 17 00:00:00 2001 From: Stefano Merotta <97297186+stefanomerotta@users.noreply.github.com> Date: Wed, 15 Jun 2022 21:48:43 +0200 Subject: [PATCH] fix: Replaces throttlers and packet callbacks with function pointers (#1063) Replaces multi-cast delegates with function pointers to gain 25% in performance and lower allocations. --- .../Network/ContainerGridPacketHandler.cs | 5 +- Projects/Server/Network/NetState/NetState.cs | 4 +- Projects/Server/Network/PacketHandler.cs | 14 ++-- .../Network/Packets/IncomingAccountPackets.cs | 28 ++++---- .../Network/Packets/IncomingEntityPackets.cs | 10 +-- .../Packets/IncomingExtendedCommandPackets.cs | 47 +++++++------- .../Network/Packets/IncomingHousePackets.cs | 4 +- .../Network/Packets/IncomingItemPackets.cs | 12 ++-- .../Network/Packets/IncomingMessagePackets.cs | 6 +- .../Network/Packets/IncomingMobilePackets.cs | 10 +-- .../Packets/IncomingMovementPackets.cs | 4 +- .../Server/Network/Packets/IncomingPackets.cs | 5 +- .../Network/Packets/IncomingPlayerPackets.cs | 46 ++++++------- .../Packets/IncomingTargetingPackets.cs | 4 +- .../Network/Packets/IncomingVendorPackets.cs | 6 +- .../Accounting/AccountAttackLimiter.cs | 8 +-- .../UOContent/Engines/Chat/ChatPackets.cs | 6 +- .../Engines/ML Quests/Gumps/RaceChangeGump.cs | 4 +- .../Engines/UltimaStore/UltimaStorePackets.cs | 4 +- Projects/UOContent/Items/Books/BookPackets.cs | 8 +-- .../Bulletin Boards/BulletinBoardPackets.cs | 4 +- .../Items/Games/Mahjong/MahjongPackets.cs | 4 +- .../UOContent/Items/Maps/MapItemPackets.cs | 4 +- Projects/UOContent/Misc/HardwareInfo.cs | 4 +- Projects/UOContent/Misc/PacketThrottles.cs | 8 +-- .../Multis/Houses/HouseFoundation.cs | 4 +- .../UOContent/Network/FreeshardProtocol.cs | 9 ++- Projects/UOContent/Network/MapUO.cs | 15 +++-- .../UOContent/Network/ProtocolExtensions.cs | 64 +++++++++++-------- Projects/UOContent/Network/UOGateway.cs | 6 +- .../UOContent/Skills/Tracking/Tracking.cs | 4 +- 31 files changed, 189 insertions(+), 172 deletions(-) diff --git a/Projects/Server/Network/ContainerGridPacketHandler.cs b/Projects/Server/Network/ContainerGridPacketHandler.cs index ccbf94603..0907a3d43 100644 --- a/Projects/Server/Network/ContainerGridPacketHandler.cs +++ b/Projects/Server/Network/ContainerGridPacketHandler.cs @@ -15,9 +15,10 @@ namespace Server.Network; -public class ContainerGridPacketHandler : PacketHandler +public unsafe class ContainerGridPacketHandler : PacketHandler { - public ContainerGridPacketHandler(int packetID, int length, bool ingame, OnPacketReceive onReceive) + public ContainerGridPacketHandler(int packetID, int length, bool ingame, + delegate* onReceive) : base(packetID, length, ingame, onReceive) { } diff --git a/Projects/Server/Network/NetState/NetState.cs b/Projects/Server/Network/NetState/NetState.cs index 036f8f3a9..fad1ffe5e 100755 --- a/Projects/Server/Network/NetState/NetState.cs +++ b/Projects/Server/Network/NetState/NetState.cs @@ -745,7 +745,7 @@ public partial class NetState : IComparable * length is the total buffer length. We might be able to use packetReader.Capacity() instead. * packetLength is the length of the packet that this function actually found. */ - private ParserState HandlePacket(CircularBufferReader packetReader, byte packetId, out int packetLength) + private unsafe ParserState HandlePacket(CircularBufferReader packetReader, byte packetId, out int packetLength) { PacketHandler handler = IncomingPackets.GetHandler(packetId); int length = packetReader.Length; @@ -793,7 +793,7 @@ public partial class NetState : IComparable } } - ThrottlePacketCallback throttler = handler.ThrottleCallback; + var throttler = handler.ThrottleCallback; if (throttler != null) { if (!throttler(packetId, this, out bool drop)) diff --git a/Projects/Server/Network/PacketHandler.cs b/Projects/Server/Network/PacketHandler.cs index fdf13b589..8ee6ff7df 100644 --- a/Projects/Server/Network/PacketHandler.cs +++ b/Projects/Server/Network/PacketHandler.cs @@ -15,15 +15,11 @@ namespace Server.Network; -public delegate void OnPacketReceive(NetState state, CircularBufferReader reader, int packetLength); - -public delegate bool ThrottlePacketCallback(int packetId, NetState state, out bool drop); - -public class PacketHandler +public unsafe class PacketHandler { - private int _length; + private readonly int _length; - public PacketHandler(int packetID, int length, bool ingame, OnPacketReceive onReceive) + public PacketHandler(int packetID, int length, bool ingame, delegate* onReceive) { _length = length; PacketID = packetID; @@ -35,9 +31,9 @@ public class PacketHandler public virtual int GetLength(NetState ns) => _length; - public OnPacketReceive OnReceive { get; } + public delegate* OnReceive { get; } - public ThrottlePacketCallback ThrottleCallback { get; set; } + public delegate* ThrottleCallback { get; set; } public bool Ingame { get; } } diff --git a/Projects/Server/Network/Packets/IncomingAccountPackets.cs b/Projects/Server/Network/Packets/IncomingAccountPackets.cs index a29d6157c..33cb6117b 100644 --- a/Projects/Server/Network/Packets/IncomingAccountPackets.cs +++ b/Projects/Server/Network/Packets/IncomingAccountPackets.cs @@ -38,21 +38,21 @@ public static class IncomingAccountPackets } } - public static void Configure() + public static unsafe void Configure() { - IncomingPackets.Register(0x00, 104, false, CreateCharacter); - IncomingPackets.Register(0x5D, 73, false, PlayCharacter); - IncomingPackets.Register(0x80, 62, false, AccountLogin); - IncomingPackets.Register(0x83, 39, false, DeleteCharacter); - IncomingPackets.Register(0x91, 65, false, GameLogin); - IncomingPackets.Register(0xA0, 3, false, PlayServer); - IncomingPackets.Register(0xBB, 9, false, AccountID); - IncomingPackets.Register(0xBD, 0, false, ClientVersion); - IncomingPackets.Register(0xBE, 0, true, AssistVersion); - IncomingPackets.Register(0xCF, 0, false, AccountLogin); - IncomingPackets.Register(0xE1, 0, false, ClientType); - IncomingPackets.Register(0xEF, 21, false, LoginServerSeed); - IncomingPackets.Register(0xF8, 106, false, CreateCharacter); + IncomingPackets.Register(0x00, 104, false, &CreateCharacter); + IncomingPackets.Register(0x5D, 73, false, &PlayCharacter); + IncomingPackets.Register(0x80, 62, false, &AccountLogin); + IncomingPackets.Register(0x83, 39, false, &DeleteCharacter); + IncomingPackets.Register(0x91, 65, false, &GameLogin); + IncomingPackets.Register(0xA0, 3, false, &PlayServer); + IncomingPackets.Register(0xBB, 9, false, &AccountID); + IncomingPackets.Register(0xBD, 0, false, &ClientVersion); + IncomingPackets.Register(0xBE, 0, true, &AssistVersion); + IncomingPackets.Register(0xCF, 0, false, &AccountLogin); + IncomingPackets.Register(0xE1, 0, false, &ClientType); + IncomingPackets.Register(0xEF, 21, false, &LoginServerSeed); + IncomingPackets.Register(0xF8, 106, false, &CreateCharacter); } public static void CreateCharacter(NetState state, CircularBufferReader reader, int packetLength) diff --git a/Projects/Server/Network/Packets/IncomingEntityPackets.cs b/Projects/Server/Network/Packets/IncomingEntityPackets.cs index 8ae998b03..30f56b7ef 100644 --- a/Projects/Server/Network/Packets/IncomingEntityPackets.cs +++ b/Projects/Server/Network/Packets/IncomingEntityPackets.cs @@ -19,12 +19,12 @@ public static class IncomingEntityPackets { public static bool SingleClickProps { get; set; } - public static void Configure() + public static unsafe void Configure() { - IncomingPackets.Register(0x06, 5, true, UseReq); - IncomingPackets.Register(0x09, 5, true, LookReq); - IncomingPackets.Register(0xB6, 9, true, ObjectHelpRequest); - IncomingPackets.Register(0xD6, 0, true, BatchQueryProperties); + IncomingPackets.Register(0x06, 5, true, &UseReq); + IncomingPackets.Register(0x09, 5, true, &LookReq); + IncomingPackets.Register(0xB6, 9, true, &ObjectHelpRequest); + IncomingPackets.Register(0xD6, 0, true, &BatchQueryProperties); } public static void ObjectHelpRequest(NetState state, CircularBufferReader reader, int packetLength) diff --git a/Projects/Server/Network/Packets/IncomingExtendedCommandPackets.cs b/Projects/Server/Network/Packets/IncomingExtendedCommandPackets.cs index 0a8e399aa..a9b15cfbf 100644 --- a/Projects/Server/Network/Packets/IncomingExtendedCommandPackets.cs +++ b/Projects/Server/Network/Packets/IncomingExtendedCommandPackets.cs @@ -34,29 +34,29 @@ public static class IncomingExtendedCommandPackets 125, 126, 127, 128 }; - public static void Configure() + public static unsafe void Configure() { - IncomingPackets.Register(0xBF, 0, true, ExtendedCommand); + IncomingPackets.Register(0xBF, 0, true, &ExtendedCommand); - RegisterExtended(0x05, false, ScreenSize); - RegisterExtended(0x06, true, PartyMessage); - RegisterExtended(0x09, true, DisarmRequest); - RegisterExtended(0x0A, true, StunRequest); - RegisterExtended(0x0B, false, Language); - RegisterExtended(0x0C, true, CloseStatus); - RegisterExtended(0x0E, true, Animate); - RegisterExtended(0x0F, false, Empty); // What's this? - RegisterExtended(0x10, true, QueryProperties); - RegisterExtended(0x13, true, ContextMenuRequest); - RegisterExtended(0x15, true, ContextMenuResponse); - RegisterExtended(0x1A, true, StatLockChange); - RegisterExtended(0x1C, true, CastSpell); - RegisterExtended(0x24, false, UnhandledBF); - RegisterExtended(0x2C, true, BandageTarget); - RegisterExtended(0x2D, true, TargetedSpell); - RegisterExtended(0x2E, true, TargetedSkillUse); - RegisterExtended(0x30, true, TargetByResourceMacro); - RegisterExtended(0x32, true, ToggleFlying); + RegisterExtended(0x05, false, &ScreenSize); + RegisterExtended(0x06, true, &PartyMessage); + RegisterExtended(0x09, true, &DisarmRequest); + RegisterExtended(0x0A, true, &StunRequest); + RegisterExtended(0x0B, false, &Language); + RegisterExtended(0x0C, true, &CloseStatus); + RegisterExtended(0x0E, true, &Animate); + RegisterExtended(0x0F, false, &Empty); // What's this? + RegisterExtended(0x10, true, &QueryProperties); + RegisterExtended(0x13, true, &ContextMenuRequest); + RegisterExtended(0x15, true, &ContextMenuResponse); + RegisterExtended(0x1A, true, &StatLockChange); + RegisterExtended(0x1C, true, &CastSpell); + RegisterExtended(0x24, false, &UnhandledBF); + RegisterExtended(0x2C, true, &BandageTarget); + RegisterExtended(0x2D, true, &TargetedSpell); + RegisterExtended(0x2E, true, &TargetedSkillUse); + RegisterExtended(0x30, true, &TargetByResourceMacro); + RegisterExtended(0x32, true, &ToggleFlying); } private static void UnhandledBF(NetState state, CircularBufferReader reader, int packetLength) @@ -67,7 +67,8 @@ public static class IncomingExtendedCommandPackets { } - public static void RegisterExtended(int packetID, bool ingame, OnPacketReceive onReceive) + public static unsafe void RegisterExtended(int packetID, bool ingame, + delegate* onReceive) { if (packetID is >= 0 and < 0x100) { @@ -86,7 +87,7 @@ public static class IncomingExtendedCommandPackets } } - public static void ExtendedCommand(NetState state, CircularBufferReader reader, int packetLength) + public static unsafe void ExtendedCommand(NetState state, CircularBufferReader reader, int packetLength) { int packetId = reader.ReadUInt16(); diff --git a/Projects/Server/Network/Packets/IncomingHousePackets.cs b/Projects/Server/Network/Packets/IncomingHousePackets.cs index 1d9925537..a1ba476ab 100644 --- a/Projects/Server/Network/Packets/IncomingHousePackets.cs +++ b/Projects/Server/Network/Packets/IncomingHousePackets.cs @@ -17,9 +17,9 @@ namespace Server.Network; public static class IncomingHousePackets { - public static void Configure() + public static unsafe void Configure() { - IncomingPackets.Register(0xFB, 2, false, ShowPublicHouseContent); + IncomingPackets.Register(0xFB, 2, false, &ShowPublicHouseContent); } public static void ShowPublicHouseContent(NetState state, CircularBufferReader reader, int packetLength) diff --git a/Projects/Server/Network/Packets/IncomingItemPackets.cs b/Projects/Server/Network/Packets/IncomingItemPackets.cs index 0b9059d19..beb58b189 100644 --- a/Projects/Server/Network/Packets/IncomingItemPackets.cs +++ b/Projects/Server/Network/Packets/IncomingItemPackets.cs @@ -21,13 +21,13 @@ namespace Server.Network; public static class IncomingItemPackets { - public static void Configure() + public static unsafe void Configure() { - IncomingPackets.Register(0x07, 7, true, LiftReq); - IncomingPackets.Register(new ContainerGridPacketHandler(0x08, 14, true, DropReq)); - IncomingPackets.Register(0x13, 10, true, EquipReq); - IncomingPackets.Register(0xEC, 0, false, EquipMacro); - IncomingPackets.Register(0xED, 0, false, UnequipMacro); + IncomingPackets.Register(0x07, 7, true, &LiftReq); + IncomingPackets.Register(new ContainerGridPacketHandler(0x08, 14, true, &DropReq)); + IncomingPackets.Register(0x13, 10, true, &EquipReq); + IncomingPackets.Register(0xEC, 0, false, &EquipMacro); + IncomingPackets.Register(0xED, 0, false, &UnequipMacro); } public static void LiftReq(NetState state, CircularBufferReader reader, int packetLength) diff --git a/Projects/Server/Network/Packets/IncomingMessagePackets.cs b/Projects/Server/Network/Packets/IncomingMessagePackets.cs index 8bea6bb45..5404bc2ed 100644 --- a/Projects/Server/Network/Packets/IncomingMessagePackets.cs +++ b/Projects/Server/Network/Packets/IncomingMessagePackets.cs @@ -40,10 +40,10 @@ public static class IncomingMessagePackets { private static readonly KeywordList m_KeywordList = new(); - public static void Configure() + public static unsafe void Configure() { - IncomingPackets.Register(0x03, 0, true, AsciiSpeech); - IncomingPackets.Register(0xAD, 0, true, UnicodeSpeech); + IncomingPackets.Register(0x03, 0, true, &AsciiSpeech); + IncomingPackets.Register(0xAD, 0, true, &UnicodeSpeech); } public static void AsciiSpeech(NetState state, CircularBufferReader reader, int packetLength) diff --git a/Projects/Server/Network/Packets/IncomingMobilePackets.cs b/Projects/Server/Network/Packets/IncomingMobilePackets.cs index a612e4ea1..1cdcb7c62 100644 --- a/Projects/Server/Network/Packets/IncomingMobilePackets.cs +++ b/Projects/Server/Network/Packets/IncomingMobilePackets.cs @@ -19,12 +19,12 @@ namespace Server.Network; public static class IncomingMobilePackets { - public static void Configure() + public static unsafe void Configure() { - IncomingPackets.Register(0x75, 35, true, RenameRequest); - IncomingPackets.Register(0x98, 0, true, MobileNameRequest); - IncomingPackets.Register(0xB8, 0, true, ProfileReq); - IncomingPackets.Register(0x6F, 0, true, SecureTrade); + IncomingPackets.Register(0x75, 35, true, &RenameRequest); + IncomingPackets.Register(0x98, 0, true, &MobileNameRequest); + IncomingPackets.Register(0xB8, 0, true, &ProfileReq); + IncomingPackets.Register(0x6F, 0, true, &SecureTrade); } public static void RenameRequest(NetState state, CircularBufferReader reader, int packetLength) diff --git a/Projects/Server/Network/Packets/IncomingMovementPackets.cs b/Projects/Server/Network/Packets/IncomingMovementPackets.cs index 9a361bfa2..9fc1bb0a3 100644 --- a/Projects/Server/Network/Packets/IncomingMovementPackets.cs +++ b/Projects/Server/Network/Packets/IncomingMovementPackets.cs @@ -17,9 +17,9 @@ namespace Server.Network; public static class IncomingMovementPackets { - public static void Configure() + public static unsafe void Configure() { - IncomingPackets.Register(0x02, 7, true, MovementReq); + IncomingPackets.Register(0x02, 7, true, &MovementReq); // Not used by OSI, and interferes with ClassicUO/Razor protocol extensions // IncomingPackets.Register(0xF0, 0, true, NewMovementReq); // IncomingPackets.Register(0xF1, 9, true, TimeSyncReq); diff --git a/Projects/Server/Network/Packets/IncomingPackets.cs b/Projects/Server/Network/Packets/IncomingPackets.cs index 3aa6e2597..23012d7ae 100644 --- a/Projects/Server/Network/Packets/IncomingPackets.cs +++ b/Projects/Server/Network/Packets/IncomingPackets.cs @@ -24,7 +24,8 @@ public static class IncomingPackets public static PacketHandler[] Handlers { get; } = new PacketHandler[0x100]; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void Register(int packetID, int length, bool ingame, OnPacketReceive onReceive) => + public static unsafe void Register(int packetID, int length, bool ingame, + delegate* onReceive) => Register(new PacketHandler(packetID, length, ingame, onReceive)); public static void Register(PacketHandler packetHandler) @@ -53,7 +54,7 @@ public static class IncomingPackets } } - public static void RegisterThrottler(int packetID, ThrottlePacketCallback t) + public static unsafe void RegisterThrottler(int packetID, delegate* t) { var ph = GetHandler(packetID); diff --git a/Projects/Server/Network/Packets/IncomingPlayerPackets.cs b/Projects/Server/Network/Packets/IncomingPlayerPackets.cs index 7de69d681..e409e3edd 100644 --- a/Projects/Server/Network/Packets/IncomingPlayerPackets.cs +++ b/Projects/Server/Network/Packets/IncomingPlayerPackets.cs @@ -23,30 +23,30 @@ namespace Server.Network; public static class IncomingPlayerPackets { - public static void Configure() + public static unsafe void Configure() { - IncomingPackets.Register(0x01, 5, false, Disconnect); - IncomingPackets.Register(0x05, 5, true, AttackReq); - IncomingPackets.Register(0x12, 0, true, TextCommand); - IncomingPackets.Register(0x22, 3, true, Resynchronize); - IncomingPackets.Register(0x2C, 2, true, DeathStatusResponse); - IncomingPackets.Register(0x34, 10, true, MobileQuery); - IncomingPackets.Register(0x3A, 0, true, ChangeSkillLock); - IncomingPackets.Register(0x72, 5, true, SetWarMode); - IncomingPackets.Register(0x73, 2, false, PingReq); - IncomingPackets.Register(0x7D, 13, true, MenuResponse); - IncomingPackets.Register(0x95, 9, true, HuePickerResponse); - IncomingPackets.Register(0x9A, 0, true, AsciiPromptResponse); - IncomingPackets.Register(0x9B, 258, true, HelpRequest); - IncomingPackets.Register(0xA4, 149, false, SystemInfo); - IncomingPackets.Register(0xA7, 4, true, RequestScrollWindow); - IncomingPackets.Register(0xB1, 0, true, DisplayGumpResponse); - IncomingPackets.Register(0xC2, 0, true, UnicodePromptResponse); - IncomingPackets.Register(0xC8, 2, true, SetUpdateRange); - IncomingPackets.Register(0xD0, 0, true, ConfigurationFile); - IncomingPackets.Register(0xD1, 2, true, LogoutReq); - IncomingPackets.Register(0xD7, 0, true, EncodedCommand); - IncomingPackets.Register(0xF4, 0, false, CrashReport); + IncomingPackets.Register(0x01, 5, false, &Disconnect); + IncomingPackets.Register(0x05, 5, true, &AttackReq); + IncomingPackets.Register(0x12, 0, true, &TextCommand); + IncomingPackets.Register(0x22, 3, true, &Resynchronize); + IncomingPackets.Register(0x2C, 2, true, &DeathStatusResponse); + IncomingPackets.Register(0x34, 10, true, &MobileQuery); + IncomingPackets.Register(0x3A, 0, true, &ChangeSkillLock); + IncomingPackets.Register(0x72, 5, true, &SetWarMode); + IncomingPackets.Register(0x73, 2, false, &PingReq); + IncomingPackets.Register(0x7D, 13, true, &MenuResponse); + IncomingPackets.Register(0x95, 9, true, &HuePickerResponse); + IncomingPackets.Register(0x9A, 0, true, &AsciiPromptResponse); + IncomingPackets.Register(0x9B, 258, true, &HelpRequest); + IncomingPackets.Register(0xA4, 149, false, &SystemInfo); + IncomingPackets.Register(0xA7, 4, true, &RequestScrollWindow); + IncomingPackets.Register(0xB1, 0, true, &DisplayGumpResponse); + IncomingPackets.Register(0xC2, 0, true, &UnicodePromptResponse); + IncomingPackets.Register(0xC8, 2, true, &SetUpdateRange); + IncomingPackets.Register(0xD0, 0, true, &ConfigurationFile); + IncomingPackets.Register(0xD1, 2, true, &LogoutReq); + IncomingPackets.Register(0xD7, 0, true, &EncodedCommand); + IncomingPackets.Register(0xF4, 0, false, &CrashReport); IncomingPackets.RegisterEncoded(0x28, true, GuildGumpRequest); IncomingPackets.RegisterEncoded(0x32, true, QuestGumpRequest); diff --git a/Projects/Server/Network/Packets/IncomingTargetingPackets.cs b/Projects/Server/Network/Packets/IncomingTargetingPackets.cs index e4bcd7342..b4efa9e81 100644 --- a/Projects/Server/Network/Packets/IncomingTargetingPackets.cs +++ b/Projects/Server/Network/Packets/IncomingTargetingPackets.cs @@ -20,9 +20,9 @@ namespace Server.Network; public static class IncomingTargetingPackets { - public static void Configure() + public static unsafe void Configure() { - IncomingPackets.Register(0x6C, 19, true, TargetResponse); + IncomingPackets.Register(0x6C, 19, true, &TargetResponse); } public static void TargetResponse(NetState state, CircularBufferReader reader, int packetLength) diff --git a/Projects/Server/Network/Packets/IncomingVendorPackets.cs b/Projects/Server/Network/Packets/IncomingVendorPackets.cs index 7328639c7..2f11b20e4 100644 --- a/Projects/Server/Network/Packets/IncomingVendorPackets.cs +++ b/Projects/Server/Network/Packets/IncomingVendorPackets.cs @@ -19,10 +19,10 @@ namespace Server.Network; public static class IncomingVendorPackets { - public static void Configure() + public static unsafe void Configure() { - IncomingPackets.Register(0x3B, 0, true, VendorBuyReply); - IncomingPackets.Register(0x9F, 0, true, VendorSellReply); + IncomingPackets.Register(0x3B, 0, true, &VendorBuyReply); + IncomingPackets.Register(0x9F, 0, true, &VendorSellReply); } public static void VendorBuyReply(NetState state, CircularBufferReader reader, int packetLength) diff --git a/Projects/UOContent/Accounting/AccountAttackLimiter.cs b/Projects/UOContent/Accounting/AccountAttackLimiter.cs index 97bbc90df..53143327b 100644 --- a/Projects/UOContent/Accounting/AccountAttackLimiter.cs +++ b/Projects/UOContent/Accounting/AccountAttackLimiter.cs @@ -17,16 +17,16 @@ namespace Server.Accounting Enabled = ServerConfiguration.GetOrUpdateSetting("accountAttackLimiter.enable", true); } - public static void Initialize() + public static unsafe void Initialize() { if (!Enabled) { return; } - IncomingPackets.RegisterThrottler(0x80, Throttle); - IncomingPackets.RegisterThrottler(0x91, Throttle); - IncomingPackets.RegisterThrottler(0xCF, Throttle); + IncomingPackets.RegisterThrottler(0x80, &Throttle); + IncomingPackets.RegisterThrottler(0x91, &Throttle); + IncomingPackets.RegisterThrottler(0xCF, &Throttle); } public static bool Throttle(int packetId, NetState ns, out bool drop) diff --git a/Projects/UOContent/Engines/Chat/ChatPackets.cs b/Projects/UOContent/Engines/Chat/ChatPackets.cs index 7eedb3abf..31c63bdb6 100644 --- a/Projects/UOContent/Engines/Chat/ChatPackets.cs +++ b/Projects/UOContent/Engines/Chat/ChatPackets.cs @@ -21,10 +21,10 @@ namespace Server.Engines.Chat { public static class ChatPackets { - public static void Configure() + public static unsafe void Configure() { - IncomingPackets.Register(0xB5, 0x40, true, OpenChatWindowRequest); - IncomingPackets.Register(0xB3, 0, true, ChatAction); + IncomingPackets.Register(0xB5, 0x40, true, &OpenChatWindowRequest); + IncomingPackets.Register(0xB3, 0, true, &ChatAction); } public static void OpenChatWindowRequest(NetState state, CircularBufferReader reader, int packetLength) diff --git a/Projects/UOContent/Engines/ML Quests/Gumps/RaceChangeGump.cs b/Projects/UOContent/Engines/ML Quests/Gumps/RaceChangeGump.cs index d19425fa8..abc739166 100644 --- a/Projects/UOContent/Engines/ML Quests/Gumps/RaceChangeGump.cs +++ b/Projects/UOContent/Engines/ML Quests/Gumps/RaceChangeGump.cs @@ -76,11 +76,11 @@ namespace Server.Engines.MLQuests.Gumps } } - public static void Initialize() + public static unsafe void Initialize() { m_Pending = new Dictionary(); - IncomingExtendedCommandPackets.RegisterExtended(0x2A, true, RaceChangeReply); + IncomingExtendedCommandPackets.RegisterExtended(0x2A, true, &RaceChangeReply); } public static bool IsPending(NetState state) => state != null && m_Pending.ContainsKey(state); diff --git a/Projects/UOContent/Engines/UltimaStore/UltimaStorePackets.cs b/Projects/UOContent/Engines/UltimaStore/UltimaStorePackets.cs index 24a3ba797..bb4b1698b 100644 --- a/Projects/UOContent/Engines/UltimaStore/UltimaStorePackets.cs +++ b/Projects/UOContent/Engines/UltimaStore/UltimaStorePackets.cs @@ -4,9 +4,9 @@ namespace Server.Engines.UltimaStore { public static class UltimaStorePackets { - public static void Configure() + public static unsafe void Configure() { - IncomingPackets.Register(0xFA, 1, true, UltimaStoreOpenRequest); + IncomingPackets.Register(0xFA, 1, true, &UltimaStoreOpenRequest); } public static void UltimaStoreOpenRequest(NetState state, CircularBufferReader reader, int packetLength) diff --git a/Projects/UOContent/Items/Books/BookPackets.cs b/Projects/UOContent/Items/Books/BookPackets.cs index 5eb43d5a1..8e9c6d257 100644 --- a/Projects/UOContent/Items/Books/BookPackets.cs +++ b/Projects/UOContent/Items/Books/BookPackets.cs @@ -22,11 +22,11 @@ namespace Server.Items { public static class BookPackets { - public static void Configure() + public static unsafe void Configure() { - IncomingPackets.Register(0xD4, 0, true, HeaderChange); - IncomingPackets.Register(0x66, 0, true, ContentChange); - IncomingPackets.Register(0x93, 99, true, OldHeaderChange); + IncomingPackets.Register(0xD4, 0, true, &HeaderChange); + IncomingPackets.Register(0x66, 0, true, &ContentChange); + IncomingPackets.Register(0x93, 99, true, &OldHeaderChange); } public static void OldHeaderChange(NetState state, CircularBufferReader reader, int packetLength) diff --git a/Projects/UOContent/Items/Bulletin Boards/BulletinBoardPackets.cs b/Projects/UOContent/Items/Bulletin Boards/BulletinBoardPackets.cs index 2cca09634..53086b70f 100644 --- a/Projects/UOContent/Items/Bulletin Boards/BulletinBoardPackets.cs +++ b/Projects/UOContent/Items/Bulletin Boards/BulletinBoardPackets.cs @@ -24,9 +24,9 @@ namespace Server.Network { public static class BulletinBoardPackets { - public static void Configure() + public static unsafe void Configure() { - IncomingPackets.Register(0x71, 0, true, BBClientRequest); + IncomingPackets.Register(0x71, 0, true, &BBClientRequest); } public static string FormatTS(TimeSpan ts) diff --git a/Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs b/Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs index fa958623e..8d6dfe42e 100644 --- a/Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs +++ b/Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs @@ -43,9 +43,9 @@ namespace Server.Engines.Mahjong return null; } - public static void Configure() + public static unsafe void Configure() { - IncomingPackets.Register(0xDA, 0, true, OnPacket); + IncomingPackets.Register(0xDA, 0, true, &OnPacket); RegisterSubCommand(0x6, ExitGame); RegisterSubCommand(0xA, GivePoints); diff --git a/Projects/UOContent/Items/Maps/MapItemPackets.cs b/Projects/UOContent/Items/Maps/MapItemPackets.cs index c98e34812..935331792 100644 --- a/Projects/UOContent/Items/Maps/MapItemPackets.cs +++ b/Projects/UOContent/Items/Maps/MapItemPackets.cs @@ -20,9 +20,9 @@ namespace Server.Network { public static class MapItemPackets { - public static void Configure() + public static unsafe void Configure() { - IncomingPackets.Register(0x56, 11, true, OnMapCommand); + IncomingPackets.Register(0x56, 11, true, &OnMapCommand); } private static void OnMapCommand(NetState state, CircularBufferReader reader, int packetLength) diff --git a/Projects/UOContent/Misc/HardwareInfo.cs b/Projects/UOContent/Misc/HardwareInfo.cs index 20ef94ddc..eeaff8304 100644 --- a/Projects/UOContent/Misc/HardwareInfo.cs +++ b/Projects/UOContent/Misc/HardwareInfo.cs @@ -87,9 +87,9 @@ namespace Server [CommandProperty(AccessLevel.GameMaster)] public DateTime TimeReceived { get; private set; } - public static void Configure() + public static unsafe void Configure() { - IncomingPackets.Register(0xD9, 0x10C, false, OnReceive); + IncomingPackets.Register(0xD9, 0x10C, false, &OnReceive); CommandSystem.Register("HWInfo", AccessLevel.GameMaster, HWInfo_OnCommand); } diff --git a/Projects/UOContent/Misc/PacketThrottles.cs b/Projects/UOContent/Misc/PacketThrottles.cs index a49f62aca..33ef421c7 100644 --- a/Projects/UOContent/Misc/PacketThrottles.cs +++ b/Projects/UOContent/Misc/PacketThrottles.cs @@ -12,7 +12,7 @@ namespace Server.Network private static readonly int[] Delays = new int[0x100]; private const string ThrottlesConfiguration = "Configuration/throttles.json"; - public static void Initialize() + public static unsafe void Initialize() { CommandSystem.Register("GetThrottle", AccessLevel.Administrator, GetThrottle); CommandSystem.Register("SetThrottle", AccessLevel.Administrator, SetThrottle); @@ -47,7 +47,7 @@ namespace Server.Network { if (Delays[i] > 0) { - IncomingPackets.RegisterThrottler(i, Throttle); + IncomingPackets.RegisterThrottler(i, &Throttle); } } @@ -77,7 +77,7 @@ namespace Server.Network [Usage("SetThrottle ")] [Description("Sets a throttle for the given packet.")] - public static void SetThrottle(CommandEventArgs e) + public static unsafe void SetThrottle(CommandEventArgs e) { if (e.Length != 2) { @@ -104,7 +104,7 @@ namespace Server.Network if (oldDelay == 0 && delay > 0) { - IncomingPackets.RegisterThrottler(packetID, Throttle); + IncomingPackets.RegisterThrottler(packetID, &Throttle); } else if (oldDelay > 0 && delay == 0) { diff --git a/Projects/UOContent/Multis/Houses/HouseFoundation.cs b/Projects/UOContent/Multis/Houses/HouseFoundation.cs index 186952f38..a994c5e2b 100644 --- a/Projects/UOContent/Multis/Houses/HouseFoundation.cs +++ b/Projects/UOContent/Multis/Houses/HouseFoundation.cs @@ -972,9 +972,9 @@ namespace Server.Multis public bool IsHiddenToCustomizer(Item item) => item == Signpost || item == SignHanger || item == Sign || IsFixture(item); - public static void Initialize() + public static unsafe void Initialize() { - IncomingExtendedCommandPackets.RegisterExtended(0x1E, true, QueryDesignDetails); + IncomingExtendedCommandPackets.RegisterExtended(0x1E, true, &QueryDesignDetails); IncomingPackets.RegisterEncoded(0x02, true, Designer_Backup); IncomingPackets.RegisterEncoded(0x03, true, Designer_Restore); diff --git a/Projects/UOContent/Network/FreeshardProtocol.cs b/Projects/UOContent/Network/FreeshardProtocol.cs index 93b6a49b3..62efd6abd 100644 --- a/Projects/UOContent/Network/FreeshardProtocol.cs +++ b/Projects/UOContent/Network/FreeshardProtocol.cs @@ -22,10 +22,15 @@ namespace Server.Network [CallPriority(10)] public static void Configure() { - _handlers = ProtocolExtensions.Register(0xF1); + _handlers = ProtocolExtensions.Register(new FreeshardProtocolInfo()); } - public static void Register(int cmd, bool ingame, OnPacketReceive onReceive) => + public static unsafe void Register(int cmd, bool ingame, delegate* onReceive) => _handlers[cmd] = new PacketHandler(cmd, 0, ingame, onReceive); + + private struct FreeshardProtocolInfo : IProtocolExtensionsInfo + { + public int PacketId => 0xF1; + } } } diff --git a/Projects/UOContent/Network/MapUO.cs b/Projects/UOContent/Network/MapUO.cs index 92769f92b..11f7305ea 100644 --- a/Projects/UOContent/Network/MapUO.cs +++ b/Projects/UOContent/Network/MapUO.cs @@ -25,15 +25,15 @@ namespace Server.Network { private static PacketHandler[] _handlers; - public static void Configure() + public static unsafe void Configure() { - _handlers = ProtocolExtensions.Register(0xF0); + _handlers = ProtocolExtensions.Register(new MapUOProtocolInfo()); - Register(0x00, true, QueryPartyMemberLocations); - Register(0x01, true, QueryGuildMemberLocations); + Register(0x00, true, &QueryPartyMemberLocations); + Register(0x01, true, &QueryGuildMemberLocations); } - public static void Register(int cmd, bool ingame, OnPacketReceive onReceive) => + public static unsafe void Register(int cmd, bool ingame, delegate* onReceive) => _handlers[cmd] = new PacketHandler(cmd, 0, ingame, onReceive); public static void QueryGuildMemberLocations(NetState state, CircularBufferReader reader, int packetLength) @@ -160,5 +160,10 @@ namespace Server.Network writer.WritePacketLength(); ns.Send(writer.Span); } + + private struct MapUOProtocolInfo : IProtocolExtensionsInfo + { + public int PacketId => 0xF0; + } } } diff --git a/Projects/UOContent/Network/ProtocolExtensions.cs b/Projects/UOContent/Network/ProtocolExtensions.cs index e8a034b3e..6df2a6a8b 100644 --- a/Projects/UOContent/Network/ProtocolExtensions.cs +++ b/Projects/UOContent/Network/ProtocolExtensions.cs @@ -15,40 +15,48 @@ namespace Server.Network { - public static class ProtocolExtensions + public interface IProtocolExtensionsInfo { - public static PacketHandler[] Register(byte packetId) + public int PacketId { get; } + } + + public static class ProtocolExtensions where T : struct, IProtocolExtensionsInfo + { + private static readonly PacketHandler[] packetHandlers = new PacketHandler[0x100]; + private static int packetId; + + public static unsafe PacketHandler[] Register(T info) { - var packetHandlers = new PacketHandler[0x100]; + packetId = info.PacketId; + IncomingPackets.Register(packetId, 0, false, &DecodeBundledPacket); - void DecodeBundledPacket(NetState state, CircularBufferReader reader, int packetLength) + return packetHandlers; + } + + private static unsafe void DecodeBundledPacket(NetState state, CircularBufferReader reader, int packetLength) + { + int cmd = reader.ReadByte(); + + PacketHandler ph = packetHandlers[cmd]; + + if (ph == null) { - int cmd = reader.ReadByte(); - - PacketHandler ph = packetHandlers[cmd]; - - if (ph == null) - { - return; - } - - if (ph.Ingame && state.Mobile == null) - { - state.LogInfo($"Sent in-game packet (0x{packetId:X2}x{cmd:X2}) before having been attached to a mobile"); - state.Disconnect("Sent in-game packet before being attached to a mobile."); - } - else if (ph.Ingame && state.Mobile.Deleted) - { - state.Disconnect(string.Empty); - } - else - { - ph.OnReceive(state, reader, packetLength); - } + return; } - IncomingPackets.Register(packetId, 0, false, DecodeBundledPacket); - return packetHandlers; + if (ph.Ingame && state.Mobile == null) + { + state.LogInfo($"Sent in-game packet (0x{packetId:X2}x{cmd:X2}) before having been attached to a mobile"); + state.Disconnect("Sent in-game packet before being attached to a mobile."); + } + else if (ph.Ingame && state.Mobile.Deleted) + { + state.Disconnect(string.Empty); + } + else + { + ph.OnReceive(state, reader, packetLength); + } } } } diff --git a/Projects/UOContent/Network/UOGateway.cs b/Projects/UOContent/Network/UOGateway.cs index 3d9721f37..b3b3bdcc4 100644 --- a/Projects/UOContent/Network/UOGateway.cs +++ b/Projects/UOContent/Network/UOGateway.cs @@ -22,14 +22,14 @@ namespace Server.Network { public static class UOGateway { - public static void Configure() + public static unsafe void Configure() { var enabled = ServerConfiguration.GetOrUpdateSetting("uogateway.enabled", true); if (enabled) { - FreeshardProtocol.Register(0xFE, false, QueryCompactShardStats); - FreeshardProtocol.Register(0xFF, false, QueryExtendedShardStats); + FreeshardProtocol.Register(0xFE, false, &QueryCompactShardStats); + FreeshardProtocol.Register(0xFF, false, &QueryExtendedShardStats); } } diff --git a/Projects/UOContent/Skills/Tracking/Tracking.cs b/Projects/UOContent/Skills/Tracking/Tracking.cs index 4cd3f52ad..ad62def69 100644 --- a/Projects/UOContent/Skills/Tracking/Tracking.cs +++ b/Projects/UOContent/Skills/Tracking/Tracking.cs @@ -12,9 +12,9 @@ namespace Server.SkillHandlers { private static readonly Dictionary m_Table = new(); - public static void Configure() + public static unsafe void Configure() { - IncomingExtendedCommandPackets.RegisterExtended(0x07, true, QuestArrow); + IncomingExtendedCommandPackets.RegisterExtended(0x07, true, &QuestArrow); SkillInfo.Table[(int)SkillName.Tracking].Callback = OnUse; }