diff --git a/Projects/Server.Tests/Tests/Network/Packets/Outgoing/ContainerPacketTests.cs b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/ContainerPacketTests.cs index ee0ec367e..d8f65f93f 100644 --- a/Projects/Server.Tests/Tests/Network/Packets/Outgoing/ContainerPacketTests.cs +++ b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/ContainerPacketTests.cs @@ -161,9 +161,12 @@ namespace Server.Tests.Network { var cont = new Container(World.NewItem); cont.AddItem(new Item(World.NewItem)); + cont.Map = Map.Felucca; var m = new Mobile(0x1); m.DefaultMobileInit(); + m.AccessLevel = AccessLevel.Administrator; + m.Map = Map.Felucca; var expected = new ContainerContent(m, cont).Compile(); @@ -179,9 +182,12 @@ namespace Server.Tests.Network { var cont = new Container(World.NewItem); cont.AddItem(new Item(World.NewItem)); + cont.Map = Map.Felucca; var m = new Mobile(0x1); m.DefaultMobileInit(); + m.AccessLevel = AccessLevel.Administrator; + m.Map = Map.Felucca; var expected = new ContainerContent6017(m, cont).Compile(); diff --git a/Projects/Server/Network/PacketUtilities.cs b/Projects/Server/Network/PacketUtilities.cs index ade7e12b3..7360508a3 100644 --- a/Projects/Server/Network/PacketUtilities.cs +++ b/Projects/Server/Network/PacketUtilities.cs @@ -34,10 +34,9 @@ namespace Server.Network [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void WritePacketLength(this SpanWriter writer) { - var length = writer.Position; writer.Seek(1, SeekOrigin.Begin); - writer.Write((ushort)length); - writer.Seek(length, SeekOrigin.Begin); + writer.Write((ushort)writer.BytesWritten); + writer.Seek(0, SeekOrigin.End); } // If LOCAL INIT is off, then stack/heap allocations have garbage data diff --git a/Projects/Server/Network/Packets/OutgoingCombatPackets.cs b/Projects/Server/Network/Packets/OutgoingCombatPackets.cs index 153034621..7cd05caad 100644 --- a/Projects/Server/Network/Packets/OutgoingCombatPackets.cs +++ b/Projects/Server/Network/Packets/OutgoingCombatPackets.cs @@ -21,47 +21,35 @@ namespace Server.Network { public static void SendSwing(this NetState ns, Serial attacker, Serial defender) { - if (ns == null || !ns.GetSendBuffer(out var buffer)) + if (ns == null) { return; } - var writer = new CircularBufferWriter(buffer); + var writer = new SpanWriter(stackalloc byte[10]); writer.Write((byte)0x2F); // Packet ID writer.Write((byte)0); writer.Write(attacker); writer.Write(defender); - ns.Send(ref buffer, writer.Position); + ns.Send(writer.Span); } - public static void SendSetWarMode(this NetState ns, bool warmode) - { - if (ns == null || !ns.GetSendBuffer(out var buffer)) - { - return; - } - - var writer = new CircularBufferWriter(buffer); - writer.Write((byte)0x72); // Packet ID - // Warmode, 0x00, 0x32, 0x00 - writer.Write(warmode ? 0x01003200 : 0x00003200); - - ns.Send(ref buffer, writer.Position); - } + public static unsafe void SendSetWarMode(this NetState ns, bool warmode) => + ns?.Send(stackalloc byte[] { 0x72, *(byte*)&warmode, 0x00, 0x32, 0x00 }); public static void SendChangeCombatant(this NetState ns, Serial combatant) { - if (ns == null || !ns.GetSendBuffer(out var buffer)) + if (ns == null) { return; } - var writer = new CircularBufferWriter(buffer); + var writer = new SpanWriter(stackalloc byte[5]); writer.Write((byte)0xAA); // Packet ID writer.Write(combatant); - ns.Send(ref buffer, writer.Position); + ns.Send(writer.Span); } } } diff --git a/Projects/Server/Network/Packets/OutgoingContainerPackets.cs b/Projects/Server/Network/Packets/OutgoingContainerPackets.cs index b01e937e4..9663af367 100644 --- a/Projects/Server/Network/Packets/OutgoingContainerPackets.cs +++ b/Projects/Server/Network/Packets/OutgoingContainerPackets.cs @@ -42,12 +42,12 @@ namespace Server.Network public static void SendNewSpellbookContent(this NetState ns, Serial book, int graphic, int offset, ulong content) { - if (ns == null || !ns.GetSendBuffer(out var buffer)) + if (ns == null) { return; } - var writer = new CircularBufferWriter(buffer); + var writer = new SpanWriter(stackalloc byte[23]); writer.Write((byte)0xBF); // Packet ID writer.Write((ushort)23); // Length writer.Write((short)0x1B); // Subpacket @@ -62,24 +62,25 @@ namespace Server.Network writer.Write((byte)(content >> (i * 8))); } - ns.Send(ref buffer, writer.Position); + ns.Send(writer.Span); } public static void SendOldSpellbookContent(this NetState ns, Serial book, int offset, ulong content) { - if (ns == null || !ns.GetSendBuffer(out var buffer)) + if (ns == null) { return; } - var writer = new CircularBufferWriter(buffer); - writer.Write((byte)0x3C); // Packet ID - writer.Seek(4, SeekOrigin.Current); // Length & written count + var count = content.NumberOfSetBits(); + var length = 5 + count * (ns.ContainerGridLines ? 20 : 19); - var written = 0; + var writer = new SpanWriter(stackalloc byte[length]); + writer.Write((byte)0x3C); // Packet ID + writer.Write((ushort)length); + writer.Write((ushort)count); ulong mask = 1; - for (var i = 0; i < 64; ++i, mask <<= 1) { if ((content & mask) != 0) @@ -95,27 +96,20 @@ namespace Server.Network } writer.Write(book); writer.Write((short)0); // Quest Hue - - ++written; } } - var length = writer.Position; - writer.Seek(1, SeekOrigin.Begin); - writer.Write((ushort)length); - writer.Write((ushort)written); - - ns.Send(ref buffer, length); + ns.Send(writer.Span); } public static void SendDisplayContainer(this NetState ns, Serial cont, int gumpId) { - if (ns == null || !ns.GetSendBuffer(out var buffer)) + if (ns == null) { return; } - var writer = new CircularBufferWriter(buffer); + var writer = new SpanWriter(stackalloc byte[ns.HighSeas ? 9 : 7]); writer.Write((byte)0x24); // Packet ID writer.Write(cont); writer.Write((ushort)gumpId); @@ -124,12 +118,12 @@ namespace Server.Network writer.Write((short)0x7D); } - ns.Send(ref buffer, writer.Position); + ns.Send(writer.Span); } public static void SendContainerContentUpdate(this NetState ns, Item item) { - if (ns == null || !ns.GetSendBuffer(out var buffer)) + if (ns == null) { return; } @@ -146,7 +140,7 @@ namespace Server.Network parentSerial = Serial.Zero; } - var writer = new CircularBufferWriter(buffer); + var writer = new SpanWriter(stackalloc byte[ns.ContainerGridLines ? 21 : 20]); writer.Write((byte)0x25); // Packet ID writer.Write(item.Serial); writer.Write((ushort)item.ItemID); @@ -161,7 +155,7 @@ namespace Server.Network writer.Write(parentSerial); writer.Write((ushort)(item.QuestItem ? Item.QuestItemHue : item.Hue)); - ns.Send(ref buffer, writer.Position); + ns.Send(writer.Span); } public static void SendContainerContent(this NetState ns, Mobile beholder, Item beheld) @@ -174,9 +168,9 @@ namespace Server.Network var items = beheld.Items; var count = items.Count; - var writer = new CircularBufferWriter(buffer); + var writer = new SpanWriter(stackalloc byte[5 + items.Count * (ns.ContainerGridLines ? 20 : 19)]); writer.Write((byte)0x3C); // Packet ID - writer.Seek(4, SeekOrigin.Current); // Length & writter count + writer.Seek(4, SeekOrigin.Current); // Length & written count var written = 0; @@ -205,12 +199,12 @@ namespace Server.Network } } - var length = writer.Position; writer.Seek(1, SeekOrigin.Begin); - writer.Write((ushort)length); + writer.Write((ushort)writer.BytesWritten); writer.Write((ushort)written); + writer.Seek(0, SeekOrigin.End); - ns.Send(ref buffer, length); + ns.Send(writer.Span); } } } diff --git a/Projects/Server/Utilities/Utility.cs b/Projects/Server/Utilities/Utility.cs index 365ed271b..915149b1a 100644 --- a/Projects/Server/Utilities/Utility.cs +++ b/Projects/Server/Utilities/Utility.cs @@ -1457,5 +1457,13 @@ namespace Server { set.RemoveWhere(entry => entry?.Deleted != false); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int NumberOfSetBits(this ulong i) + { + i -= (i >> 1) & 0x5555555555555555UL; + i = (i & 0x3333333333333333UL) + ((i >> 2) & 0x3333333333333333UL); + return (int)(unchecked(((i + (i >> 4)) & 0xF0F0F0F0F0F0F0FUL) * 0x101010101010101UL) >> 56); + } } }