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:
Kamron Batman 2024-08-09 19:07:32 -07:00 committed by GitHub
parent 40d99f6d1c
commit 8282b00ca2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
246 changed files with 1722 additions and 1383 deletions

View file

@ -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
}
}

View file

@ -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
}
}

View file

@ -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>");
}
}

View file

@ -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
}
}

View 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.");
}
}
}

View file

@ -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);