From e17195ca8093c4756c4beef9bd5352dd2ad0a759 Mon Sep 17 00:00:00 2001 From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com> Date: Fri, 3 Jul 2020 19:03:10 -0700 Subject: [PATCH] Adds more packet tests (#166) --- .../Network/Packets/GumpUtilities.cs | 40 ++ .../Old/Outgoing/AccountPacketTests.cs | 50 ++- .../Packets/Old/Outgoing/EffectPacketTests.cs | 178 ++++++++ .../Old/Outgoing/EquipmentPacketTests.cs | 3 +- .../Packets/Old/Outgoing/GumpPacketTests.cs | 244 +++++++++++ .../Packets/Old/Outgoing/ItemPacketTests.cs | 388 ++++++++++++++++++ .../Packets/Old/Outgoing/MenuPacketTests.cs | 37 +- .../Old/Outgoing/SecureTradePacketTests.cs | 2 +- .../Old/Outgoing/VendorBuyPacketTests.cs | 25 +- .../Old/Outgoing/VendorSellPacketTests.cs | 3 +- .../Network/Packets/PacketTestUtilities.cs | 153 ++++++- Projects/Server.Tests/Server.Tests.csproj | 1 + Projects/Server.Tests/packages.lock.json | 99 +++-- Projects/Server/Gumps/Gump.cs | 18 +- Projects/Server/Items/Container.cs | 4 +- Projects/Server/Main.cs | 5 + .../Packets/Old Packets/GumpPackets.cs | 8 +- .../Packets/Old Packets/ItemPackets.cs | 64 +-- Projects/Server/TileData.cs | 125 ++---- .../UOContent.Tests/UOContent.Tests.csproj | 4 +- Projects/UOContent.Tests/packages.lock.json | 15 +- .../Items/Skill Items/Magical/Spellbook.cs | 14 +- 22 files changed, 1203 insertions(+), 277 deletions(-) create mode 100644 Projects/Server.Tests/Network/Packets/GumpUtilities.cs create mode 100644 Projects/Server.Tests/Network/Packets/Old/Outgoing/EffectPacketTests.cs create mode 100644 Projects/Server.Tests/Network/Packets/Old/Outgoing/GumpPacketTests.cs create mode 100644 Projects/Server.Tests/Network/Packets/Old/Outgoing/ItemPacketTests.cs diff --git a/Projects/Server.Tests/Network/Packets/GumpUtilities.cs b/Projects/Server.Tests/Network/Packets/GumpUtilities.cs new file mode 100644 index 000000000..0b99d4b4e --- /dev/null +++ b/Projects/Server.Tests/Network/Packets/GumpUtilities.cs @@ -0,0 +1,40 @@ +using System; +using System.IO.Compression; +using System.Text; + +namespace Server.Tests.Network.Packets +{ + public class GumpUtilities + { + public static readonly byte[] NoMoveBuffer = Encoding.ASCII.GetBytes("{ nomove }"); + public static readonly byte[] NoCloseBuffer = Encoding.ASCII.GetBytes("{ noclose }"); + public static readonly byte[] NoDisposeBuffer = Encoding.ASCII.GetBytes("{ nodispose }"); + public static readonly byte[] NoResizeBuffer = Encoding.ASCII.GetBytes("{ noresize }"); + + public const string NoMove = "{ nomove }"; + public const string NoClose = "{ noclose }"; + public const string NoDispose = "{ nodispose }"; + public const string NoResize = "{ noresize }"; + + public static int WritePacked(ReadOnlySpan source, Span dest) + { + int length = source.Length; + + if (length == 0) + { + dest.Slice(0, 4).Clear(); + return 4; + } + + ulong packLength = (ulong)dest.Length - 8; + + ZlibError ce = Zlib.Pack(dest.Slice(8), ref packLength, source, ZlibQuality.Default); + if (ce != ZlibError.Okay) Console.WriteLine("ZLib error: {0} (#{1})", ce, (int)ce); + + ((int)(4 + packLength)).CopyTo(dest.Slice(0, 4)); + length.CopyTo(dest.Slice(4, 4)); + + return (int)(8 + packLength); + } + } +} diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/AccountPacketTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/AccountPacketTests.cs index c66dba37d..d4d4eb838 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/AccountPacketTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/AccountPacketTests.cs @@ -114,10 +114,10 @@ namespace Server.Tests.Network.Packets Span expectedData = stackalloc byte[5 + account.Length * 60]; int pos = 0; - expectedData[pos++] = 0x81; // Packet ID + ((byte)0x81).CopyTo(ref pos, expectedData); // Packet ID ((ushort)expectedData.Length).CopyTo(ref pos, expectedData); // Length - expectedData[pos++] = 1; // Count of non-null characters - expectedData[pos++] = 0; + ((byte)1).CopyTo(ref pos, expectedData); // Count of non-null characters + ((byte)0).CopyTo(ref pos, expectedData); for (var i = 0; i < account.Length; ++i) { @@ -183,13 +183,19 @@ namespace Server.Tests.Network.Packets [InlineData(ProtocolChanges.Version6000)] public void TestSupportedFeatures(ProtocolChanges protocolChanges) { + var firstMobile = new Mobile(0x1); + firstMobile.DefaultMobileInit(); + firstMobile.Name = "Test Mobile"; + + var account = new TestAccount(new[] {firstMobile, null, null, null, null}); + NetState ns = new NetState(new TestConnectionContext { RemoteEndPoint = IPEndPoint.Parse("127.0.0.1") - }); - - ns.ProtocolChanges = protocolChanges; - ns.Account = new TestAccount(new Mobile[0]); + }) + { + Account = account + }; Span data = new SupportedFeatures(ns).Compile(); @@ -257,7 +263,7 @@ namespace Server.Tests.Network.Packets ((ushort)m.X).CopyTo(ref pos, expectedData); ((ushort)m.Y).CopyTo(ref pos, expectedData); ((ushort)m.Z).CopyTo(ref pos, expectedData); - expectedData[pos++] = (byte)m.Direction; + ((byte)m.Direction).CopyTo(ref pos, expectedData); pos += 9; var map = m.Map; @@ -297,7 +303,7 @@ namespace Server.Tests.Network.Packets Span expectedData = stackalloc byte[4 + account.Length * 60]; int pos = 0; - expectedData[pos++] = 0x86; // Packet ID + ((byte)0x86).CopyTo(ref pos, expectedData); // Packet ID ((ushort)expectedData.Length).CopyTo(ref pos, expectedData); // Length int highSlot = -1; @@ -309,7 +315,7 @@ namespace Server.Tests.Network.Packets } int count = Math.Max(Math.Max(highSlot + 1, account.Limit), 5); - expectedData[pos++] = (byte)count; + ((byte)count).CopyTo(ref pos, expectedData); for (int i = 0; i < count; i++) { @@ -346,7 +352,7 @@ namespace Server.Tests.Network.Packets Span expectedData = stackalloc byte[11 + account.Length * 60 + info.Length * 89]; int pos = 0; - expectedData[pos++] = 0xA9; // Packet ID + ((byte)0xA9).CopyTo(ref pos, expectedData); // Packet ID ((ushort)expectedData.Length).CopyTo(ref pos, expectedData); // Length int highSlot = -1; @@ -358,7 +364,7 @@ namespace Server.Tests.Network.Packets } int count = Math.Max(Math.Max(highSlot + 1, account.Limit), 5); - expectedData[pos++] = (byte)count; + ((byte)count).CopyTo(ref pos, expectedData); for (int i = 0; i < count; i++) { @@ -374,12 +380,12 @@ namespace Server.Tests.Network.Packets } } - expectedData[pos++] = (byte)info.Length; + ((byte)info.Length).CopyTo(ref pos, expectedData); for (int i = 0; i < info.Length; i++) { var ci = info[i]; - expectedData[pos++] = (byte)i; + ((byte)i).CopyTo(ref pos, expectedData); ci.City.CopyASCIIFixedTo(ref pos, 32, expectedData); ci.Building.CopyASCIIFixedTo(ref pos, 32, expectedData); ci.X.CopyTo(ref pos, expectedData); @@ -424,7 +430,7 @@ namespace Server.Tests.Network.Packets Span expectedData = stackalloc byte[9 + account.Length * 60 + info.Length * 63]; int pos = 0; - expectedData[pos++] = 0xA9; // Packet ID + ((byte)0xA9).CopyTo(ref pos, expectedData); // Packet ID ((ushort)expectedData.Length).CopyTo(ref pos, expectedData); // Length int highSlot = -1; @@ -436,7 +442,7 @@ namespace Server.Tests.Network.Packets } int count = Math.Max(Math.Max(highSlot + 1, account.Limit), 5); - expectedData[pos++] = (byte)count; + ((byte)count).CopyTo(ref pos, expectedData); for (int i = 0; i < count; i++) { @@ -452,12 +458,12 @@ namespace Server.Tests.Network.Packets } } - expectedData[pos++] = (byte)info.Length; + ((byte)info.Length).CopyTo(ref pos, expectedData); for (int i = 0; i < info.Length; i++) { var ci = info[i]; - expectedData[pos++] = (byte)i; + ((byte)i).CopyTo(ref pos, expectedData); ci.City.CopyASCIIFixedTo(ref pos, 31, expectedData); ci.Building.CopyASCIIFixedTo(ref pos, 31, expectedData); } @@ -505,9 +511,9 @@ namespace Server.Tests.Network.Packets Span expectedData = stackalloc byte[6 + info.Length * 40]; int pos = 0; - expectedData[pos++] = 0xA8; // Packet ID + ((byte)0xA8).CopyTo(ref pos, expectedData); // Packet ID ((ushort)expectedData.Length).CopyTo(ref pos, expectedData); - expectedData[pos++] = 0x5D; // Unknown + ((byte)0x5D).CopyTo(ref pos, expectedData); // Unknown ((ushort)info.Length).CopyTo(ref pos, expectedData); for (int i = 0; i < info.Length; i++) @@ -515,8 +521,8 @@ namespace Server.Tests.Network.Packets var si = info[i]; ((ushort)i).CopyTo(ref pos, expectedData); si.Name.CopyASCIIFixedTo(ref pos, 32, expectedData); - expectedData[pos++] = (byte)si.FullPercent; - expectedData[pos++] = (byte)si.TimeZone; + ((byte)si.FullPercent).CopyTo(ref pos, expectedData); + ((byte)si.TimeZone).CopyTo(ref pos, expectedData); Utility.GetAddressValue(si.Address.Address).CopyTo(ref pos, expectedData); } diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/EffectPacketTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/EffectPacketTests.cs new file mode 100644 index 000000000..40b879d09 --- /dev/null +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/EffectPacketTests.cs @@ -0,0 +1,178 @@ +using System; +using Server.Network; +using Xunit; + +namespace Server.Tests.Network.Packets +{ + public class EffectPackets + { + [Fact] + public void TestParticleEffect() + { + EffectType effectType = EffectType.Moving; + Serial serial = 0x4000; + Serial from = 0x1000; + Serial to = 0x2000; + var itemId = 0x100; + Point3D fromPoint = new Point3D(1000, 100, -10); + Point3D toPoint = new Point3D(1500, 500, 0); + byte speed = 3; + byte duration = 2; + bool direction = false; + bool explode = false; + int hue = 0x1024; + int renderMode = 1; + ushort effect = 3; + ushort explodeEffect = 0; + ushort explodeSound = 0; + byte layer = 9; + ushort unknown = 0; + + Span data = new ParticleEffect( + effectType, from, to, itemId, + fromPoint, toPoint, speed, duration, + direction, explode, hue, renderMode, + effect, explodeEffect, explodeSound, serial, + layer, unknown + ).Compile(); + + Span expectedData = stackalloc byte[49]; + + int pos = 0; + ((byte)0xC7).CopyTo(ref pos, expectedData); // Packet ID + ((byte)effectType).CopyTo(ref pos, expectedData); + from.CopyTo(ref pos, expectedData); + to.CopyTo(ref pos, expectedData); + ((ushort)itemId).CopyTo(ref pos, expectedData); + ((ushort)fromPoint.X).CopyTo(ref pos, expectedData); + ((ushort)fromPoint.Y).CopyTo(ref pos, expectedData); + ((byte)fromPoint.Z).CopyTo(ref pos, expectedData); + ((ushort)toPoint.X).CopyTo(ref pos, expectedData); + ((ushort)toPoint.Y).CopyTo(ref pos, expectedData); + ((byte)toPoint.Z).CopyTo(ref pos, expectedData); + speed.CopyTo(ref pos, expectedData); + duration.CopyTo(ref pos, expectedData); + expectedData.Clear(ref pos, 2); + direction.CopyTo(ref pos, expectedData); + explode.CopyTo(ref pos, expectedData); + hue.CopyTo(ref pos, expectedData); + renderMode.CopyTo(ref pos, expectedData); + effect.CopyTo(ref pos, expectedData); + explodeEffect.CopyTo(ref pos, expectedData); + explodeSound.CopyTo(ref pos, expectedData); + serial.CopyTo(ref pos, expectedData); + layer.CopyTo(ref pos, expectedData); + unknown.CopyTo(ref pos, expectedData); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestHuedEffect() + { + EffectType effectType = EffectType.Moving; + Serial serial = 0x4000; + Serial from = 0x1000; + Serial to = 0x2000; + var itemId = 0x100; + Point3D fromPoint = new Point3D(1000, 100, -10); + Point3D toPoint = new Point3D(1500, 500, 0); + byte speed = 3; + byte duration = 2; + bool direction = false; + bool explode = false; + int hue = 0x1024; + int renderMode = 1; + + Span data = new HuedEffect( + effectType, from, to, itemId, + fromPoint, toPoint, speed, duration, + direction, explode, hue, renderMode + ).Compile(); + + Span expectedData = stackalloc byte[36]; + + int pos = 0; + ((byte)0xC0).CopyTo(ref pos, expectedData); // Packet ID + ((byte)effectType).CopyTo(ref pos, expectedData); + from.CopyTo(ref pos, expectedData); + to.CopyTo(ref pos, expectedData); + ((ushort)itemId).CopyTo(ref pos, expectedData); + ((ushort)fromPoint.X).CopyTo(ref pos, expectedData); + ((ushort)fromPoint.Y).CopyTo(ref pos, expectedData); + ((byte)fromPoint.Z).CopyTo(ref pos, expectedData); + ((ushort)toPoint.X).CopyTo(ref pos, expectedData); + ((ushort)toPoint.Y).CopyTo(ref pos, expectedData); + ((byte)toPoint.Z).CopyTo(ref pos, expectedData); + speed.CopyTo(ref pos, expectedData); + duration.CopyTo(ref pos, expectedData); + expectedData.Clear(ref pos, 2); + direction.CopyTo(ref pos, expectedData); + explode.CopyTo(ref pos, expectedData); + hue.CopyTo(ref pos, expectedData); + renderMode.CopyTo(ref pos, expectedData); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestScreenEffect() + { + var type = ScreenEffectType.FadeOut; + Span data = new ScreenEffect(type).Compile(); + + Span expectedData = stackalloc byte[28] + { + 0x70, // Packet ID + 0x04, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, // Screen Effect Type + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 + }; + + ((ushort)type).CopyTo(expectedData.Slice(10, 2)); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestBoltEffect() + { + IEntity entity = new Entity(0x1000, new Point3D(1000, 100, -10), Map.Felucca); + var hue = 0x1024; + Span data = new BoltEffect(entity, hue).Compile(); + + Span expectedData = stackalloc byte[36] + { + 0xC0, // Packet ID + 0x01, // Effect + 0x00, 0x00, 0x00, 0x00, // From Serial + 0x00, 0x00, 0x00, 0x00, // To Serial + 0x00, 0x00, // Item ID + 0x00, 0x00, 0x00, 0x00, 0x00, // From Point + 0x00, 0x00, 0x00, 0x00, 0x00, // To Point + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, // Hue + 0x00, 0x00, 0x00, 0x00 + }; + + int pos = 2; + entity.Serial.CopyTo(ref pos, expectedData); + pos += 6; + ((ushort)entity.X).CopyTo(ref pos, expectedData); + ((ushort)entity.Y).CopyTo(ref pos, expectedData); + ((byte)entity.Z).CopyTo(ref pos, expectedData); + ((ushort)entity.X).CopyTo(ref pos, expectedData); + ((ushort)entity.Y).CopyTo(ref pos, expectedData); + ((byte)entity.Z).CopyTo(ref pos, expectedData); + pos += 6; + hue.CopyTo(ref pos, expectedData); + + AssertThat.Equal(data, expectedData); + } + } +} diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/EquipmentPacketTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/EquipmentPacketTests.cs index 25ab2f020..3d101d2eb 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/EquipmentPacketTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/EquipmentPacketTests.cs @@ -37,7 +37,7 @@ namespace Server.Tests.Network.Packets int pos = 0; - expectedData[pos++] = 0xBF; // Packet ID + ((byte)0xBF).CopyTo(ref pos, expectedData); // Packet ID ((ushort)length).CopyTo(ref pos, expectedData); // Length ((ushort)0x10).CopyTo(ref pos, expectedData); // Subcommand item.Serial.CopyTo(ref pos, expectedData); @@ -46,7 +46,6 @@ namespace Server.Tests.Network.Packets { var name = info.Crafter.Name ?? ""; (-3).CopyTo(ref pos, expectedData); - ((ushort)name.Length).CopyTo(ref pos, expectedData); name.CopyASCIITo(ref pos, expectedData); } diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/GumpPacketTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/GumpPacketTests.cs new file mode 100644 index 000000000..4e238c35a --- /dev/null +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/GumpPacketTests.cs @@ -0,0 +1,244 @@ +using System; +using System.Buffers; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using Server.Gumps; +using Server.Network; +using Xunit; + +namespace Server.Tests.Network.Packets +{ + public class GumpPacketTests + { + [Fact] + public void TestCloseGump() + { + var typeId = 100; + var buttonId = 10; + + Span data = new CloseGump(typeId, buttonId).Compile(); + + Span expectedData = stackalloc byte[] + { + 0xBF, // Packet ID + 0x00, 0xD, // Length + 0x00, 0x04, // Close + 0x00, 0x00, 0x00, 0x00, // Type Id + 0x00, 0x00, 0x00, 0x00, // Button Id + }; + + typeId.CopyTo(expectedData.Slice(5, 4)); + buttonId.CopyTo(expectedData.Slice(9, 4)); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestDisplaySignGump() + { + Serial gumpSerial = 0x1000; + var gumpId = 100; + var unknownString = "This is an unknown string"; + var caption = "This is a caption"; + + Span data = new DisplaySignGump(gumpSerial, gumpId, unknownString, caption).Compile(); + + Span expectedData = stackalloc byte[15 + unknownString.Length + caption.Length]; + + int pos = 0; + ((byte)0x8B).CopyTo(ref pos, expectedData); + ((ushort)expectedData.Length).CopyTo(ref pos, expectedData); + gumpSerial.CopyTo(ref pos, expectedData); + ((ushort)gumpId).CopyTo(ref pos, expectedData); + unknownString.CopyASCIINullTo(ref pos, expectedData); + caption.CopyASCIINullTo(ref pos, expectedData); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestFastGumpPacket() + { + NetState ns = new NetState(new AccountPacketTests.TestConnectionContext + { + RemoteEndPoint = IPEndPoint.Parse("127.0.0.1"), + }); + + var gump = new ResurrectGump(2); + + Span data = gump.Compile(ns).Compile(); + + Span expectedData = stackalloc byte[0x1000]; + + int pos = 0; + + expectedData[pos++] = 0xB0; // Packet ID + pos += 2; // Length + + gump.Serial.CopyTo(ref pos, expectedData); + gump.TypeID.CopyTo(ref pos, expectedData); + gump.X.CopyTo(ref pos, expectedData); + gump.Y.CopyTo(ref pos, expectedData); + pos += 2; // Layout Length + + int layoutLength = 0; + + if (!gump.Draggable) + { + GumpUtilities.NoMoveBuffer.CopyTo(ref pos, expectedData); + layoutLength += GumpUtilities.NoMove.Length; + } + + if (!gump.Closable) + { + GumpUtilities.NoCloseBuffer.CopyTo(ref pos, expectedData); + layoutLength += GumpUtilities.NoClose.Length; + } + + if (!gump.Disposable) + { + GumpUtilities.NoDisposeBuffer.CopyTo(ref pos, expectedData); + layoutLength += GumpUtilities.NoDispose.Length; + } + + if (!gump.Resizable) + { + GumpUtilities.NoResizeBuffer.CopyTo(ref pos, expectedData); + layoutLength += GumpUtilities.NoResize.Length; + } + + foreach (var entry in gump.Entries) + { + var str = entry.Compile(ns); + str.CopyRawASCIITo(ref pos, expectedData); + layoutLength += str.Length; // ASCII so 1:1 + } + + ((ushort)layoutLength).CopyTo(expectedData.Slice(19, 2)); + ((ushort)gump.Strings.Count).CopyTo(ref pos, expectedData); + + for (var i = 0; i < gump.Strings.Count; ++i) + (gump.Strings[i] ?? "").CopyUnicodeBigEndianTo(ref pos, expectedData); + + ((ushort)pos).CopyTo(expectedData.Slice(1, 2)); + + expectedData = expectedData.Slice(0, pos); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestPackedGumpPacket() + { + NetState ns = new NetState(new AccountPacketTests.TestConnectionContext + { + RemoteEndPoint = IPEndPoint.Parse("127.0.0.1"), + }); + + ns.ProtocolChanges = ProtocolChanges.Unpack; + + var gump = new ResurrectGump(2); + + Span data = gump.Compile(ns).Compile(); + + Span expectedData = stackalloc byte[0x1000]; + + int pos = 0; + + expectedData[pos++] = 0xDD; // Packet ID + pos += 2; // Length + + gump.Serial.CopyTo(ref pos, expectedData); + gump.TypeID.CopyTo(ref pos, expectedData); + gump.X.CopyTo(ref pos, expectedData); + gump.Y.CopyTo(ref pos, expectedData); + + var layoutList = new List(); + int bufferLength = 1; // Null terminated + + if (!gump.Draggable) + { + layoutList.Add(GumpUtilities.NoMove); + bufferLength += GumpUtilities.NoMove.Length; + } + + if (!gump.Closable) + { + layoutList.Add(GumpUtilities.NoClose); + bufferLength += GumpUtilities.NoClose.Length; + } + + if (!gump.Disposable) + { + layoutList.Add(GumpUtilities.NoDispose); + bufferLength += GumpUtilities.NoDispose.Length; + } + + if (!gump.Resizable) + { + layoutList.Add(GumpUtilities.NoResize); + bufferLength += GumpUtilities.NoResize.Length; + } + + foreach (var entry in gump.Entries) + { + var str = entry.Compile(ns); + bufferLength += str.Length; + layoutList.Add(str); + } + + IMemoryOwner memOwner = SlabMemoryPool.Shared.Rent(bufferLength); + + Span buffer = memOwner.Memory.Span; + int bufferPos = 0; + + foreach (var layout in layoutList) + layout.CopyRawASCIITo(ref bufferPos, buffer); + + pos += GumpUtilities.WritePacked(buffer.Slice(0, bufferPos + 1), expectedData.Slice(pos)); + memOwner.Dispose(); + + gump.Strings.Count.CopyTo(ref pos, expectedData); + bufferLength = gump.Strings.Sum(str => 2 + str.Length * 2); + memOwner = SlabMemoryPool.Shared.Rent(bufferLength); + buffer = memOwner.Memory.Span; + bufferPos = 0; + + foreach (var str in gump.Strings) + str.CopyUnicodeBigEndianTo(ref bufferPos, buffer); + + pos += GumpUtilities.WritePacked(buffer.Slice(0, bufferPos), expectedData.Slice(pos)); + + // Length + ((ushort)pos).CopyTo(expectedData.Slice(1, 2)); + expectedData = expectedData.Slice(0, pos); + + AssertThat.Equal(data, expectedData); + } + } + + public class ResurrectGump : Gump + { + public ResurrectGump(int msg) : base(100, 0) + { + AddPage(0); + + AddBackground(0, 0, 400, 350, 2600); + + AddHtmlLocalized(0, 20, 400, 35, 1011022); //
Resurrection
+ + /* It is possible for you to be resurrected here by this healer. Do you wish to try?
+ * CONTINUE - You chose to try to come back to life now.
+ * CANCEL - You prefer to remain a ghost for now. + */ + AddHtmlLocalized(50, 55, 300, 140, 1011023 + msg, true, true); + + AddButton(200, 227, 4005, 4007, 0); + AddHtmlLocalized(235, 230, 110, 35, 1011012); // CANCEL + + AddButton(65, 227, 4005, 4007, 1); + AddHtmlLocalized(100, 230, 110, 35, 1011011); // CONTINUE + } + } +} diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/ItemPacketTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/ItemPacketTests.cs new file mode 100644 index 000000000..37a8b3ddb --- /dev/null +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/ItemPacketTests.cs @@ -0,0 +1,388 @@ +using System; +using Server.Items; +using Server.Network; +using Xunit; + +namespace Server.Tests.Network.Packets +{ + public class ItemPacketTests + { + [Fact] + public void TestWorldItemPacket() + { + Serial serial = 0x1000; + var itemId = 1; + + // Move to fixture + TileData.ItemTable[itemId] = new ItemData( + "Test Item Data", TileFlag.Generic, 1, 1, 1, 1, 1 + ); + + Item item = new Item(serial) + { + ItemID = itemId, + Hue = 0x1024, + Amount = 10, + Location = new Point3D(1000, 100, -10), + Direction = Direction.Left + }; + + Span data = new WorldItem(item).Compile(); + + Span expectedData = stackalloc byte[20]; // Max size + int pos = 0; + + ((byte)0x1A).CopyTo(ref pos, expectedData); + pos += 2; // Length + + if (item.Amount != 0) + (serial | 0x80000000).CopyTo(ref pos, expectedData); + else + (serial & 0x7FFFFFFF).CopyTo(ref pos, expectedData); + + if (item is BaseMulti) + ((ushort)(item.ItemID | 0x4000)).CopyTo(ref pos, expectedData); + else + ((ushort)item.ItemID).CopyTo(ref pos, expectedData); + + if (item.Amount != 0) + ((ushort)item.Amount).CopyTo(ref pos, expectedData); + + byte direction = (byte)item.Direction; + ushort x = (ushort)(item.X & 0x7FFF); + + if (direction != 0) + x |= 0x8000; + + x.CopyTo(ref pos, expectedData); + + int hue = item.Hue; + int flags = item.GetPacketFlags(); + ushort y = (ushort)(item.Y & 0x3FFF); + + if (hue != 0) y |= 0x8000; + if (flags != 0) y |= 0x4000; + + y.CopyTo(ref pos, expectedData); + + if (direction != 0) + direction.CopyTo(ref pos, expectedData); + + ((byte)item.Z).CopyTo(ref pos, expectedData); + + if (hue != 0) + ((ushort)hue).CopyTo(ref pos, expectedData); + + if (flags != 0) + ((byte)flags).CopyTo(ref pos, expectedData); + + // Length + ((ushort)pos).CopyTo(expectedData.Slice(1, 2)); + + // Slice the data to match in size + data = data.Slice(0, pos); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestWorldItemSAPacket() + { + Serial serial = 0x1000; + ushort itemId = 1; + + // Move to fixture + TileData.ItemTable[itemId] = new ItemData( + "Test Item Data", TileFlag.Generic, 1, 1, 1, 1, 1 + ); + + Item item = new Item(serial) + { + ItemID = itemId, + Hue = 0x1024, + Amount = 10, + Location = new Point3D(1000, 100, -10) + }; + + var loc = item.Location; + var isMulti = item is BaseMulti; + + Span data = new WorldItemSA(item).Compile(); + + Span expectedData = stackalloc byte[] + { + 0xF3, // Packet ID + 0x00, 0x01, + (byte)(isMulti ? 0x02 : 0x00), // Item Type (Regular, or Multi) + 0x00, 0x00, 0x00, 0x00, // Serial + 0x00, 0x00, // Item ID + 0x00, + 0x00, 0x00, // Amount (min?) + 0x00, 0x00, // Amount (max?) + 0x00, 0x00, // X + 0x00, 0x00, // Y + (byte)loc.Z, // Z + (byte)item.Light, // Light + 0x00, 0x00, // Hue + (byte)item.GetPacketFlags() // Flags + }; + + serial.CopyTo(expectedData.Slice(4, 4)); + ((ushort)(itemId & (isMulti ? 0x3FFF : 0xFFFF))).CopyTo(expectedData.Slice(8, 2)); + + ushort amount = (ushort)item.Amount; + amount.CopyTo(expectedData.Slice(11, 2)); + amount.CopyTo(expectedData.Slice(13, 2)); + + ((ushort)loc.X).CopyTo(expectedData.Slice(15, 2)); + ((ushort)loc.Y).CopyTo(expectedData.Slice(17, 2)); + ((ushort)item.Hue).CopyTo(expectedData.Slice(21, 2)); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestWorldItemHSPacket() + { + Serial serial = 0x1000; + var itemId = 1; + + // Move to fixture + TileData.ItemTable[itemId] = new ItemData( + "Test Item Data", TileFlag.Generic, 1, 1, 1, 1, 1 + ); + + Item item = new Item(serial) + { + ItemID = itemId, + Hue = 0x1024, + Amount = 10, + Location = new Point3D(1000, 100, -10) + }; + + var loc = item.Location; + var isMulti = item is BaseMulti; + + Span data = new WorldItemHS(item).Compile(); + + Span expectedData = stackalloc byte[] + { + 0xF3, // Packet ID + 0x00, 0x01, + (byte)(isMulti ? 0x02 : 0x00), // Item Type (Regular, or Multi) + 0x00, 0x00, 0x00, 0x00, // Serial + 0x00, 0x00, // Item ID + 0x00, + 0x00, 0x00, // Amount (min?) + 0x00, 0x00, // Amount (max?) + 0x00, 0x00, // X + 0x00, 0x00, // Y + (byte)loc.Z, // Z + (byte)item.Light, // Light + 0x00, 0x00, // Hue + (byte)item.GetPacketFlags(), // Flags + 00, 00 // ??? + }; + + serial.CopyTo(expectedData.Slice(4, 4)); + ((ushort)(itemId & (isMulti ? 0x3FFF : 0xFFFF))).CopyTo(expectedData.Slice(8, 2)); + + ushort amount = (ushort)item.Amount; + amount.CopyTo(expectedData.Slice(11, 2)); + amount.CopyTo(expectedData.Slice(13, 2)); + + ((ushort)loc.X).CopyTo(expectedData.Slice(15, 2)); + ((ushort)loc.Y).CopyTo(expectedData.Slice(17, 2)); + ((ushort)item.Hue).CopyTo(expectedData.Slice(21, 2)); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestContainerDisplay() + { + Serial serial = 0x1000; + ushort gumpId = 100; + + Span data = new ContainerDisplay(serial, gumpId).Compile(); + + Span expectedData = stackalloc byte[] + { + 0x24, // Packet ID + 0x00, 0x00, 0x00, 0x00, // Serial + 0x00, 0x00 // Gump ID + }; + + serial.CopyTo(expectedData.Slice(1, 4)); + gumpId.CopyTo(expectedData.Slice(5, 2)); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestContainerDisplayHS() + { + Serial serial = 0x1000; + ushort gumpId = 100; + + Span data = new ContainerDisplayHS(serial, gumpId).Compile(); + + Span expectedData = stackalloc byte[] + { + 0x24, // Packet ID + 0x00, 0x00, 0x00, 0x00, // Serial + 0x00, 0x00, // Gump ID + 0x00, 0x7D // Max Items? + }; + + serial.CopyTo(expectedData.Slice(1, 4)); + gumpId.CopyTo(expectedData.Slice(5, 2)); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestDisplaySpellbook() + { + Serial serial = 0x1000; + + Span data = new DisplaySpellbook(serial).Compile(); + + Span expectedData = stackalloc byte[] + { + 0x24, // Packet ID + 0x00, 0x00, 0x00, 0x00, // Serial + 0xFF, 0xFF // Gump ID + }; + + serial.CopyTo(expectedData.Slice(1, 4)); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestDisplaySpellbookHS() + { + Serial serial = 0x1000; + + Span data = new DisplaySpellbookHS(serial).Compile(); + + Span expectedData = stackalloc byte[] + { + 0x24, // Packet ID + 0x00, 0x00, 0x00, 0x00, // Serial + 0xFF, 0xFF, // Gump ID + 0x00, 0x7D // Max Items? + }; + + serial.CopyTo(expectedData.Slice(1, 4)); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestNewSpellbookContent() + { + Serial serial = 0x1000; + ushort graphic = 100; + ushort offset = 10; + ulong content = 0x123456789ABCDEF0; + + Span data = new NewSpellbookContent(serial, graphic, offset, content).Compile(); + + Span expectedData = stackalloc byte[] + { + 0xBF, // Packet ID + 0x00, 0x17, // Length + 0x00, 0x1B, // Sub-packet + 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, // Serial + 0x00, 0x00, // Graphic + 0x00, 0x00, // Offset + 0x00, 0x00, 0x00, 0x00, // Content + 0x00, 0x00, 0x00, 0x00 // Content + }; + + serial.CopyTo(expectedData.Slice(7, 4)); + graphic.CopyTo(expectedData.Slice(11, 2)); + offset.CopyTo(expectedData.Slice(13, 2)); + content.CopyToLE(expectedData.Slice(15, 8)); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestSpellbookContent() + { + Serial serial = 0x1000; + ushort offset = 10; + ulong content = 0x123456789ABCDEF0; + + Span data = new SpellbookContent(serial, offset, content).Compile(); + + Span expectedData = stackalloc byte[5 + 64 * 19]; // Max size + int pos = 0; + + ((byte)0x3C).CopyTo(ref pos, expectedData); + pos += 4; // Length + spell count + + ushort count = 0; + + for (var i = 0; i < 64; i++) + if ((content & (1ul << i)) != 0) + { + (0x7FFFFFFF - i).CopyTo(ref pos, expectedData); + expectedData.Clear(ref pos, 3); + ((ushort)(i + offset)).CopyTo(ref pos, expectedData); + expectedData.Clear(ref pos, 4); // X, Y + serial.CopyTo(ref pos, expectedData); + expectedData.Clear(ref pos, 2); + count++; + } + + ((ushort)pos).CopyTo(expectedData.Slice(1, 2)); + count.CopyTo(expectedData.Slice(3, 2)); + + expectedData = expectedData.Slice(0, pos); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestSpellbookContent6017() + { + Serial serial = 0x1000; + ushort offset = 10; + ulong content = 0x123456789ABCDEF0; + + Span data = new SpellbookContent6017(serial, offset, content).Compile(); + + Span expectedData = stackalloc byte[5 + 64 * 19]; // Max size + int pos = 0; + + ((byte)0x3C).CopyTo(ref pos, expectedData); + pos += 4; // Length + spell count + + ushort count = 0; + + for (var i = 0; i < 64; i++) + if ((content & (1ul << i)) != 0) + { + (0x7FFFFFFF - i).CopyTo(ref pos, expectedData); + expectedData.Clear(ref pos, 3); + ((ushort)(i + offset)).CopyTo(ref pos, expectedData); + expectedData.Clear(ref pos, 5); // X, Y, Grid Location + serial.CopyTo(ref pos, expectedData); + expectedData.Clear(ref pos, 2); + count++; + } + + ((ushort)pos).CopyTo(expectedData.Slice(1, 2)); + count.CopyTo(expectedData.Slice(3, 2)); + + expectedData = expectedData.Slice(0, pos); + + AssertThat.Equal(data, expectedData); + } + } +} diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/MenuPacketTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/MenuPacketTests.cs index d4a2ef5eb..a13a35938 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/MenuPacketTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/MenuPacketTests.cs @@ -51,22 +51,18 @@ namespace Server.Tests.Network.Packets int pos = 0; - expectedData[pos++] = 0x7C; // Packet ID + ((byte)0x7C).CopyTo(ref pos, expectedData); // Packet ID ((ushort)length).CopyTo(ref pos, expectedData); menu.Serial.CopyTo(ref pos, expectedData); - pos += 2; // ((ushort)0x00).CopyTo(ref pos, expectedData); - expectedData[pos++] = (byte)questionLength; - question.CopyASCIITo(ref pos, expectedData); - expectedData[pos++] = (byte)menu.Entries.Length; + ((ushort)0x00).CopyTo(ref pos, expectedData); + question.CopySmallASCIITo(ref pos, expectedData); + ((byte)menu.Entries.Length).CopyTo(ref pos, expectedData); for (int i = 0; i < menu.Entries.Length; i++) { var entry = menu.Entries[i]; ((ushort)entry.ItemID).CopyTo(ref pos, expectedData); ((ushort)entry.Hue).CopyTo(ref pos, expectedData); - string name = entry.Name?.Trim() ?? ""; - - expectedData[pos++] = (byte)name.Length; - name.CopyASCIITo(ref pos, expectedData); + (entry.Name?.Trim() ?? "").CopySmallASCIITo(ref pos, expectedData); } AssertThat.Equal(data, expectedData); @@ -96,19 +92,16 @@ namespace Server.Tests.Network.Packets int pos = 0; - expectedData[pos++] = 0x7C; // Packet ID + ((byte)0x7C).CopyTo(ref pos, expectedData); // Packet ID ((ushort)length).CopyTo(ref pos, expectedData); menu.Serial.CopyTo(ref pos, expectedData); - pos += 2; // ((ushort)0x00).CopyTo(ref pos, expectedData); - expectedData[pos++] = (byte)questionLength; - question?.CopyASCIITo(ref pos, expectedData); - expectedData[pos++] = (byte)menu.Answers.Length; + ((ushort)0x00).CopyTo(ref pos, expectedData); + question.CopySmallASCIITo(ref pos, expectedData); + ((byte)menu.Answers.Length).CopyTo(ref pos, expectedData); for (int i = 0; i < menu.Answers.Length; i++) { - pos += 4; // 0x0.CopyTo(ref pos, expectedData); - var answer = menu.Answers[i]?.Trim() ?? ""; - expectedData[pos++] = (byte)answer.Length; - answer.CopyASCIITo(ref pos, expectedData); + 0x0.CopyTo(ref pos, expectedData); + (menu.Answers[i]?.Trim() ?? "").CopySmallASCIITo(ref pos, expectedData); } AssertThat.Equal(data, expectedData); @@ -130,14 +123,14 @@ namespace Server.Tests.Network.Packets Span expectedData = stackalloc byte[length]; int pos = 0; - expectedData[pos++] = 0xBF; // Packet ID + ((byte)0xBF).CopyTo(ref pos, expectedData); // Packet ID ((ushort)length).CopyTo(ref pos, expectedData); // Length ((ushort)0x14).CopyTo(ref pos, expectedData); // Command ((ushort)0x02).CopyTo(ref pos, expectedData); // Subcommand menu.Target.Serial.CopyTo(ref pos, expectedData); var entries = menu.Entries; - expectedData[pos++] = (byte)entries.Length; + ((byte)entries.Length).CopyTo(ref pos, expectedData); for (int i = 0; i < entries.Length; i++) { @@ -177,14 +170,14 @@ namespace Server.Tests.Network.Packets Span expectedData = stackalloc byte[length]; int pos = 0; - expectedData[pos++] = 0xBF; // Packet ID + ((byte)0xBF).CopyTo(ref pos, expectedData); // Packet ID ((ushort)length).CopyTo(ref pos, expectedData); // Length ((ushort)0x14).CopyTo(ref pos, expectedData); // Command ((ushort)0x01).CopyTo(ref pos, expectedData); // Subcommand menu.Target.Serial.CopyTo(ref pos, expectedData); var entries = menu.Entries; - expectedData[pos++] = (byte)entries.Length; + ((byte)entries.Length).CopyTo(ref pos, expectedData); for (int i = 0; i < entries.Length; i++) { diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/SecureTradePacketTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/SecureTradePacketTests.cs index 5d9187c9e..1713f6ba3 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/SecureTradePacketTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/SecureTradePacketTests.cs @@ -141,7 +141,7 @@ namespace Server.Tests.Network.Packets int pos = 1; itemInCont.Serial.CopyTo(ref pos, expectedData); ((short)itemInCont.ItemID).CopyTo(ref pos, expectedData); - pos++; // expectedData[pos++] = 0x0; + pos++; ((short)itemInCont.Amount).CopyTo(ref pos, expectedData); ((short)itemInCont.X).CopyTo(ref pos, expectedData); ((short)itemInCont.Y).CopyTo(ref pos, expectedData); diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/VendorBuyPacketTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/VendorBuyPacketTests.cs index ebc3d11a6..b28d364b1 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/VendorBuyPacketTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/VendorBuyPacketTests.cs @@ -27,7 +27,7 @@ namespace Server.Tests.Network.Packets int pos = 0; - expectedData[pos++] = 0x3C; // Packet ID + ((byte)0x3C).CopyTo(ref pos, expectedData); // Packet ID ((ushort)expectedData.Length).CopyTo(ref pos, expectedData); // Length ((ushort)buyStates.Count).CopyTo(ref pos, expectedData); // Count @@ -40,8 +40,8 @@ namespace Server.Tests.Network.Packets pos++; // ItemID Offset ((ushort)buyState.Amount).CopyTo(ref pos, expectedData); ((ushort)(i + 1)).CopyTo(ref pos, expectedData); // X - expectedData[pos++] = 0; - expectedData[pos++] = 1; // Y + ((byte)0).CopyTo(ref pos, expectedData); + ((byte)1).CopyTo(ref pos, expectedData); // Y buyState.ContainerSerial.CopyTo(ref pos, expectedData); ((ushort)buyState.Hue).CopyTo(ref pos, expectedData); } @@ -67,7 +67,7 @@ namespace Server.Tests.Network.Packets int pos = 0; - expectedData[pos++] = 0x3C; // Packet ID + ((byte)0x3C).CopyTo(ref pos, expectedData); // Packet ID ((ushort)expectedData.Length).CopyTo(ref pos, expectedData); // Length ((ushort)buyStates.Count).CopyTo(ref pos, expectedData); // Count @@ -80,9 +80,9 @@ namespace Server.Tests.Network.Packets pos++; // ItemID Offset ((ushort)buyState.Amount).CopyTo(ref pos, expectedData); ((ushort)(i + 1)).CopyTo(ref pos, expectedData); // X - expectedData[pos++] = 0; - expectedData[pos++] = 1; // Y - expectedData[pos++] = 0; // Grid Location + ((byte)0).CopyTo(ref pos, expectedData); + ((byte)1).CopyTo(ref pos, expectedData); // Y + ((byte)0).CopyTo(ref pos, expectedData); // Grid Location buyState.ContainerSerial.CopyTo(ref pos, expectedData); ((ushort)buyState.Hue).CopyTo(ref pos, expectedData); } @@ -148,25 +148,22 @@ namespace Server.Tests.Network.Packets Span data = new VendorBuyList(vendor, buyStates).Compile(); - int length = 8 + 5 * 3 + buyStates.Sum(state => state.Description.Length + 1); + int length = 8 + buyStates.Sum(state => 6 + state.Description.Length); Span expectedData = stackalloc byte[length]; int pos = 0; - expectedData[pos++] = 0x74; // Packet ID + ((byte)0x74).CopyTo(ref pos, expectedData); // Packet ID ((ushort)expectedData.Length).CopyTo(ref pos, expectedData); // Length Serial.MinusOne.CopyTo(ref pos, expectedData); // Vendor Buy Pack Serial or -1 - expectedData[pos++] = (byte)buyStates.Count; + ((byte)buyStates.Count).CopyTo(ref pos, expectedData); for (int i = 0; i < buyStates.Count; i++) { BuyItemState state = buyStates[i]; state.Price.CopyTo(ref pos, expectedData); - string desc = state.Description ?? ""; - expectedData[pos++] = (byte)(desc.Length + 1); - desc.CopyASCIITo(ref pos, expectedData); - pos++; + (state.Description ?? "").CopySmallASCIINullTo(ref pos, expectedData); } AssertThat.Equal(data, expectedData); diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/VendorSellPacketTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/VendorSellPacketTests.cs index ee04014fd..425c17311 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/VendorSellPacketTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/VendorSellPacketTests.cs @@ -34,7 +34,7 @@ namespace Server.Tests.Network.Packets Span expectedData = stackalloc byte[length]; int pos = 0; - expectedData[pos++] = 0x9E; // Packet ID + ((byte)0x9E).CopyTo(ref pos, expectedData); // Packet ID ((ushort)length).CopyTo(ref pos, expectedData); vendor.Serial.CopyTo(ref pos, expectedData); ((ushort)sellStates.Count).CopyTo(ref pos, expectedData); @@ -48,7 +48,6 @@ namespace Server.Tests.Network.Packets ((ushort)state.Item.Amount).CopyTo(ref pos, expectedData); ((ushort)state.Price).CopyTo(ref pos, expectedData); string name = string.IsNullOrWhiteSpace(state.Item.Name) ? state.Name ?? "" : state.Item.Name.Trim(); - ((ushort)name.Length).CopyTo(ref pos, expectedData); name.CopyASCIITo(ref pos, expectedData); } diff --git a/Projects/Server.Tests/Network/Packets/PacketTestUtilities.cs b/Projects/Server.Tests/Network/Packets/PacketTestUtilities.cs index d91b78401..4de648275 100644 --- a/Projects/Server.Tests/Network/Packets/PacketTestUtilities.cs +++ b/Projects/Server.Tests/Network/Packets/PacketTestUtilities.cs @@ -12,6 +12,12 @@ namespace Server.Tests.Network.Packets public static Span Compile(this Packet p) => p.Compile(false, out int length).AsSpan(0, length); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void CopyTo(this byte value, Span bytes) => bytes[0] = value; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void CopyTo(this bool value, Span bytes) => bytes[0] = (byte)(value ? 0x1 : 0x0); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void CopyTo(this ushort number, Span bytes) => BinaryPrimitives.WriteUInt16BigEndian(bytes, number); @@ -28,12 +34,39 @@ namespace Server.Tests.Network.Packets public static void CopyTo(this int number, Span bytes) => BinaryPrimitives.WriteInt32BigEndian(bytes, number); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void CopyASCIITo(this string str, Span bytes) => Encoding.ASCII.GetBytes(str.AsSpan(), bytes); + public static void CopyTo(this ulong number, Span bytes) => BinaryPrimitives.WriteUInt64BigEndian(bytes, number); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void CopyASCIITo(this string str, int max, Span bytes) => Encoding.ASCII.GetBytes(str.AsSpan(0, Math.Min(str.Length, max)), bytes); + public static void CopyTo(this long number, Span bytes) => BinaryPrimitives.WriteInt64BigEndian(bytes, number); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void CopyToLE(this ushort number, Span bytes) => BinaryPrimitives.WriteUInt16LittleEndian(bytes, number); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void CopyToLE(this short number, Span bytes) => BinaryPrimitives.WriteInt16LittleEndian(bytes, number); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void CopyToLE(this Serial s, Span bytes) => BinaryPrimitives.WriteUInt32LittleEndian(bytes, s); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void CopyToLE(this uint number, Span bytes) => BinaryPrimitives.WriteUInt32LittleEndian(bytes, number); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void CopyToLE(this int number, Span bytes) => BinaryPrimitives.WriteInt32LittleEndian(bytes, number); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void CopyToLE(this ulong number, Span bytes) => BinaryPrimitives.WriteUInt64LittleEndian(bytes, number); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void CopyToLE(this long number, Span bytes) => BinaryPrimitives.WriteInt64LittleEndian(bytes, number); // With Position Reference + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void CopyTo(this byte value, ref int pos, Span bytes) => bytes[pos++] = value; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void CopyTo(this bool value, ref int pos, Span bytes) => bytes[pos++] = (byte)(value ? 0x1 : 0x0); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void CopyTo(this ushort number, ref int pos, Span bytes) { @@ -70,17 +103,97 @@ namespace Server.Tests.Network.Packets } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void CopyASCIITo(this string str, ref int pos, Span bytes) + public static void CopyTo(this ulong number, ref int pos, Span bytes) + { + BinaryPrimitives.WriteUInt64BigEndian(bytes.Slice(pos, 8), number); + pos += 8; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void CopyTo(this long number, ref int pos, Span bytes) + { + BinaryPrimitives.WriteInt64BigEndian(bytes.Slice(pos, 8), number); + pos += 8; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void CopyRawASCIITo(this string str, ref int pos, Span bytes) { pos += Encoding.ASCII.GetBytes(str.AsSpan(), bytes.Slice(pos)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void CopyASCIITo(this string str, ref int pos, int max, Span bytes) + public static void CopyRawASCIITo(this string str, ref int pos, int max, Span bytes) { pos += Encoding.ASCII.GetBytes(str.AsSpan(0, Math.Min(str.Length, max)), bytes.Slice(pos)); } + // Ascii prepended with two-byte length + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void CopyASCIITo(this string str, ref int pos, Span bytes) + { + BinaryPrimitives.WriteUInt16BigEndian(bytes.Slice(pos, 2), (ushort)str.Length); + pos += 2 + Encoding.ASCII.GetBytes(str.AsSpan(), bytes.Slice(pos + 2)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void CopyASCIITo(this string str, ref int pos, int max, Span bytes) + { + var length = Math.Min(str.Length, max); + BinaryPrimitives.WriteUInt16BigEndian(bytes.Slice(pos, 2), (ushort)length); + pos += 2 + Encoding.ASCII.GetBytes(str.AsSpan(0, length), bytes.Slice(pos + 2)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void CopyASCIINullTo(this string str, ref int pos, Span bytes) + { + BinaryPrimitives.WriteUInt16BigEndian(bytes.Slice(pos, 2), (ushort)(str.Length + 1)); + pos += 3 + Encoding.ASCII.GetBytes(str.AsSpan(), bytes.Slice(pos + 2)); + bytes[pos - 1] = 0; // null terminator + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void CopyASCIINullTo(this string str, ref int pos, int max, Span bytes) + { + var length = Math.Min(str.Length, max - 1); + BinaryPrimitives.WriteUInt16BigEndian(bytes.Slice(pos, 2), (ushort)(length + 1)); + pos += 3 + Encoding.ASCII.GetBytes(str.AsSpan(0, length), bytes.Slice(pos + 2)); + bytes[pos - 1] = 0; // null terminator + } + + // Ascii prepended with one-byte length + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void CopySmallASCIITo(this string str, ref int pos, Span bytes) + { + bytes[pos++] = (byte)str.Length; + pos += Encoding.ASCII.GetBytes(str.AsSpan(), bytes.Slice(pos)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void CopySmallASCIITo(this string str, ref int pos, int max, Span bytes) + { + var length = Math.Min(255, Math.Min(str.Length, max)); + bytes[pos++] = (byte)length; + pos += Encoding.ASCII.GetBytes(str.AsSpan(0, length), bytes.Slice(pos)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void CopySmallASCIINullTo(this string str, ref int pos, Span bytes) + { + bytes[pos++] = (byte)(str.Length + 1); + pos += Encoding.ASCII.GetBytes(str.AsSpan(), bytes.Slice(pos)); + bytes[pos++] = 0; // null terminator + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void CopySmallASCIINullTo(this string str, ref int pos, int max, Span bytes) + { + var length = Math.Min(255, Math.Min(str.Length, max)); + bytes[pos++] = (byte)length; + pos += Encoding.ASCII.GetBytes(str.AsSpan(0, length), bytes.Slice(pos)); + bytes[pos++] = 0; // null terminator + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void CopyASCIIFixedTo(this string str, ref int pos, int max, Span bytes) { @@ -93,6 +206,38 @@ namespace Server.Tests.Network.Packets pos += max; } + // Unicode prepended with two-byte length + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void CopyUnicodeBigEndianTo(this string str, ref int pos, Span bytes) + { + BinaryPrimitives.WriteUInt16BigEndian(bytes.Slice(pos, 2), (ushort)str.Length); + pos += 2 + Encoding.BigEndianUnicode.GetBytes(str.AsSpan(), bytes.Slice(pos + 2)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void CopyTo(this byte[] src, ref int pos, Span bytes) => + src.CopyTo(bytes.Slice(pos, src.Length)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void CopyTo(this byte[] src, ref int pos, int max, Span bytes) => + src.CopyTo(bytes.Slice(pos, Math.Min(max, src.Length))); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void CopyTo(this Span src, ref int pos, Span bytes) => + src.CopyTo(bytes.Slice(pos, src.Length)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void CopyTo(this Span src, ref int pos, int max, Span bytes) => + src.CopyTo(bytes.Slice(pos, Math.Min(max, src.Length))); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void CopyTo(this ReadOnlySpan src, ref int pos, Span bytes) => + src.CopyTo(bytes.Slice(pos, src.Length)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void CopyTo(this ReadOnlySpan src, ref int pos, int max, Span bytes) => + src.CopyTo(bytes.Slice(pos, Math.Min(max, src.Length))); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Clear(this Span span, ref int pos, int amount) { diff --git a/Projects/Server.Tests/Server.Tests.csproj b/Projects/Server.Tests/Server.Tests.csproj index a59ee959a..84471dbb2 100644 --- a/Projects/Server.Tests/Server.Tests.csproj +++ b/Projects/Server.Tests/Server.Tests.csproj @@ -7,6 +7,7 @@ + diff --git a/Projects/Server.Tests/packages.lock.json b/Projects/Server.Tests/packages.lock.json index b0d0f88ae..31e6ee695 100644 --- a/Projects/Server.Tests/packages.lock.json +++ b/Projects/Server.Tests/packages.lock.json @@ -35,6 +35,12 @@ "resolved": "2.4.2", "contentHash": "Trt9multph2KE3U0p9oBt0k4Fq6lUv4btUcONaQEeuFnMCak2k/b7PAArbLtMFW7HO1jxlBHUgIPKEqci3Y1dg==" }, + "Zlib.Bindings": { + "type": "Direct", + "requested": "[1.1.0, )", + "resolved": "1.1.0", + "contentHash": "hLmHUTlZR3rnJ95FboiyJdLR8MJbfHdmapnRZHWLvkxB48jDgRBBJG1w5NYRiNBteVY4uksacXM7/V8nu1byBw==" + }, "Libuv": { "type": "Transitive", "resolved": "1.10.0", @@ -1181,11 +1187,6 @@ "xunit.extensibility.core": "[2.4.1]" } }, - "Zlib.Bindings": { - "type": "Transitive", - "resolved": "1.1.0", - "contentHash": "hLmHUTlZR3rnJ95FboiyJdLR8MJbfHdmapnRZHWLvkxB48jDgRBBJG1w5NYRiNBteVY4uksacXM7/V8nu1byBw==" - }, "ModernUO": { "type": "Project", "dependencies": { @@ -1198,6 +1199,12 @@ } }, ".NETCoreApp,Version=v3.1/centos.7-x64": { + "Zlib.Bindings": { + "type": "Direct", + "requested": "[1.1.0, )", + "resolved": "1.1.0", + "contentHash": "hLmHUTlZR3rnJ95FboiyJdLR8MJbfHdmapnRZHWLvkxB48jDgRBBJG1w5NYRiNBteVY4uksacXM7/V8nu1byBw==" + }, "Libuv": { "type": "Transitive", "resolved": "1.10.0", @@ -2109,14 +2116,15 @@ "System.Runtime": "4.3.0", "runtime.any.System.Threading.Timer": "4.3.0" } - }, - "Zlib.Bindings": { - "type": "Transitive", - "resolved": "1.1.0", - "contentHash": "hLmHUTlZR3rnJ95FboiyJdLR8MJbfHdmapnRZHWLvkxB48jDgRBBJG1w5NYRiNBteVY4uksacXM7/V8nu1byBw==" } }, ".NETCoreApp,Version=v3.1/centos.8-x64": { + "Zlib.Bindings": { + "type": "Direct", + "requested": "[1.1.0, )", + "resolved": "1.1.0", + "contentHash": "hLmHUTlZR3rnJ95FboiyJdLR8MJbfHdmapnRZHWLvkxB48jDgRBBJG1w5NYRiNBteVY4uksacXM7/V8nu1byBw==" + }, "Libuv": { "type": "Transitive", "resolved": "1.10.0", @@ -2983,14 +2991,15 @@ "System.Runtime": "4.3.0", "runtime.any.System.Threading.Timer": "4.3.0" } - }, - "Zlib.Bindings": { - "type": "Transitive", - "resolved": "1.1.0", - "contentHash": "hLmHUTlZR3rnJ95FboiyJdLR8MJbfHdmapnRZHWLvkxB48jDgRBBJG1w5NYRiNBteVY4uksacXM7/V8nu1byBw==" } }, ".NETCoreApp,Version=v3.1/debian.10-x64": { + "Zlib.Bindings": { + "type": "Direct", + "requested": "[1.1.0, )", + "resolved": "1.1.0", + "contentHash": "hLmHUTlZR3rnJ95FboiyJdLR8MJbfHdmapnRZHWLvkxB48jDgRBBJG1w5NYRiNBteVY4uksacXM7/V8nu1byBw==" + }, "Libuv": { "type": "Transitive", "resolved": "1.10.0", @@ -3857,14 +3866,15 @@ "System.Runtime": "4.3.0", "runtime.any.System.Threading.Timer": "4.3.0" } - }, - "Zlib.Bindings": { - "type": "Transitive", - "resolved": "1.1.0", - "contentHash": "hLmHUTlZR3rnJ95FboiyJdLR8MJbfHdmapnRZHWLvkxB48jDgRBBJG1w5NYRiNBteVY4uksacXM7/V8nu1byBw==" } }, ".NETCoreApp,Version=v3.1/debian.9-x64": { + "Zlib.Bindings": { + "type": "Direct", + "requested": "[1.1.0, )", + "resolved": "1.1.0", + "contentHash": "hLmHUTlZR3rnJ95FboiyJdLR8MJbfHdmapnRZHWLvkxB48jDgRBBJG1w5NYRiNBteVY4uksacXM7/V8nu1byBw==" + }, "Libuv": { "type": "Transitive", "resolved": "1.10.0", @@ -4731,14 +4741,15 @@ "System.Runtime": "4.3.0", "runtime.any.System.Threading.Timer": "4.3.0" } - }, - "Zlib.Bindings": { - "type": "Transitive", - "resolved": "1.1.0", - "contentHash": "hLmHUTlZR3rnJ95FboiyJdLR8MJbfHdmapnRZHWLvkxB48jDgRBBJG1w5NYRiNBteVY4uksacXM7/V8nu1byBw==" } }, ".NETCoreApp,Version=v3.1/osx-x64": { + "Zlib.Bindings": { + "type": "Direct", + "requested": "[1.1.0, )", + "resolved": "1.1.0", + "contentHash": "hLmHUTlZR3rnJ95FboiyJdLR8MJbfHdmapnRZHWLvkxB48jDgRBBJG1w5NYRiNBteVY4uksacXM7/V8nu1byBw==" + }, "Libuv": { "type": "Transitive", "resolved": "1.10.0", @@ -5605,14 +5616,15 @@ "System.Runtime": "4.3.0", "runtime.any.System.Threading.Timer": "4.3.0" } - }, - "Zlib.Bindings": { - "type": "Transitive", - "resolved": "1.1.0", - "contentHash": "hLmHUTlZR3rnJ95FboiyJdLR8MJbfHdmapnRZHWLvkxB48jDgRBBJG1w5NYRiNBteVY4uksacXM7/V8nu1byBw==" } }, ".NETCoreApp,Version=v3.1/ubuntu.16.04-x64": { + "Zlib.Bindings": { + "type": "Direct", + "requested": "[1.1.0, )", + "resolved": "1.1.0", + "contentHash": "hLmHUTlZR3rnJ95FboiyJdLR8MJbfHdmapnRZHWLvkxB48jDgRBBJG1w5NYRiNBteVY4uksacXM7/V8nu1byBw==" + }, "Libuv": { "type": "Transitive", "resolved": "1.10.0", @@ -6524,14 +6536,15 @@ "System.Runtime": "4.3.0", "runtime.any.System.Threading.Timer": "4.3.0" } - }, - "Zlib.Bindings": { - "type": "Transitive", - "resolved": "1.1.0", - "contentHash": "hLmHUTlZR3rnJ95FboiyJdLR8MJbfHdmapnRZHWLvkxB48jDgRBBJG1w5NYRiNBteVY4uksacXM7/V8nu1byBw==" } }, ".NETCoreApp,Version=v3.1/ubuntu.18.04-x64": { + "Zlib.Bindings": { + "type": "Direct", + "requested": "[1.1.0, )", + "resolved": "1.1.0", + "contentHash": "hLmHUTlZR3rnJ95FboiyJdLR8MJbfHdmapnRZHWLvkxB48jDgRBBJG1w5NYRiNBteVY4uksacXM7/V8nu1byBw==" + }, "Libuv": { "type": "Transitive", "resolved": "1.10.0", @@ -7398,14 +7411,15 @@ "System.Runtime": "4.3.0", "runtime.any.System.Threading.Timer": "4.3.0" } - }, - "Zlib.Bindings": { - "type": "Transitive", - "resolved": "1.1.0", - "contentHash": "hLmHUTlZR3rnJ95FboiyJdLR8MJbfHdmapnRZHWLvkxB48jDgRBBJG1w5NYRiNBteVY4uksacXM7/V8nu1byBw==" } }, ".NETCoreApp,Version=v3.1/win-x64": { + "Zlib.Bindings": { + "type": "Direct", + "requested": "[1.1.0, )", + "resolved": "1.1.0", + "contentHash": "hLmHUTlZR3rnJ95FboiyJdLR8MJbfHdmapnRZHWLvkxB48jDgRBBJG1w5NYRiNBteVY4uksacXM7/V8nu1byBw==" + }, "Libuv": { "type": "Transitive", "resolved": "1.10.0", @@ -8255,11 +8269,6 @@ "System.Runtime": "4.3.0", "runtime.any.System.Threading.Timer": "4.3.0" } - }, - "Zlib.Bindings": { - "type": "Transitive", - "resolved": "1.1.0", - "contentHash": "hLmHUTlZR3rnJ95FboiyJdLR8MJbfHdmapnRZHWLvkxB48jDgRBBJG1w5NYRiNBteVY4uksacXM7/V8nu1byBw==" } } } diff --git a/Projects/Server/Gumps/Gump.cs b/Projects/Server/Gumps/Gump.cs index 17d121032..d060a9e03 100644 --- a/Projects/Server/Gumps/Gump.cs +++ b/Projects/Server/Gumps/Gump.cs @@ -37,7 +37,7 @@ namespace Server.Gumps private static readonly byte[] m_NoDispose = StringToBuffer("{ nodispose }"); private static readonly byte[] m_NoResize = StringToBuffer("{ noresize }"); - private readonly List m_Strings; + public List Strings { get; } internal int m_TextEntries, m_Switches; @@ -54,7 +54,7 @@ namespace Server.Gumps TypeID = GetTypeID(GetType()); Entries = new List(); - m_Strings = new List(); + Strings = new List(); } public int TypeID { get; } @@ -206,13 +206,9 @@ namespace Server.Gumps public void Add(GumpEntry g) { if (g.Parent != this) - { g.Parent = this; - } else if (!Entries.Contains(g)) - { Entries.Add(g); - } } public void Remove(GumpEntry g) @@ -226,12 +222,12 @@ namespace Server.Gumps public int Intern(string value) { - var indexOf = m_Strings.IndexOf(value); + var indexOf = Strings.IndexOf(value); if (indexOf >= 0) return indexOf; - m_Strings.Add(value); - return m_Strings.Count - 1; + Strings.Add(value); + return Strings.Count - 1; } public void SendTo(NetState state) @@ -242,7 +238,7 @@ namespace Server.Gumps public static byte[] StringToBuffer(string str) => Encoding.ASCII.GetBytes(str); - private Packet Compile(NetState ns = null) + public Packet Compile(NetState ns = null) { IGumpWriter disp; @@ -274,7 +270,7 @@ namespace Server.Gumps disp.AppendLayout(m_EndLayout); } - disp.WriteStrings(m_Strings); + disp.WriteStrings(Strings); disp.Flush(); diff --git a/Projects/Server/Items/Container.cs b/Projects/Server/Items/Container.cs index 26d7e1368..548626464 100644 --- a/Projects/Server/Items/Container.cs +++ b/Projects/Server/Items/Container.cs @@ -634,9 +634,9 @@ namespace Server.Items if (ns != null) { if (ns.HighSeas) - to.Send(new ContainerDisplayHS(this)); + to.Send(new ContainerDisplayHS(Serial, GumpID)); else - to.Send(new ContainerDisplay(this)); + to.Send(new ContainerDisplay(Serial, GumpID)); SendContentTo(ns); diff --git a/Projects/Server/Main.cs b/Projects/Server/Main.cs index f0edc52d7..1681f59e5 100644 --- a/Projects/Server/Main.cs +++ b/Projects/Server/Main.cs @@ -47,6 +47,11 @@ namespace Server private static bool m_Profiling; private static DateTime m_ProfileStart; private static TimeSpan m_ProfileTime; + private static bool? m_IsRunningFromXUnit; + + public static bool IsRunningFromXUnit => + m_IsRunningFromXUnit ??= AppDomain.CurrentDomain.GetAssemblies().Any( + a => a.FullName?.ToLowerInvariant().StartsWith("xunit") ?? false); /* * DateTime.Now and DateTime.UtcNow are based on actual system clock time. diff --git a/Projects/Server/Network/Packets/Old Packets/GumpPackets.cs b/Projects/Server/Network/Packets/Old Packets/GumpPackets.cs index dfff3af54..d31126cb4 100644 --- a/Projects/Server/Network/Packets/Old Packets/GumpPackets.cs +++ b/Projects/Server/Network/Packets/Old Packets/GumpPackets.cs @@ -331,14 +331,14 @@ namespace Server.Network unknown ??= ""; caption ??= ""; - EnsureCapacity(16 + unknown.Length + caption.Length); + EnsureCapacity(15 + unknown.Length + caption.Length); Stream.Write(serial); Stream.Write((short)gumpID); - Stream.Write((short)unknown.Length); - Stream.WriteAsciiFixed(unknown, unknown.Length); + Stream.Write((short)(unknown.Length + 1)); + Stream.WriteAsciiNull(unknown); Stream.Write((short)(caption.Length + 1)); - Stream.WriteAsciiFixed(caption, caption.Length + 1); + Stream.WriteAsciiNull(caption); } } } diff --git a/Projects/Server/Network/Packets/Old Packets/ItemPackets.cs b/Projects/Server/Network/Packets/Old Packets/ItemPackets.cs index 087d9c754..05045742d 100644 --- a/Projects/Server/Network/Packets/Old Packets/ItemPackets.cs +++ b/Projects/Server/Network/Packets/Old Packets/ItemPackets.cs @@ -105,14 +105,6 @@ namespace Server.Network Stream.Write((short)itemID); Stream.Write((byte)0); - /*} else if ( ) { - m_Stream.Write( (byte) 0x01 ); - - m_Stream.Write( (int) item.Serial ); - - m_Stream.Write( (short) itemID ); - - m_Stream.Write( (byte) item.Direction );*/ } else { @@ -132,10 +124,8 @@ namespace Server.Network Stream.Write((short)amount); var loc = item.Location; - var x = loc.m_X & 0x7FFF; - var y = loc.m_Y & 0x3FFF; - Stream.Write((short)x); - Stream.Write((short)y); + Stream.Write((short)loc.m_X); + Stream.Write((short)loc.m_Y); Stream.Write((sbyte)loc.m_Z); Stream.Write((byte)item.Light); @@ -163,14 +153,6 @@ namespace Server.Network Stream.Write((ushort)itemID); Stream.Write((byte)0); - /*} else if ( ) { - m_Stream.Write( (byte) 0x01 ); - - m_Stream.Write( (int) item.Serial ); - - m_Stream.Write( (ushort) itemID ); - - m_Stream.Write( (byte) item.Direction );*/ } else { @@ -190,10 +172,8 @@ namespace Server.Network Stream.Write((short)amount); var loc = item.Location; - var x = loc.m_X & 0x7FFF; - var y = loc.m_Y & 0x3FFF; - Stream.Write((short)x); - Stream.Write((short)y); + Stream.Write((short)loc.m_X); + Stream.Write((short)loc.m_Y); Stream.Write((sbyte)loc.m_Z); Stream.Write((byte)item.Light); @@ -206,18 +186,18 @@ namespace Server.Network public sealed class DisplaySpellbook : Packet { - public DisplaySpellbook(Item book) : base(0x24, 7) + public DisplaySpellbook(Serial book) : base(0x24, 7) { - Stream.Write(book.Serial); + Stream.Write(book); Stream.Write((short)-1); } } public sealed class DisplaySpellbookHS : Packet { - public DisplaySpellbookHS(Item book) : base(0x24, 9) + public DisplaySpellbookHS(Serial book) : base(0x24, 9) { - Stream.Write(book.Serial); + Stream.Write(book); Stream.Write((short)-1); Stream.Write((short)0x7D); } @@ -225,14 +205,14 @@ namespace Server.Network public sealed class NewSpellbookContent : Packet { - public NewSpellbookContent(Item item, int graphic, int offset, ulong content) : base(0xBF) + public NewSpellbookContent(Serial spellbook, int graphic, int offset, ulong content) : base(0xBF) { EnsureCapacity(23); Stream.Write((short)0x1B); Stream.Write((short)0x01); - Stream.Write(item.Serial); + Stream.Write(spellbook); Stream.Write((short)graphic); Stream.Write((short)offset); @@ -243,9 +223,9 @@ namespace Server.Network public sealed class SpellbookContent : Packet { - public SpellbookContent(int count, int offset, ulong content, Item item) : base(0x3C) + public SpellbookContent(Serial spellbook, int offset, ulong content) : base(0x3C) { - EnsureCapacity(5 + count * 19); + EnsureCapacity(5 + 64 * 19); var written = 0; @@ -262,7 +242,7 @@ namespace Server.Network Stream.Write((ushort)(i + offset)); Stream.Write((short)0); Stream.Write((short)0); - Stream.Write(item.Serial); + Stream.Write(spellbook); Stream.Write((short)0); ++written; @@ -275,9 +255,9 @@ namespace Server.Network public sealed class SpellbookContent6017 : Packet { - public SpellbookContent6017(int count, int offset, ulong content, Item item) : base(0x3C) + public SpellbookContent6017(Serial spellbook, int offset, ulong content) : base(0x3C) { - EnsureCapacity(5 + count * 20); + EnsureCapacity(5 + 64 * 20); var written = 0; @@ -295,7 +275,7 @@ namespace Server.Network Stream.Write((short)0); Stream.Write((short)0); Stream.Write((byte)0); // Grid Location? - Stream.Write(item.Serial); + Stream.Write(spellbook); Stream.Write((short)0); ++written; @@ -308,19 +288,19 @@ namespace Server.Network public sealed class ContainerDisplay : Packet { - public ContainerDisplay(Container c) : base(0x24, 7) + public ContainerDisplay(Serial cont, int gumpId) : base(0x24, 7) { - Stream.Write(c.Serial); - Stream.Write((short)c.GumpID); + Stream.Write(cont); + Stream.Write((short)gumpId); } } public sealed class ContainerDisplayHS : Packet { - public ContainerDisplayHS(Container c) : base(0x24, 9) + public ContainerDisplayHS(Serial cont, int gumpId) : base(0x24, 9) { - Stream.Write(c.Serial); - Stream.Write((short)c.GumpID); + Stream.Write(cont); + Stream.Write((short)gumpId); Stream.Write((short)0x7D); } } diff --git a/Projects/Server/TileData.cs b/Projects/Server/TileData.cs index 2ff53d08b..9b2a467eb 100644 --- a/Projects/Server/TileData.cs +++ b/Projects/Server/TileData.cs @@ -20,6 +20,7 @@ using System; using System.IO; +using System.Linq; using System.Text; namespace Server @@ -181,108 +182,56 @@ namespace Server static TileData() { + ItemTable = new ItemData[0x10000]; + LandTable = new LandData[0x4000]; + + if (Core.IsRunningFromXUnit) return; + var filePath = Core.FindDataFile("tiledata.mul"); using var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read); var bin = new BinaryReader(fs); - if (fs.Length == 3188736) + var is7090 = fs.Length == 3188736; + bool is7000 = fs.Length == 1644544; + + for (var i = 0; i < 0x4000; i++) { - // 7.0.9.0 - LandTable = new LandData[0x4000]; - - for (var i = 0; i < 0x4000; ++i) + // header + if (is7090) { - if (i == 1 || i > 0 && (i & 0x1F) == 0) bin.ReadInt32(); // header - - var flags = (TileFlag)bin.ReadInt64(); - bin.ReadInt16(); // skip 2 bytes -- textureID - - LandTable[i] = new LandData(ReadNameString(bin), flags); + if (i == 1 || i > 0 && (i & 0x1F) == 0) + bin.ReadInt32(); } - - ItemTable = new ItemData[0x10000]; - - for (var i = 0; i < 0x10000; ++i) - { - if ((i & 0x1F) == 0) bin.ReadInt32(); // header - - var flags = (TileFlag)bin.ReadInt64(); - int weight = bin.ReadByte(); - int quality = bin.ReadByte(); - bin.ReadInt16(); - bin.ReadByte(); - int quantity = bin.ReadByte(); + else if ((i & 0x1F) == 0) bin.ReadInt32(); - bin.ReadByte(); - int value = bin.ReadByte(); - int height = bin.ReadByte(); - ItemTable[i] = new ItemData(ReadNameString(bin), flags, weight, quality, quantity, value, - height); - } + var flags = (TileFlag)(is7090 ? bin.ReadInt64() : bin.ReadInt32()); + bin.ReadInt16(); // skip 2 bytes -- textureID + + LandTable[i] = new LandData(ReadNameString(bin), flags); } - else + + int length = is7090 ? 0x10000 : is7000 ? 0x8000 : 0x4000; + + for (var i = 0; i < length; i++) { - LandTable = new LandData[0x4000]; + if ((i & 0x1F) == 0) bin.ReadInt32(); // header - for (var i = 0; i < 0x4000; ++i) - { - if ((i & 0x1F) == 0) bin.ReadInt32(); // header + var flags = (TileFlag)(is7090 ? bin.ReadInt64() : bin.ReadInt32()); + int weight = bin.ReadByte(); + int quality = bin.ReadByte(); + bin.ReadInt16(); + bin.ReadByte(); + int quantity = bin.ReadByte(); + bin.ReadInt32(); + bin.ReadByte(); + int value = bin.ReadByte(); + int height = bin.ReadByte(); - var flags = (TileFlag)bin.ReadInt32(); - bin.ReadInt16(); // skip 2 bytes -- textureID - - LandTable[i] = new LandData(ReadNameString(bin), flags); - } - - if (fs.Length == 1644544) - { - // 7.0.0.0 - ItemTable = new ItemData[0x8000]; - - for (var i = 0; i < 0x8000; ++i) - { - if ((i & 0x1F) == 0) bin.ReadInt32(); // header - - var flags = (TileFlag)bin.ReadInt32(); - int weight = bin.ReadByte(); - int quality = bin.ReadByte(); - bin.ReadInt16(); - bin.ReadByte(); - int quantity = bin.ReadByte(); - bin.ReadInt32(); - bin.ReadByte(); - int value = bin.ReadByte(); - int height = bin.ReadByte(); - - ItemTable[i] = new ItemData(ReadNameString(bin), flags, weight, quality, quantity, value, - height); - } - } - else - { - ItemTable = new ItemData[0x4000]; - - for (var i = 0; i < 0x4000; ++i) - { - if ((i & 0x1F) == 0) bin.ReadInt32(); // header - - var flags = (TileFlag)bin.ReadInt32(); - int weight = bin.ReadByte(); - int quality = bin.ReadByte(); - bin.ReadInt16(); - bin.ReadByte(); - int quantity = bin.ReadByte(); - bin.ReadInt32(); - bin.ReadByte(); - int value = bin.ReadByte(); - int height = bin.ReadByte(); - - ItemTable[i] = new ItemData(ReadNameString(bin), flags, weight, quality, quantity, value, - height); - } - } + ItemTable[i] = new ItemData( + ReadNameString(bin), flags, weight, quality, quantity, value, height + ); } MaxLandValue = LandTable.Length - 1; diff --git a/Projects/UOContent.Tests/UOContent.Tests.csproj b/Projects/UOContent.Tests/UOContent.Tests.csproj index 878e6ee1c..648fdfa1a 100644 --- a/Projects/UOContent.Tests/UOContent.Tests.csproj +++ b/Projects/UOContent.Tests/UOContent.Tests.csproj @@ -5,8 +5,8 @@ - - + + diff --git a/Projects/UOContent.Tests/packages.lock.json b/Projects/UOContent.Tests/packages.lock.json index d81049123..8b39c2e81 100644 --- a/Projects/UOContent.Tests/packages.lock.json +++ b/Projects/UOContent.Tests/packages.lock.json @@ -4,9 +4,9 @@ ".NETCoreApp,Version=v3.1": { "coverlet.collector": { "type": "Direct", - "requested": "[1.2.1, )", - "resolved": "1.2.1", - "contentHash": "a4JYYZbEXk2UsrTEHlKrQxBVROeQkAg/Qwrf/XgZHGDXNctIrIu9MCihNKpFXC6cgj6wuXmWcPN++T9wOnhskA==" + "requested": "[1.3.0, )", + "resolved": "1.3.0", + "contentHash": "t8pnf5SX2ya0RX4vjoxsbhDMQCZJcpPun2neHKJ4FouMmObylo25FvoOydvf3Bl+l+IzWw7u2vjEeCBHnleB9g==" }, "Microsoft.NET.Test.Sdk": { "type": "Direct", @@ -31,12 +31,9 @@ }, "xunit.runner.visualstudio": { "type": "Direct", - "requested": "[2.4.1, )", - "resolved": "2.4.1", - "contentHash": "mBXd1lp1TQr4to2nFv+c4Tf+RnPoQPKglzwLdbdirOUxRaJsCUNDUx2y7E6j9ajgISlTTp1CydFBZCRCUIrwDg==", - "dependencies": { - "Microsoft.NET.Test.Sdk": "15.0.0" - } + "requested": "[2.4.2, )", + "resolved": "2.4.2", + "contentHash": "Trt9multph2KE3U0p9oBt0k4Fq6lUv4btUcONaQEeuFnMCak2k/b7PAArbLtMFW7HO1jxlBHUgIPKEqci3Y1dg==" }, "Argon2.Bindings": { "type": "Transitive", diff --git a/Projects/UOContent/Items/Skill Items/Magical/Spellbook.cs b/Projects/UOContent/Items/Skill Items/Magical/Spellbook.cs index 38e2c4e86..997e736df 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Spellbook.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Spellbook.cs @@ -603,30 +603,30 @@ namespace Server.Items } if (ns.HighSeas) - to.Send(new DisplaySpellbookHS(this)); + to.Send(new DisplaySpellbookHS(Serial)); else - to.Send(new DisplaySpellbook(this)); + to.Send(new DisplaySpellbook(Serial)); if (ObjectPropertyList.Enabled) { if (ns.NewSpellbook) { - to.Send(new NewSpellbookContent(this, ItemID, BookOffset + 1, m_Content)); + to.Send(new NewSpellbookContent(Serial, ItemID, BookOffset + 1, m_Content)); } else { if (ns.ContainerGridLines) - to.Send(new SpellbookContent6017(SpellCount, BookOffset + 1, m_Content, this)); + to.Send(new SpellbookContent6017(Serial, BookOffset + 1, m_Content)); else - to.Send(new SpellbookContent(SpellCount, BookOffset + 1, m_Content, this)); + to.Send(new SpellbookContent(Serial, BookOffset + 1, m_Content)); } } else { if (ns.ContainerGridLines) - to.Send(new SpellbookContent6017(SpellCount, BookOffset + 1, m_Content, this)); + to.Send(new SpellbookContent6017(Serial, BookOffset + 1, m_Content)); else - to.Send(new SpellbookContent(SpellCount, BookOffset + 1, m_Content, this)); + to.Send(new SpellbookContent(Serial, BookOffset + 1, m_Content)); } }