using System; using System.Buffers; using System.Collections.Generic; using System.Linq; using Server.Gumps; using Server.Network; using Xunit; namespace Server.Tests.Network { public class GumpPacketTests { [Fact] public void TestCloseGump() { var typeId = 100; var buttonId = 10; var data = new CloseGump(typeId, buttonId).Compile(); Span expectedData = stackalloc byte[13]; var pos = 0; expectedData.Write(ref pos, (byte)0xBF); // Packet ID expectedData.Write(ref pos, (ushort)0xD); // Length expectedData.Write(ref pos, (ushort)0x4); // Close Gump expectedData.Write(ref pos, typeId); expectedData.Write(ref pos, buttonId); 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"; var data = new DisplaySignGump(gumpSerial, gumpId, unknownString, caption).Compile(); Span expectedData = stackalloc byte[15 + unknownString.Length + caption.Length]; var pos = 0; expectedData.Write(ref pos, (byte)0x8B); expectedData.Write(ref pos, (ushort)expectedData.Length); expectedData.Write(ref pos, gumpSerial); expectedData.Write(ref pos, (ushort)gumpId); expectedData.Write(ref pos, (ushort)(unknownString.Length + 1)); expectedData.WriteAsciiNull(ref pos, unknownString); expectedData.Write(ref pos, (ushort)(caption.Length + 1)); expectedData.WriteAsciiNull(ref pos, caption); AssertThat.Equal(data, expectedData); } [Fact] public void TestFastGumpPacket() { var ns = new NetState(null); var gump = new ResurrectGump(2); var data = gump.Compile(ns).Compile(); Span expectedData = stackalloc byte[0x1000]; var pos = 0; expectedData[pos++] = 0xB0; // Packet ID pos += 2; // Length expectedData.Write(ref pos, gump.Serial); expectedData.Write(ref pos, gump.TypeID); expectedData.Write(ref pos, gump.X); expectedData.Write(ref pos, gump.Y); pos += 2; // Layout Length var layoutLength = 0; if (!gump.Draggable) { expectedData.Write(ref pos, GumpUtilities.NoMoveBuffer); layoutLength += GumpUtilities.NoMove.Length; } if (!gump.Closable) { expectedData.Write(ref pos, GumpUtilities.NoCloseBuffer); layoutLength += GumpUtilities.NoClose.Length; } if (!gump.Disposable) { expectedData.Write(ref pos, GumpUtilities.NoDisposeBuffer); layoutLength += GumpUtilities.NoDispose.Length; } if (!gump.Resizable) { expectedData.Write(ref pos, GumpUtilities.NoResizeBuffer); layoutLength += GumpUtilities.NoResize.Length; } foreach (var entry in gump.Entries) { var str = entry.Compile(ns); expectedData.WriteAscii(ref pos, str); layoutLength += str.Length; // ASCII so 1:1 } expectedData.Slice(19, 2).Write((ushort)layoutLength); expectedData.Write(ref pos, (ushort)gump.Strings.Count); for (var i = 0; i < gump.Strings.Count; ++i) { expectedData.WriteBigUni(ref pos, gump.Strings[i] ?? ""); } expectedData.Slice(1, 2).Write((ushort)pos); // Length expectedData = expectedData.Slice(0, pos); AssertThat.Equal(data, expectedData); } [Fact] public void TestPackedGumpPacket() { var ns = new NetState(null) { ProtocolChanges = ProtocolChanges.Unpack }; var gump = new ResurrectGump(2); var data = gump.Compile(ns).Compile(); Span expectedData = stackalloc byte[0x1000]; var pos = 0; expectedData[pos++] = 0xDD; // Packet ID pos += 2; // Length expectedData.Write(ref pos, gump.Serial); expectedData.Write(ref pos, gump.TypeID); expectedData.Write(ref pos, gump.X); expectedData.Write(ref pos, gump.Y); var layoutList = new List(); var 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); } var rawBuffer = ArrayPool.Shared.Rent(bufferLength); Span buffer = rawBuffer; var bufferPos = 0; foreach (var layout in layoutList) { buffer.WriteAscii(ref bufferPos, layout); } #if NO_LOCAL_INIT buffer.Write(ref bufferPos, (byte)0); // Layout terminator #else bufferPos++; #endif expectedData.WritePacked(ref pos, buffer.Slice(0, bufferPos)); ArrayPool.Shared.Return(rawBuffer); expectedData.Write(ref pos, gump.Strings.Count); bufferLength = gump.Strings.Sum(str => 2 + str.Length * 2); rawBuffer = ArrayPool.Shared.Rent(bufferLength); buffer = rawBuffer; bufferPos = 0; foreach (var str in gump.Strings) { buffer.WriteBigUni(ref bufferPos, str); } expectedData.WritePacked(ref pos, buffer.Slice(0, bufferPos)); ArrayPool.Shared.Return(rawBuffer); // Length expectedData.Slice(1, 2).Write((ushort)pos); 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 } } }