feat: Moves gumps out of the core (#1916)
> [!Important] > **Developer Note** > This code change will **completely move gumps out of the core** ### Summary - Adds `GetGumps()` convenience which exposes methods to Find/Close/Send multiple gumps. This helper is a performance improvement by eliminating the Dictionary<Player, List> lookup for gumps.
This commit is contained in:
parent
40d99f6d1c
commit
8282b00ca2
246 changed files with 1722 additions and 1383 deletions
|
|
@ -0,0 +1,35 @@
|
|||
using Server.Gumps;
|
||||
|
||||
namespace Server.Tests.Gumps;
|
||||
|
||||
public class DynamicTestGump : DynamicGump
|
||||
{
|
||||
private readonly string _petName;
|
||||
|
||||
public DynamicTestGump(string petName) : base(50, 50)
|
||||
{
|
||||
_petName = petName;
|
||||
Serial = (Serial)0x123;
|
||||
TypeID = 0x5345;
|
||||
}
|
||||
|
||||
protected override void BuildLayout(ref DynamicGumpBuilder builder)
|
||||
{
|
||||
builder.AddPage();
|
||||
|
||||
builder.AddBackground(10, 10, 265, 140, 0x242C);
|
||||
|
||||
builder.AddItem(205, 40, 0x4);
|
||||
builder.AddItem(227, 40, 0x5);
|
||||
|
||||
builder.AddItem(180, 78, 0xCAE);
|
||||
builder.AddItem(195, 90, 0xCAD);
|
||||
builder.AddItem(218, 95, 0xCB0);
|
||||
|
||||
builder.AddHtml(30, 30, 150, 75, "<div align=center>Wilt thou sanctify the resurrection of:</div>");
|
||||
builder.AddHtml(30, 70, 150, 25, $"<CENTER>{_petName}</CENTER>", true);
|
||||
|
||||
builder.AddButton(40, 105, 0x81A, 0x81B, 0x1); // Okay
|
||||
builder.AddButton(110, 105, 0x819, 0x818, 0x2); // Cancel
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
using Server.Gumps;
|
||||
|
||||
namespace Server.Tests.Gumps;
|
||||
|
||||
public sealed class LegacyTestGump : Gump
|
||||
{
|
||||
public LegacyTestGump(string petName) : base(50, 50)
|
||||
{
|
||||
Serial = (Serial)0x123;
|
||||
TypeID = 0x5345;
|
||||
|
||||
AddPage(0);
|
||||
|
||||
AddBackground(10, 10, 265, 140, 0x242C);
|
||||
|
||||
AddItem(205, 40, 0x4);
|
||||
AddItem(227, 40, 0x5);
|
||||
|
||||
AddItem(180, 78, 0xCAE);
|
||||
AddItem(195, 90, 0xCAD);
|
||||
AddItem(218, 95, 0xCB0);
|
||||
|
||||
AddHtml(30, 30, 150, 75, "<div align=center>Wilt thou sanctify the resurrection of:</div>");
|
||||
AddHtml(30, 70, 150, 25, $"<CENTER>{petName}</CENTER>", true);
|
||||
|
||||
AddButton(40, 105, 0x81A, 0x81B, 0x1); // Okay
|
||||
AddButton(110, 105, 0x819, 0x818, 0x2); // Cancel
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
using Server.Gumps;
|
||||
|
||||
namespace Server.Tests.Gumps;
|
||||
|
||||
public class StaticLayoutTestGump : StaticGump<StaticLayoutTestGump>
|
||||
{
|
||||
private readonly string _petName;
|
||||
|
||||
public StaticLayoutTestGump(string petName) : base(50, 50)
|
||||
{
|
||||
_petName = petName;
|
||||
Serial = (Serial)0x123;
|
||||
TypeID = 0x5345;
|
||||
}
|
||||
|
||||
protected override void BuildLayout(ref StaticGumpBuilder builder)
|
||||
{
|
||||
builder.AddPage();
|
||||
|
||||
builder.AddBackground(10, 10, 265, 140, 0x242C);
|
||||
|
||||
builder.AddItem(205, 40, 0x4);
|
||||
builder.AddItem(227, 40, 0x5);
|
||||
|
||||
builder.AddItem(180, 78, 0xCAE);
|
||||
builder.AddItem(195, 90, 0xCAD);
|
||||
builder.AddItem(218, 95, 0xCB0);
|
||||
|
||||
builder.AddHtml(30, 30, 150, 75, "<div align=center>Wilt thou sanctify the resurrection of:</div>");
|
||||
builder.AddHtmlPlaceholder(30, 70, 150, 25, "petName", true);
|
||||
|
||||
builder.AddButton(40, 105, 0x81A, 0x81B, 0x1); // Okay
|
||||
builder.AddButton(110, 105, 0x819, 0x818, 0x2); // Cancel
|
||||
}
|
||||
|
||||
protected override void BuildStrings(ref GumpStringsBuilder builder)
|
||||
{
|
||||
builder.SetStringSlot("petName", $"<CENTER>{_petName}</CENTER>");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
using Server.Gumps;
|
||||
|
||||
namespace Server.Tests.Gumps;
|
||||
|
||||
public class StaticTestGump : StaticGump<StaticTestGump>
|
||||
{
|
||||
public StaticTestGump() : base(50, 50)
|
||||
{
|
||||
Serial = (Serial)0x123;
|
||||
TypeID = 0x5345;
|
||||
}
|
||||
|
||||
protected override void BuildLayout(ref StaticGumpBuilder builder)
|
||||
{
|
||||
builder.AddPage();
|
||||
|
||||
builder.AddBackground(10, 10, 265, 140, 0x242C);
|
||||
|
||||
builder.AddItem(205, 40, 0x4);
|
||||
builder.AddItem(227, 40, 0x5);
|
||||
|
||||
builder.AddItem(180, 78, 0xCAE);
|
||||
builder.AddItem(195, 90, 0xCAD);
|
||||
builder.AddItem(218, 95, 0xCB0);
|
||||
|
||||
builder.AddHtml(30, 30, 150, 75, "<div align=center>Wilt thou sanctify the resurrection of:</div>");
|
||||
builder.AddHtml(30, 70, 150, 25, "<CENTER>Test</CENTER>", true);
|
||||
|
||||
builder.AddButton(40, 105, 0x81A, 0x81B, 0x1); // Okay
|
||||
builder.AddButton(110, 105, 0x819, 0x818, 0x2); // Cancel
|
||||
}
|
||||
}
|
||||
142
Projects/UOContent.Tests/Tests/Gumps/TestLayoutGumps.cs
Normal file
142
Projects/UOContent.Tests/Tests/Gumps/TestLayoutGumps.cs
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO;
|
||||
using Server.Gumps;
|
||||
using Server.Tests.Network;
|
||||
using Xunit;
|
||||
|
||||
namespace Server.Tests.Gumps;
|
||||
|
||||
[Collection("Sequential Tests")]
|
||||
public class TestLayoutGumps
|
||||
{
|
||||
[Fact]
|
||||
public void TestDynamicGumpPacket()
|
||||
{
|
||||
var legacyGump = new LegacyTestGump("Test");
|
||||
var legacyPacketData = legacyGump.Compile().Compile();
|
||||
|
||||
var staticGump = new DynamicTestGump("Test");
|
||||
var buffer = GC.AllocateUninitializedArray<byte>(512);
|
||||
var writer = new SpanWriter(buffer);
|
||||
staticGump.Compile(ref writer);
|
||||
|
||||
AssertThat.Equal(writer.Span, legacyPacketData);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestStaticLayoutGumpPacket()
|
||||
{
|
||||
var expectedLayout =
|
||||
"{ page 0 }{ resizepic 10 10 9260 265 140 }{ tilepic 205 40 4 }{ tilepic 227 40 5 }{ tilepic 180 78 3246 }{ tilepic 195 90 3245 }{ tilepic 218 95 3248 }{ htmlgump 30 30 150 75 1 0 0 }{ htmlgump 30 70 150 25 00002 1 0 }{ button 40 105 2074 2075 1 0 1 }{ button 110 105 2073 2072 1 0 2 }\0"u8;
|
||||
|
||||
string[] strings =
|
||||
[
|
||||
"<div align=center>Wilt thou sanctify the resurrection of:</div>",
|
||||
"<CENTER>Test</CENTER>"
|
||||
];
|
||||
|
||||
InternalTestStaticGump(expectedLayout, new StaticLayoutTestGump("Test"), strings);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestStaticGumpPacket()
|
||||
{
|
||||
var expectedLayout =
|
||||
"{ page 0 }{ resizepic 10 10 9260 265 140 }{ tilepic 205 40 4 }{ tilepic 227 40 5 }{ tilepic 180 78 3246 }{ tilepic 195 90 3245 }{ tilepic 218 95 3248 }{ htmlgump 30 30 150 75 1 0 0 }{ htmlgump 30 70 150 25 2 1 0 }{ button 40 105 2074 2075 1 0 1 }{ button 110 105 2073 2072 1 0 2 }\0"u8;
|
||||
|
||||
string[] strings =
|
||||
[
|
||||
"<div align=center>Wilt thou sanctify the resurrection of:</div>",
|
||||
"<CENTER>Test</CENTER>"
|
||||
];
|
||||
|
||||
InternalTestStaticGump(expectedLayout, new StaticTestGump(), strings);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestStaticGumpIsCached()
|
||||
{
|
||||
var gump = new CachedGump();
|
||||
var buffer = GC.AllocateUninitializedArray<byte>(512);
|
||||
var writer = new SpanWriter(buffer);
|
||||
gump.Compile(ref writer);
|
||||
|
||||
var packet = writer.Span.ToArray();
|
||||
|
||||
// Reset the writer
|
||||
writer.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
// Second call should not call BuildLayout
|
||||
gump.Compile(ref writer);
|
||||
|
||||
AssertThat.Equal(writer.Span, packet);
|
||||
}
|
||||
|
||||
private static void InternalTestStaticGump<T>(ReadOnlySpan<byte> expectedLayout, StaticGump<T> staticGump, string[] strings)
|
||||
where T : StaticGump<T>
|
||||
{
|
||||
// Expected layout
|
||||
var expectedBuffer = GC.AllocateUninitializedArray<byte>(512);
|
||||
var expectedBufferWriter = new SpanWriter(expectedBuffer);
|
||||
OutgoingGumpPackets.WritePacked(expectedLayout, ref expectedBufferWriter);
|
||||
var layoutLength = expectedBufferWriter.BytesWritten;
|
||||
|
||||
var buffer = GC.AllocateUninitializedArray<byte>(512);
|
||||
var writer = new SpanWriter(buffer);
|
||||
staticGump.Compile(ref writer);
|
||||
|
||||
// Assert layout is exactly what we are expecting
|
||||
AssertThat.Equal(writer.Span.Slice(19, layoutLength), expectedBufferWriter.Span);
|
||||
|
||||
// Assert strings count
|
||||
AssertThat.Equal(writer.Span.Slice(19 + layoutLength, 4), stackalloc byte[] { 0, 0, 0, 3 });
|
||||
|
||||
var expectedStringsBuffer = GC.AllocateUninitializedArray<byte>(512);
|
||||
var expectedStringsWriter = new SpanWriter(expectedStringsBuffer);
|
||||
|
||||
// Empty string
|
||||
expectedStringsWriter.Write((ushort)0);
|
||||
|
||||
// loop through the strings, write them to the strings writer
|
||||
foreach (var str in strings)
|
||||
{
|
||||
expectedStringsWriter.Write((ushort)str.Length);
|
||||
expectedStringsWriter.WriteBigUni(str);
|
||||
}
|
||||
|
||||
// Reset buffer
|
||||
expectedBufferWriter.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
OutgoingGumpPackets.WritePacked(expectedStringsWriter.Span, ref expectedBufferWriter);
|
||||
|
||||
// Assert strings are exactly what we are expecting
|
||||
AssertThat.Equal(writer.Span[(19 + layoutLength + 4)..], expectedBufferWriter.Span);
|
||||
}
|
||||
|
||||
private class CachedGump : StaticGump<CachedGump>
|
||||
{
|
||||
private bool _isCachedLayout;
|
||||
|
||||
public CachedGump() : base(50, 50)
|
||||
{
|
||||
Serial = (Serial)0x124;
|
||||
TypeID = 0x5346;
|
||||
}
|
||||
|
||||
protected override void BuildLayout(ref StaticGumpBuilder builder)
|
||||
{
|
||||
Assert.False(_isCachedLayout);
|
||||
_isCachedLayout = true;
|
||||
|
||||
builder.AddPage();
|
||||
|
||||
builder.AddHtml(30, 30, 150, 75, "Some text");
|
||||
}
|
||||
|
||||
protected override void BuildStrings(ref GumpStringsBuilder builder)
|
||||
{
|
||||
Assert.Fail("BuildStrings should not be called when the layout is cached.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
using Server.Gumps;
|
||||
using Server.Mobiles;
|
||||
using Server.Network;
|
||||
using Server.SkillHandlers;
|
||||
using Server.Tests;
|
||||
using Server.Tests.Network;
|
||||
|
|
@ -20,7 +20,7 @@ public class TrackingGumpTests : IClassFixture<ServerFixture>
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
|
||||
var expected = g.Compile(ns).Compile();
|
||||
ns.SendDisplayGump(g, out var switches, out var entries);
|
||||
ns.SendGump(g);
|
||||
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue