diff --git a/Projects/Server.Tests/Tests/Network/Packets/Outgoing/GumpPacketTests.cs b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/GumpPacketTests.cs index 4b9148df8..4247ca123 100644 --- a/Projects/Server.Tests/Tests/Network/Packets/Outgoing/GumpPacketTests.cs +++ b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/GumpPacketTests.cs @@ -1,5 +1,4 @@ using Server.Gumps; -using Server.Network; using Xunit; namespace Server.Tests.Network; @@ -45,8 +44,7 @@ public class GumpPacketTests : IClassFixture var ns = PacketTestUtilities.CreateTestNetState(); var expected = gump.Compile(ns).Compile(); - - ns.SendDisplayGump(gump, out _, out _); + ns.SendGump(gump); var result = ns.SendPipe.Reader.AvailableToRead(); AssertThat.Equal(result, expected); @@ -65,8 +63,7 @@ public class GumpPacketTests : IClassFixture var ns = PacketTestUtilities.CreateTestNetState(); var expected = gump.Compile(ns).Compile(); - - ns.SendDisplayGump(gump, out _, out _); + ns.SendGump(gump); var result = ns.SendPipe.Reader.AvailableToRead(); AssertThat.Equal(result, expected); diff --git a/Projects/Server/IVirtualCheckGump.cs b/Projects/Server/IVirtualCheckGump.cs new file mode 100644 index 000000000..8df4c9ff0 --- /dev/null +++ b/Projects/Server/IVirtualCheckGump.cs @@ -0,0 +1,13 @@ +using Server.Items; + +namespace Server.Gumps +{ + public interface IVirtualCheckGump + { + public VirtualCheck Check { get; } + + public void Send(); + public void Refresh(bool recompile); + public void Close(); + } +} diff --git a/Projects/Server/Items/VirtualCheck.cs b/Projects/Server/Items/VirtualCheck.cs index a4362d84c..424a04eae 100644 --- a/Projects/Server/Items/VirtualCheck.cs +++ b/Projects/Server/Items/VirtualCheck.cs @@ -15,7 +15,7 @@ using ModernUO.Serialization; using Server.Gumps; -using Server.Network; +using System; namespace Server.Items; @@ -23,10 +23,16 @@ namespace Server.Items; public sealed partial class VirtualCheck : Item { public static bool UseEditGump { get; private set; } + public static unsafe delegate* GumpActivator { get; set; } - public static void Configure() + public static unsafe void Configure() { UseEditGump = ServerConfiguration.GetSetting("virtualChecks.useEditGump", Core.TOL); + + if (UseEditGump && GumpActivator is null) + { + throw new NullReferenceException(nameof(GumpActivator)); + } } private int _gold; @@ -42,15 +48,12 @@ public sealed partial class VirtualCheck : Item } public override bool IsVirtualItem => true; - public override bool DisplayWeight => false; public override bool DisplayLootType => false; - public override double DefaultWeight => 0; - public override string DefaultName => "Offer Of Currency"; - public EditGump Editor { get; private set; } + public IVirtualCheckGump Editor { get; private set; } [CommandProperty(AccessLevel.Administrator)] public int Plat @@ -86,13 +89,13 @@ public sealed partial class VirtualCheck : Item return c.RootParent == check && IsChildOf(c); } - public override void OnDoubleClickSecureTrade(Mobile from) + public override unsafe void OnDoubleClickSecureTrade(Mobile from) { if (UseEditGump && IsAccessibleTo(from)) { if (Editor?.Check?.Deleted != false) { - Editor = new EditGump(from, this); + Editor = GumpActivator(from, this); Editor.Send(); } else @@ -161,226 +164,4 @@ public sealed partial class VirtualCheck : Item { Delete(); } - - public class EditGump : Gump - { - public enum Buttons - { - Close, - Clear, - Accept, - AllPlat, - AllGold - } - - private int _plat, _gold; - - public EditGump(Mobile user, VirtualCheck check) : base(50, 50) - { - User = user; - Check = check; - - _plat = Check.Plat; - _gold = Check.Gold; - - Closable = true; - Disposable = true; - Draggable = true; - Resizable = false; - - User.CloseGump(); - - CompileLayout(); - } - - public Mobile User { get; } - public VirtualCheck Check { get; private set; } - - public override void OnServerClose(NetState owner) - { - base.OnServerClose(owner); - - if (Check?.Deleted == false) - { - Check.UpdateTrade(User); - } - } - - public void Close() - { - User.CloseGump(); - - if (Check?.Deleted == false) - { - Check.UpdateTrade(User); - } - else - { - Check = null; - } - } - - public void Send() - { - if (Check?.Deleted == false) - { - User.SendGump(this); - } - else - { - Close(); - } - } - - public void Refresh(bool recompile) - { - if (Check?.Deleted != false) - { - Close(); - return; - } - - if (recompile) - { - CompileLayout(); - } - - Close(); - Send(); - } - - private void CompileLayout() - { - if (Check?.Deleted != false) - { - return; - } - - Entries.ForEach(e => e.Parent = null); - Entries.Clear(); - - AddPage(0); - - AddBackground(0, 0, 400, 160, 3500); - - // Title - AddImageTiled(25, 35, 350, 3, 96); - AddImage(10, 8, 113); - AddImage(360, 8, 113); - - AddHtml(40, 15, 320, 20, $"BANK OF {User.RawName.ToUpper()}".Center(0x2F4F4F)); - - // Platinum Row - AddBackground(15, 60, 175, 20, 9300); - AddBackground(20, 45, 165, 30, 9350); - AddItem(20, 45, 3826); // Plat - AddLabel(60, 50, 0, User.Account.TotalPlat.ToString("#,0")); - - AddButton(195, 50, 95, 95, (int)Buttons.AllPlat); // -> - - AddBackground(210, 60, 175, 20, 9300); - AddBackground(215, 45, 165, 30, 9350); - AddTextEntry(225, 50, 145, 20, 0, 0, _plat.ToString(), User.Account.TotalPlat.ToString().Length); - - // Gold Row - AddBackground(15, 100, 175, 20, 9300); - AddBackground(20, 85, 165, 30, 9350); - AddItem(20, 85, 3823); // Gold - AddLabel(60, 90, 0, User.Account.TotalGold.ToString("#,0")); - - AddButton(195, 90, 95, 95, (int)Buttons.AllGold); // -> - - AddBackground(210, 100, 175, 20, 9300); - AddBackground(215, 85, 165, 30, 9350); - AddTextEntry(225, 90, 145, 20, 0, 1, _gold.ToString(), User.Account.TotalGold.ToString().Length); - - // Buttons - AddButton(20, 128, 12006, 12007, (int)Buttons.Close); - AddButton(215, 128, 12003, 12004, (int)Buttons.Clear); - AddButton(305, 128, 12000, 12002, (int)Buttons.Accept); - } - - public override void OnResponse(NetState sender, in RelayInfo info) - { - if (Check?.Deleted != false || sender.Mobile != User) - { - Close(); - return; - } - - var refresh = false; - var updated = false; - - switch ((Buttons)info.ButtonID) - { - case Buttons.Clear: - { - _plat = _gold = 0; - refresh = true; - break; - } - case Buttons.Accept: - { - var platText = info.GetTextEntry(0); - var goldText = info.GetTextEntry(1); - - if (!int.TryParse(platText, out _plat)) - { - User.SendMessage("That is not a valid amount of platinum."); - refresh = true; - } - else if (!int.TryParse(goldText, out _gold)) - { - User.SendMessage("That is not a valid amount of gold."); - refresh = true; - } - else - { - var totalPlat = User.Account.TotalPlat; - var totalGold = User.Account.TotalGold; - - if (totalPlat < _plat || totalGold < _gold) - { - _plat = User.Account.TotalPlat; - _gold = User.Account.TotalGold; - User.SendMessage("You do not have that much currency."); - refresh = true; - } - else - { - Check.Plat = _plat; - Check.Gold = _gold; - updated = true; - } - } - break; - } - case Buttons.AllPlat: - { - _plat = User.Account.TotalPlat; - refresh = true; - break; - } - case Buttons.AllGold: - { - _gold = User.Account.TotalGold; - refresh = true; - break; - } - } - - if (updated) - { - User.SendMessage("Your offer has been updated."); - } - - if (refresh && Check?.Deleted == false) - { - Refresh(true); - return; - } - - Close(); - } - } } diff --git a/Projects/Server/Mobiles/Mobile.cs b/Projects/Server/Mobiles/Mobile.cs index 978215c10..adcdfbc60 100644 --- a/Projects/Server/Mobiles/Mobile.cs +++ b/Projects/Server/Mobiles/Mobile.cs @@ -13,14 +13,10 @@ * along with this program. If not, see . * *************************************************************************/ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; using Server.Accounting; using Server.Collections; using Server.ContextMenus; using Server.Guilds; -using Server.Gumps; using Server.HuePickers; using Server.Items; using Server.Logging; @@ -30,6 +26,9 @@ using Server.Network; using Server.Prompts; using Server.Targeting; using Server.Text; +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; using CalcMoves = Server.Movement.Movement; namespace Server; @@ -8121,65 +8120,6 @@ public partial class Mobile : IHued, IComparable, ISpawnable, IObjectPro return false; } - public BaseGump FindGump() where T : BaseGump => m_NetState?.Gumps.Find(g => g is T); - - public bool CloseGump() where T : BaseGump - { - if (m_NetState == null) - { - return false; - } - - var gump = FindGump(); - - if (gump != null) - { - m_NetState.SendCloseGump(gump.TypeID, 0); - m_NetState.RemoveGump(gump); - gump.OnServerClose(m_NetState); - - return true; - } - - return false; - } - - public void CloseAllGumps() - { - var ns = m_NetState; - - if (ns.CannotSendPackets()) - { - return; - } - - var gumps = new List(ns.Gumps); - - ns.ClearGumps(); - - foreach (var gump in gumps) - { - ns.SendCloseGump(gump.TypeID, 0); - - gump.OnServerClose(ns); - } - - return; - } - - public bool HasGump() where T : BaseGump => m_NetState?.Gumps.Exists(g => g is T) ?? false; - - public bool SendGump(BaseGump g) - { - if (m_NetState == null) - { - return false; - } - - g.SendTo(m_NetState); - return true; - } - public bool SendMenu(IMenu m) { if (m_NetState == null) diff --git a/Projects/Server/Network/NetState/NetState.cs b/Projects/Server/Network/NetState/NetState.cs index 57fec62a8..51ef3eb0e 100755 --- a/Projects/Server/Network/NetState/NetState.cs +++ b/Projects/Server/Network/NetState/NetState.cs @@ -13,6 +13,13 @@ * along with this program. If not, see . * *************************************************************************/ +using Server.Accounting; +using Server.Collections; +using Server.Diagnostics; +using Server.HuePickers; +using Server.Items; +using Server.Logging; +using Server.Menus; using System; using System.Buffers; using System.Collections.Concurrent; @@ -23,14 +30,6 @@ using System.Net.Sockets; using System.Network; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using Server.Accounting; -using Server.Collections; -using Server.Diagnostics; -using Server.Gumps; -using Server.HuePickers; -using Server.Items; -using Server.Logging; -using Server.Menus; namespace Server.Network; @@ -46,7 +45,6 @@ public partial class NetState : IComparable, IValueLinkListNode, IValueLinkListNode, IValueLinkListNode Gumps { get; private set; } - public List HuePickers { get; private set; } public List Menus { get; private set; } @@ -419,36 +414,6 @@ public partial class NetState : IComparable, IValueLinkListNode, IValueLinkListNode. * + *************************************************************************/ + using System; using Server.Accounting; using Server.Items; @@ -411,7 +426,7 @@ public class SecureTrade } } -public class SecureTradeInfo : IDisposable +public sealed class SecureTradeInfo : IDisposable { public SecureTradeInfo(SecureTrade owner, Mobile m, SecureTradeContainer c) { diff --git a/Projects/Server.Tests/Tests/Gumps/TestGumps/DynamicTestGump.cs b/Projects/UOContent.Tests/Tests/Gumps/TestGumps/DynamicTestGump.cs similarity index 100% rename from Projects/Server.Tests/Tests/Gumps/TestGumps/DynamicTestGump.cs rename to Projects/UOContent.Tests/Tests/Gumps/TestGumps/DynamicTestGump.cs diff --git a/Projects/Server.Tests/Tests/Gumps/TestGumps/LegacyTestGump.cs b/Projects/UOContent.Tests/Tests/Gumps/TestGumps/LegacyTestGump.cs similarity index 100% rename from Projects/Server.Tests/Tests/Gumps/TestGumps/LegacyTestGump.cs rename to Projects/UOContent.Tests/Tests/Gumps/TestGumps/LegacyTestGump.cs diff --git a/Projects/Server.Tests/Tests/Gumps/TestGumps/StaticLayoutTestGump.cs b/Projects/UOContent.Tests/Tests/Gumps/TestGumps/StaticLayoutTestGump.cs similarity index 100% rename from Projects/Server.Tests/Tests/Gumps/TestGumps/StaticLayoutTestGump.cs rename to Projects/UOContent.Tests/Tests/Gumps/TestGumps/StaticLayoutTestGump.cs diff --git a/Projects/Server.Tests/Tests/Gumps/TestGumps/StaticTestGump.cs b/Projects/UOContent.Tests/Tests/Gumps/TestGumps/StaticTestGump.cs similarity index 100% rename from Projects/Server.Tests/Tests/Gumps/TestGumps/StaticTestGump.cs rename to Projects/UOContent.Tests/Tests/Gumps/TestGumps/StaticTestGump.cs diff --git a/Projects/Server.Tests/Tests/Gumps/TestLayoutGumps.cs b/Projects/UOContent.Tests/Tests/Gumps/TestLayoutGumps.cs similarity index 96% rename from Projects/Server.Tests/Tests/Gumps/TestLayoutGumps.cs rename to Projects/UOContent.Tests/Tests/Gumps/TestLayoutGumps.cs index 8cea30251..465f08c80 100644 --- a/Projects/Server.Tests/Tests/Gumps/TestLayoutGumps.cs +++ b/Projects/UOContent.Tests/Tests/Gumps/TestLayoutGumps.cs @@ -2,7 +2,6 @@ using System; using System.Buffers; using System.IO; using Server.Gumps; -using Server.Network; using Server.Tests.Network; using Xunit; @@ -20,7 +19,7 @@ public class TestLayoutGumps var staticGump = new DynamicTestGump("Test"); var buffer = GC.AllocateUninitializedArray(512); var writer = new SpanWriter(buffer); - staticGump.CreatePacket(ref writer); + staticGump.Compile(ref writer); AssertThat.Equal(writer.Span, legacyPacketData); } @@ -61,7 +60,7 @@ public class TestLayoutGumps var gump = new CachedGump(); var buffer = GC.AllocateUninitializedArray(512); var writer = new SpanWriter(buffer); - gump.CreatePacket(ref writer); + gump.Compile(ref writer); var packet = writer.Span.ToArray(); @@ -69,7 +68,7 @@ public class TestLayoutGumps writer.Seek(0, SeekOrigin.Begin); // Second call should not call BuildLayout - gump.CreatePacket(ref writer); + gump.Compile(ref writer); AssertThat.Equal(writer.Span, packet); } @@ -85,7 +84,7 @@ public class TestLayoutGumps var buffer = GC.AllocateUninitializedArray(512); var writer = new SpanWriter(buffer); - staticGump.CreatePacket(ref writer); + staticGump.Compile(ref writer); // Assert layout is exactly what we are expecting AssertThat.Equal(writer.Span.Slice(19, layoutLength), expectedBufferWriter.Span); diff --git a/Projects/UOContent.Tests/Tests/Skills/Tracking/TrackingGumpTests.cs b/Projects/UOContent.Tests/Tests/Skills/Tracking/TrackingGumpTests.cs index d4f79455c..c55cf740c 100644 --- a/Projects/UOContent.Tests/Tests/Skills/Tracking/TrackingGumpTests.cs +++ b/Projects/UOContent.Tests/Tests/Skills/Tracking/TrackingGumpTests.cs @@ -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 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); diff --git a/Projects/UOContent/Commands/AddonGenerator.cs b/Projects/UOContent/Commands/AddonGenerator.cs index 85999f383..001363e28 100644 --- a/Projects/UOContent/Commands/AddonGenerator.cs +++ b/Projects/UOContent/Commands/AddonGenerator.cs @@ -307,9 +307,10 @@ public class AddonGenerator private const int GreenHue = 0x40; private readonly PickerState _state; + public override bool Singleton => true; + public InternalGump(Mobile m, PickerState state) : base(100, 50) { - m.CloseGump(); _state = state; MakeGump(); } diff --git a/Projects/UOContent/Commands/Generic/Commands/Commands.cs b/Projects/UOContent/Commands/Generic/Commands/Commands.cs index 904921d45..5150595dc 100644 --- a/Projects/UOContent/Commands/Generic/Commands/Commands.cs +++ b/Projects/UOContent/Commands/Generic/Commands/Commands.cs @@ -524,11 +524,11 @@ namespace Server.Commands.Generic if (match.Length < 3) { e.Mobile.SendMessage("Invalid search string."); - e.Mobile.SendGump(new AddGump(e.Mobile, match, 0, Type.EmptyTypes, false)); + e.Mobile.SendGump(new AddGump(match, 0, Type.EmptyTypes, false)); } else { - e.Mobile.SendGump(new AddGump(e.Mobile, match, 0, AddGump.Match(match), true)); + e.Mobile.SendGump(new AddGump(match, 0, AddGump.Match(match), true)); } } else diff --git a/Projects/UOContent/Commands/HelpInfo.cs b/Projects/UOContent/Commands/HelpInfo.cs index 6039f3dd2..0361fbadc 100644 --- a/Projects/UOContent/Commands/HelpInfo.cs +++ b/Projects/UOContent/Commands/HelpInfo.cs @@ -290,18 +290,20 @@ public static class HelpInfo public override void OnResponse(NetState sender, in RelayInfo info) { var m = sender.Mobile; + var gumps = m.GetGumps(); + switch (info.ButtonID) { case 0: { - m.CloseGump(); + gumps.Close(); break; } case 1: { if (_page > 0) { - m.SendGump(new CommandListGump(_page - 1, m, _list)); + gumps.Send(new CommandListGump(_page - 1, m, _list)); } break; @@ -310,7 +312,7 @@ public static class HelpInfo { if ((_page + 1) * EntriesPerPage < SortedHelpInfo.Count) { - m.SendGump(new CommandListGump(_page + 1, m, _list)); + gumps.Send(new CommandListGump(_page + 1, m, _list)); } break; @@ -325,13 +327,13 @@ public static class HelpInfo if (m.AccessLevel >= c.AccessLevel) { - m.SendGump(new CommandInfoGump(c)); - m.SendGump(new CommandListGump(_page, m, _list)); + gumps.Send(new CommandInfoGump(c)); + gumps.Send(new CommandListGump(_page, m, _list)); } else { m.SendMessage("You no longer have access to that command."); - m.SendGump(new CommandListGump(_page, m, null)); + gumps.Send(new CommandListGump(_page, m, null)); } } diff --git a/Projects/UOContent/Commands/Object Creation/AddGump.cs b/Projects/UOContent/Commands/Object Creation/AddGump.cs index 26b26b5bc..7e8bfb33e 100644 --- a/Projects/UOContent/Commands/Object Creation/AddGump.cs +++ b/Projects/UOContent/Commands/Object Creation/AddGump.cs @@ -14,14 +14,14 @@ public class AddGump : DynamicGump private readonly string _searchString; private readonly bool _explicitSearch; - public AddGump(Mobile from, string searchString, int page, Type[] searchResults, bool explicitSearch) : base(50, 50) + public override bool Singleton => true; + + public AddGump(string searchString, int page, Type[] searchResults, bool explicitSearch) : base(50, 50) { _searchString = searchString; _searchResults = searchResults; _explicitSearch = explicitSearch; _page = page; - - from.CloseGump(); } protected override void BuildLayout(ref DynamicGumpBuilder builder) { @@ -120,7 +120,7 @@ public class AddGump : DynamicGump explicitSearch = true; } - e.Mobile.SendGump(new AddGump(e.Mobile, val, 0, types, explicitSearch)); + e.Mobile.SendGump(new AddGump(val, 0, types, explicitSearch)); } private static void Match(string match, Type[] types, HashSet results) @@ -212,11 +212,11 @@ public class AddGump : DynamicGump if (match.Length < 3) { from.SendMessage("Invalid search string."); - from.SendGump(new AddGump(from, match, _page, _searchResults, false)); + from.SendGump(new AddGump(match, _page, _searchResults, false)); } else { - from.SendGump(new AddGump(from, match, 0, Match(match), true)); + from.SendGump(new AddGump(match, 0, Match(match), true)); } break; @@ -225,7 +225,7 @@ public class AddGump : DynamicGump { if (_page > 0) { - from.SendGump(new AddGump(from, _searchString, _page - 1, _searchResults, true)); + from.SendGump(new AddGump(_searchString, _page - 1, _searchResults, true)); } break; @@ -234,7 +234,7 @@ public class AddGump : DynamicGump { if ((_page + 1) * 10 < _searchResults.Length) { - from.SendGump(new AddGump(from, _searchString, _page + 1, _searchResults, true)); + from.SendGump(new AddGump(_searchString, _page + 1, _searchResults, true)); } break; @@ -307,7 +307,7 @@ public class AddGump : DynamicGump { if (cancelType == TargetCancelType.Canceled) { - from.SendGump(new AddGump(from, m_SearchString, m_Page, m_SearchResults, true)); + from.SendGump(new AddGump(m_SearchString, m_Page, m_SearchResults, true)); } } } diff --git a/Projects/UOContent/Commands/Object Creation/CategorizedAddGump.cs b/Projects/UOContent/Commands/Object Creation/CategorizedAddGump.cs index 9e944b1ce..b46812115 100644 --- a/Projects/UOContent/Commands/Object Creation/CategorizedAddGump.cs +++ b/Projects/UOContent/Commands/Object Creation/CategorizedAddGump.cs @@ -34,14 +34,14 @@ namespace Server.Gumps private readonly Mobile m_Owner; private int m_Page; + public override bool Singleton => true; + public CategorizedAddGump(Mobile owner) : this(owner, CAGCategory.Root) { } public CategorizedAddGump(Mobile owner, CAGCategory category, int page = 0) : base(GumpOffsetX, GumpOffsetY) { - owner.CloseGump(); - m_Owner = owner; m_Category = category; diff --git a/Projects/Server/Diagnostics/GumpProfile.cs b/Projects/UOContent/Diagnostics/GumpProfile.cs similarity index 100% rename from Projects/Server/Diagnostics/GumpProfile.cs rename to Projects/UOContent/Diagnostics/GumpProfile.cs diff --git a/Projects/UOContent/Engines/Advanced Search/AdvancedSearchCommand.cs b/Projects/UOContent/Engines/Advanced Search/AdvancedSearchCommand.cs index 5365ebe51..c1027acda 100644 --- a/Projects/UOContent/Engines/Advanced Search/AdvancedSearchCommand.cs +++ b/Projects/UOContent/Engines/Advanced Search/AdvancedSearchCommand.cs @@ -1,3 +1,5 @@ +using Server.Gumps; + namespace Server.Engines.AdvancedSearch; public static class AdvancedSearchCommand @@ -14,7 +16,6 @@ public static class AdvancedSearchCommand { var from = e.Mobile; - from.CloseGump(); - from.SendGump(new AdvancedSearchGump(from)); + from.SendGump(new AdvancedSearchGump(from), true); } } diff --git a/Projects/UOContent/Engines/Bulk Orders/Books/BOBFilterGump.cs b/Projects/UOContent/Engines/Bulk Orders/Books/BOBFilterGump.cs index 3dd830a44..6e334a791 100644 --- a/Projects/UOContent/Engines/Bulk Orders/Books/BOBFilterGump.cs +++ b/Projects/UOContent/Engines/Bulk Orders/Books/BOBFilterGump.cs @@ -4,11 +4,11 @@ using Server.Network; namespace Server.Engines.BulkOrders { - public class BOBFilterGump : Gump + public sealed class BOBFilterGump : DynamicGump { private const int LabelColor = 0x7FFF; - private static readonly int[,] m_MaterialFilters = + private static readonly int[,] _materialFilters = { { 1044067, 1 }, // Blacksmithy { 1062226, 3 }, // Iron @@ -30,21 +30,21 @@ namespace Server.Engines.BulkOrders { 1062238, 16 } // Barbed }; - private static readonly int[,] m_TypeFilters = + private static readonly int[,] _typeFilters = { { 1062229, 0 }, // All { 1062224, 1 }, // Small { 1062225, 2 } // Large }; - private static readonly int[,] m_QualityFilters = + private static readonly int[,] _qualityFilters = { { 1062229, 0 }, // All { 1011542, 1 }, // Normal { 1060636, 2 } // Exceptional }; - private static readonly int[,] m_AmountFilters = + private static readonly int[,] _amountFilters = { { 1062229, 0 }, // All { 1049706, 1 }, // 10 @@ -52,74 +52,77 @@ namespace Server.Engines.BulkOrders { 1062239, 3 } // 20 }; - private static readonly int[][,] m_Filters = + private static readonly int[][,] _filters = { - m_TypeFilters, - m_QualityFilters, - m_MaterialFilters, - m_AmountFilters + _typeFilters, + _qualityFilters, + _materialFilters, + _amountFilters }; - private static readonly int[] m_XOffsets_Type = { 0, 75, 170 }; - private static readonly int[] m_XOffsets_Quality = { 0, 75, 170 }; - private static readonly int[] m_XOffsets_Amount = { 0, 75, 180, 275 }; - private static readonly int[] m_XOffsets_Material = { 0, 105, 210, 305, 390, 485 }; + private static readonly int[] _xOffsets_Type = [0, 75, 170]; + private static readonly int[] _xOffsets_Quality = [0, 75, 170]; + private static readonly int[] _xOffsets_Amount = [0, 75, 180, 275]; + private static readonly int[] _xOffsets_Material = [0, 105, 210, 305, 390, 485]; - private static readonly int[] m_XWidths_Small = { 50, 50, 70, 50 }; - private static readonly int[] m_XWidths_Large = { 80, 50, 50, 50, 50, 50 }; - private readonly BulkOrderBook m_Book; - private readonly PlayerMobile m_From; + private static readonly int[] _xWidths_Small = [50, 50, 70, 50]; + private static readonly int[] _xWidths_Large = [80, 50, 50, 50, 50, 50]; + + private readonly BulkOrderBook _book; + private readonly PlayerMobile _from; + + public override bool Singleton => true; public BOBFilterGump(PlayerMobile from, BulkOrderBook book) : base(12, 24) { - from.CloseGump(); - from.CloseGump(); - - m_From = from; - m_Book = book; - - var f = from.UseOwnFilter ? from.BOBFilter : book.Filter; - - AddPage(0); - - AddBackground(10, 10, 600, 439, 5054); - - AddImageTiled(18, 20, 583, 420, 2624); - AddAlphaRegion(18, 20, 583, 420); - - AddImage(5, 5, 10460); - AddImage(585, 5, 10460); - AddImage(5, 424, 10460); - AddImage(585, 424, 10460); - - AddHtmlLocalized(270, 32, 200, 32, 1062223, LabelColor); // Filter Preference - - AddHtmlLocalized(26, 64, 120, 32, 1062228, LabelColor); // Bulk Order Type - AddFilterList(25, 96, m_XOffsets_Type, 40, m_TypeFilters, m_XWidths_Small, f.Type, 0); - - AddHtmlLocalized(320, 64, 50, 32, 1062215, LabelColor); // Quality - AddFilterList(320, 96, m_XOffsets_Quality, 40, m_QualityFilters, m_XWidths_Small, f.Quality, 1); - - AddHtmlLocalized(26, 160, 120, 32, 1062232, LabelColor); // Material Type - AddFilterList(25, 192, m_XOffsets_Material, 40, m_MaterialFilters, m_XWidths_Large, f.Material, 2); - - AddHtmlLocalized(26, 320, 120, 32, 1062217, LabelColor); // Amount - AddFilterList(25, 352, m_XOffsets_Amount, 40, m_AmountFilters, m_XWidths_Small, f.Quantity, 3); - - AddHtmlLocalized(75, 416, 120, 32, 1062477, from.UseOwnFilter ? LabelColor : 16927); // Set Book Filter - AddButton(40, 416, 4005, 4007, 1); - - AddHtmlLocalized(235, 416, 120, 32, 1062478, from.UseOwnFilter ? 16927 : LabelColor); // Set Your Filter - AddButton(200, 416, 4005, 4007, 2); - - AddHtmlLocalized(405, 416, 120, 32, 1062231, LabelColor); // Clear Filter - AddButton(370, 416, 4005, 4007, 3); - - AddHtmlLocalized(540, 416, 50, 32, 1011046, LabelColor); // APPLY - AddButton(505, 416, 4017, 4018, 0); + _from = from; + _book = book; } - private void AddFilterList( + protected override void BuildLayout(ref DynamicGumpBuilder builder) + { + var f = _from.UseOwnFilter ? _from.BOBFilter : _book.Filter; + + builder.AddPage(); + + builder.AddBackground(10, 10, 600, 439, 5054); + + builder.AddImageTiled(18, 20, 583, 420, 2624); + builder.AddAlphaRegion(18, 20, 583, 420); + + builder.AddImage(5, 5, 10460); + builder.AddImage(585, 5, 10460); + builder.AddImage(5, 424, 10460); + builder.AddImage(585, 424, 10460); + + builder.AddHtmlLocalized(270, 32, 200, 32, 1062223, LabelColor); // Filter Preference + + builder.AddHtmlLocalized(26, 64, 120, 32, 1062228, LabelColor); // Bulk Order Type + AddFilterList(ref builder, 25, 96, _xOffsets_Type, 40, _typeFilters, _xWidths_Small, f.Type, 0); + + builder.AddHtmlLocalized(320, 64, 50, 32, 1062215, LabelColor); // Quality + AddFilterList(ref builder, 320, 96, _xOffsets_Quality, 40, _qualityFilters, _xWidths_Small, f.Quality, 1); + + builder.AddHtmlLocalized(26, 160, 120, 32, 1062232, LabelColor); // Material Type + AddFilterList(ref builder, 25, 192, _xOffsets_Material, 40, _materialFilters, _xWidths_Large, f.Material, 2); + + builder.AddHtmlLocalized(26, 320, 120, 32, 1062217, LabelColor); // Amount + AddFilterList(ref builder, 25, 352, _xOffsets_Amount, 40, _amountFilters, _xWidths_Small, f.Quantity, 3); + + builder.AddHtmlLocalized(75, 416, 120, 32, 1062477, _from.UseOwnFilter ? LabelColor : 16927); // Set Book Filter + builder.AddButton(40, 416, 4005, 4007, 1); + + builder.AddHtmlLocalized(235, 416, 120, 32, 1062478, _from.UseOwnFilter ? 16927 : LabelColor); // Set Your Filter + builder.AddButton(200, 416, 4005, 4007, 2); + + builder.AddHtmlLocalized(405, 416, 120, 32, 1062231, LabelColor); // Clear Filter + builder.AddButton(370, 416, 4005, 4007, 3); + + builder.AddHtmlLocalized(540, 416, 50, 32, 1011046, LabelColor); // APPLY + builder.AddButton(505, 416, 4017, 4018, 0); + } + + private void AddFilterList(ref DynamicGumpBuilder builder, int x, int y, int[] xOffsets, int yOffset, int[,] filters, int[] xWidths, int filterValue, int filterIndex ) @@ -136,7 +139,7 @@ namespace Server.Engines.BulkOrders var isSelected = filters[i, 1] == filterValue || i % xOffsets.Length == 0 && filterValue == 0; - AddHtmlLocalized( + builder.AddHtmlLocalized( x + 35 + xOffsets[i % xOffsets.Length], y + i / xOffsets.Length * yOffset, xWidths[i % xOffsets.Length], @@ -144,7 +147,8 @@ namespace Server.Engines.BulkOrders number, isSelected ? 16927 : LabelColor ); - AddButton( + + builder.AddButton( x + xOffsets[i % xOffsets.Length], y + i / xOffsets.Length * yOffset, 4005, @@ -156,7 +160,7 @@ namespace Server.Engines.BulkOrders public override void OnResponse(NetState sender, in RelayInfo info) { - var f = m_From.UseOwnFilter ? m_From.BOBFilter : m_Book.Filter; + var f = _from.UseOwnFilter ? _from.BOBFilter : _book.Filter; var index = info.ButtonID; @@ -164,28 +168,28 @@ namespace Server.Engines.BulkOrders { case 0: // Apply { - m_From.SendGump(new BOBGump(m_From, m_Book)); + _from.SendGump(new BOBGump(_from, _book)); break; } case 1: // Set Book Filter { - m_From.UseOwnFilter = false; - m_From.SendGump(new BOBFilterGump(m_From, m_Book)); + _from.UseOwnFilter = false; + _from.SendGump(new BOBFilterGump(_from, _book)); break; } case 2: // Set Your Filter { - m_From.UseOwnFilter = true; - m_From.SendGump(new BOBFilterGump(m_From, m_Book)); + _from.UseOwnFilter = true; + _from.SendGump(new BOBFilterGump(_from, _book)); break; } case 3: // Clear Filter { f.Clear(); - m_From.SendGump(new BOBFilterGump(m_From, m_Book)); + _from.SendGump(new BOBFilterGump(_from, _book)); break; } @@ -196,9 +200,9 @@ namespace Server.Engines.BulkOrders var type = index % 4; index /= 4; - if (type >= 0 && type < m_Filters.Length) + if (type >= 0 && type < _filters.Length) { - var filters = m_Filters[type]; + var filters = _filters[type]; if (index >= 0 && index < filters.GetLength(0)) { @@ -223,7 +227,7 @@ namespace Server.Engines.BulkOrders break; } - m_From.SendGump(new BOBFilterGump(m_From, m_Book)); + _from.SendGump(new BOBFilterGump(_from, _book)); } } diff --git a/Projects/UOContent/Engines/Bulk Orders/Books/BOBGump.cs b/Projects/UOContent/Engines/Bulk Orders/Books/BOBGump.cs index ac6267504..28ee596c2 100644 --- a/Projects/UOContent/Engines/Bulk Orders/Books/BOBGump.cs +++ b/Projects/UOContent/Engines/Bulk Orders/Books/BOBGump.cs @@ -11,20 +11,19 @@ namespace Server.Engines.BulkOrders public class BOBGump : Gump { private const int LabelColor = 0x7FFF; - private readonly BulkOrderBook m_Book; - private readonly PlayerMobile m_From; - private readonly List m_List; + private readonly BulkOrderBook _book; + private readonly PlayerMobile _from; + private readonly List _list; - private int m_Page; + private int _page; + + public override bool Singleton => true; public BOBGump(PlayerMobile from, BulkOrderBook book, int page = 0, List list = null) : base(12, 24) { - from.CloseGump(); - from.CloseGump(); - - m_From = from; - m_Book = book; - m_Page = page; + _from = from; + _book = book; + _page = page; if (list == null) { @@ -41,7 +40,7 @@ namespace Server.Engines.BulkOrders } } - m_List = list; + _list = list; var index = GetIndexForPage(page); var count = GetCountForIndex(index); @@ -313,7 +312,7 @@ namespace Server.Engines.BulkOrders Type itemType ) { - var f = m_From.UseOwnFilter ? m_From.BOBFilter : m_Book.Filter; + var f = _from.UseOwnFilter ? _from.BOBFilter : _book.Filter; if (f.IsDefault) { @@ -394,7 +393,7 @@ namespace Server.Engines.BulkOrders var slots = 0; var count = 0; - var list = m_List; + var list = _list; for (var i = index; i >= 0 && i < list.Count; ++i) { @@ -429,7 +428,7 @@ namespace Server.Engines.BulkOrders var page = 0; int i; - var list = m_List; + var list = _list; for (i = 0; i < index && i < list.Count; i++) { var entry = list[i]; @@ -525,6 +524,13 @@ namespace Server.Engines.BulkOrders return "Invalid"; } + public override void SendTo(NetState ns) + { + ns.CloseGump(); + + base.SendTo(ns); + } + public override void OnResponse(NetState sender, in RelayInfo info) { var index = info.ButtonID; @@ -537,34 +543,34 @@ namespace Server.Engines.BulkOrders } case 1: // Set Filter { - m_From.SendGump(new BOBFilterGump(m_From, m_Book)); + _from.SendGump(new BOBFilterGump(_from, _book)); break; } case 2: // Previous page { - if (m_Page > 0) + if (_page > 0) { - m_From.SendGump(new BOBGump(m_From, m_Book, m_Page - 1, m_List)); + _from.SendGump(new BOBGump(_from, _book, _page - 1, _list)); } return; } case 3: // Next page { - if (GetIndexForPage(m_Page + 1) < m_List.Count) + if (GetIndexForPage(_page + 1) < _list.Count) { - m_From.SendGump(new BOBGump(m_From, m_Book, m_Page + 1, m_List)); + _from.SendGump(new BOBGump(_from, _book, _page + 1, _list)); } break; } case 4: // Price all { - if (m_Book.IsChildOf(m_From.Backpack)) + if (_book.IsChildOf(_from.Backpack)) { - m_From.Prompt = new SetPricePrompt(m_Book, null, m_Page, m_List); - m_From.SendMessage("Type in a price for all deeds in the book:"); + _from.Prompt = new SetPricePrompt(_book, null, _page, _list); + _from.SendMessage("Type in a price for all deeds in the book:"); } break; @@ -576,28 +582,28 @@ namespace Server.Engines.BulkOrders var type = index % 2; index /= 2; - if (index < 0 || index >= m_List.Count) + if (index < 0 || index >= _list.Count) { break; } - var bobEntry = m_List[index]; + var bobEntry = _list[index]; - if (!m_Book.Entries.Contains(bobEntry)) + if (!_book.Entries.Contains(bobEntry)) { - m_From.SendLocalizedMessage(1062382); // The deed selected is not available. + _from.SendLocalizedMessage(1062382); // The deed selected is not available. break; } if (type == 0) // Drop { - if (m_Book.IsChildOf(m_From.Backpack)) + if (_book.IsChildOf(_from.Backpack)) { var item = bobEntry.Reconstruct(); - var pack = m_From.Backpack; + var pack = _from.Backpack; if (pack?.CheckHold( - m_From, + _from, item, true, true, @@ -605,37 +611,37 @@ namespace Server.Engines.BulkOrders item.PileWeight + item.TotalWeight ) != true) { - m_From.SendLocalizedMessage(503204); // You do not have room in your backpack for this - m_From.SendGump(new BOBGump(m_From, m_Book, m_Page)); + _from.SendLocalizedMessage(503204); // You do not have room in your backpack for this + _from.SendGump(new BOBGump(_from, _book, _page)); } else { - if (m_Book.IsChildOf(m_From.Backpack)) + if (_book.IsChildOf(_from.Backpack)) { var sizeOfDroppedBod = bobEntry is BOBLargeEntry entry ? entry.Entries.Length : 1; - m_From.AddToBackpack(item); + _from.AddToBackpack(item); // The bulk order deed has been placed in your backpack. - m_From.SendLocalizedMessage(1045152); + _from.SendLocalizedMessage(1045152); - m_Book.Entries.Remove(bobEntry); - m_Book.InvalidateProperties(); + _book.Entries.Remove(bobEntry); + _book.InvalidateProperties(); - if (m_Book.Entries.Count / 5 < m_Book.ItemCount) + if (_book.Entries.Count / 5 < _book.ItemCount) { - m_Book.ItemCount--; - m_Book.InvalidateItems(); + _book.ItemCount--; + _book.InvalidateItems(); } - if (m_Book.Entries.Count > 0) + if (_book.Entries.Count > 0) { - m_Page = GetPageForIndex(index, sizeOfDroppedBod); - m_From.SendGump(new BOBGump(m_From, m_Book, m_Page)); + _page = GetPageForIndex(index, sizeOfDroppedBod); + _from.SendGump(new BOBGump(_from, _book, _page)); } else { - m_From.SendLocalizedMessage(1062381); // The book is empty. + _from.SendLocalizedMessage(1062381); // The book is empty. } } } @@ -643,14 +649,14 @@ namespace Server.Engines.BulkOrders } else // Set Price | Buy { - if (m_Book.IsChildOf(m_From.Backpack)) + if (_book.IsChildOf(_from.Backpack)) { - m_From.Prompt = new SetPricePrompt(m_Book, bobEntry, m_Page, m_List); - m_From.SendLocalizedMessage(1062383); // Type in a price for the deed: + _from.Prompt = new SetPricePrompt(_book, bobEntry, _page, _list); + _from.SendLocalizedMessage(1062383); // Type in a price for the deed: } - else if (m_Book.RootParent is PlayerVendor pv) + else if (_book.RootParent is PlayerVendor pv) { - var vi = pv.GetVendorItem(m_Book); + var vi = pv.GetVendorItem(_book); if (vi?.IsForSale != false) { @@ -662,18 +668,18 @@ namespace Server.Engines.BulkOrders if (price == 0) { - m_From.SendLocalizedMessage(1062382); // The deed selected is not available. + _from.SendLocalizedMessage(1062382); // The deed selected is not available. } else { - if (m_Book.Entries.Count > 0) + if (_book.Entries.Count > 0) { - m_Page = GetPageForIndex(index, sizeOfDroppedBod); - m_From.SendGump(new BODBuyGump(m_From, m_Book, bobEntry, m_Page, price)); + _page = GetPageForIndex(index, sizeOfDroppedBod); + _from.SendGump(new BODBuyGump(_from, _book, bobEntry, _page, price)); } else { - m_From.SendLocalizedMessage(1062381); // The book is emptz + _from.SendLocalizedMessage(1062381); // The book is emptz } } } diff --git a/Projects/UOContent/Engines/Bulk Orders/LargeBOD.cs b/Projects/UOContent/Engines/Bulk Orders/LargeBOD.cs index b918f3e79..c18b12e28 100644 --- a/Projects/UOContent/Engines/Bulk Orders/LargeBOD.cs +++ b/Projects/UOContent/Engines/Bulk Orders/LargeBOD.cs @@ -1,4 +1,5 @@ using ModernUO.Serialization; +using Server.Gumps; using Server.Mobiles; namespace Server.Engines.BulkOrders diff --git a/Projects/UOContent/Engines/Bulk Orders/LargeBODAcceptGump.cs b/Projects/UOContent/Engines/Bulk Orders/LargeBODAcceptGump.cs index 00b070dd9..8e989685f 100644 --- a/Projects/UOContent/Engines/Bulk Orders/LargeBODAcceptGump.cs +++ b/Projects/UOContent/Engines/Bulk Orders/LargeBODAcceptGump.cs @@ -8,14 +8,13 @@ namespace Server.Engines.BulkOrders private readonly LargeBOD m_Deed; private readonly Mobile m_From; + public override bool Singleton => true; + public LargeBODAcceptGump(Mobile from, LargeBOD deed) : base(50, 50) { m_From = from; m_Deed = deed; - m_From.CloseGump(); - m_From.CloseGump(); - var entries = deed.Entries; AddPage(0); diff --git a/Projects/UOContent/Engines/Bulk Orders/LargeBODGump.cs b/Projects/UOContent/Engines/Bulk Orders/LargeBODGump.cs index fe4c881da..6fc2e2b2a 100644 --- a/Projects/UOContent/Engines/Bulk Orders/LargeBODGump.cs +++ b/Projects/UOContent/Engines/Bulk Orders/LargeBODGump.cs @@ -8,14 +8,13 @@ namespace Server.Engines.BulkOrders private readonly LargeBOD m_Deed; private readonly Mobile m_From; + public override bool Singleton => true; + public LargeBODGump(Mobile from, LargeBOD deed) : base(25, 25) { m_From = from; m_Deed = deed; - m_From.CloseGump(); - m_From.CloseGump(); - var entries = deed.Entries; AddPage(0); diff --git a/Projects/UOContent/Engines/Bulk Orders/SmallBOD.cs b/Projects/UOContent/Engines/Bulk Orders/SmallBOD.cs index 5d3d7c7a2..72d25749e 100644 --- a/Projects/UOContent/Engines/Bulk Orders/SmallBOD.cs +++ b/Projects/UOContent/Engines/Bulk Orders/SmallBOD.cs @@ -1,4 +1,5 @@ using System; +using Server.Gumps; using Server.Items; using Server.Mobiles; diff --git a/Projects/UOContent/Engines/Bulk Orders/SmallBODAcceptGump.cs b/Projects/UOContent/Engines/Bulk Orders/SmallBODAcceptGump.cs index 794715af0..9b235573c 100644 --- a/Projects/UOContent/Engines/Bulk Orders/SmallBODAcceptGump.cs +++ b/Projects/UOContent/Engines/Bulk Orders/SmallBODAcceptGump.cs @@ -8,14 +8,13 @@ namespace Server.Engines.BulkOrders private readonly SmallBOD m_Deed; private readonly Mobile m_From; + public override bool Singleton => true; + public SmallBODAcceptGump(Mobile from, SmallBOD deed) : base(50, 50) { m_From = from; m_Deed = deed; - m_From.CloseGump(); - m_From.CloseGump(); - AddPage(0); AddBackground(25, 10, 430, 264, 5054); diff --git a/Projects/UOContent/Engines/Bulk Orders/SmallBODGump.cs b/Projects/UOContent/Engines/Bulk Orders/SmallBODGump.cs index 9f70c55bf..9363e7516 100644 --- a/Projects/UOContent/Engines/Bulk Orders/SmallBODGump.cs +++ b/Projects/UOContent/Engines/Bulk Orders/SmallBODGump.cs @@ -8,14 +8,13 @@ namespace Server.Engines.BulkOrders private readonly SmallBOD m_Deed; private readonly Mobile m_From; + public override bool Singleton => true; + public SmallBODGump(Mobile from, SmallBOD deed) : base(25, 25) { m_From = from; m_Deed = deed; - m_From.CloseGump(); - m_From.CloseGump(); - AddPage(0); AddBackground(50, 10, 455, 260, 5054); diff --git a/Projects/UOContent/Engines/ConPVP/AcceptDuelGump.cs b/Projects/UOContent/Engines/ConPVP/AcceptDuelGump.cs index 6d005605d..c705587c1 100644 --- a/Projects/UOContent/Engines/ConPVP/AcceptDuelGump.cs +++ b/Projects/UOContent/Engines/ConPVP/AcceptDuelGump.cs @@ -22,6 +22,8 @@ namespace Server.Engines.ConPVP private bool m_Active = true; + public override bool Singleton => true; + public AcceptDuelGump(Mobile challenger, Mobile challenged, DuelContext context, Participant p, int slot) : base( 50, 50 @@ -33,8 +35,6 @@ namespace Server.Engines.ConPVP m_Participant = p; m_Slot = slot; - challenged.CloseGump(); - Closable = false; AddPage(0); @@ -244,23 +244,18 @@ namespace Server.Engines.ConPVP m_Challenger.SendMessage($"{m_Challenged.Name} has accepted the request."); m_Challenged.SendMessage($"You have accepted the request from {m_Challenger.Name}."); - var ns = m_Challenger.NetState; - - if (ns != null) + foreach (var g in m_Challenger.GetAllGumps()) { - foreach (var g in ns.Gumps) + if (g is ParticipantGump pg && pg.Participant == m_Participant) { - if (g is ParticipantGump pg && pg.Participant == m_Participant) - { - m_Challenger.SendGump(new ParticipantGump(m_Challenger, m_Context, m_Participant)); - break; - } + m_Challenger.SendGump(new ParticipantGump(m_Challenger, m_Context, m_Participant)); + break; + } - if (g is DuelContextGump dcg && dcg.Context == m_Context) - { - m_Challenger.SendGump(new DuelContextGump(m_Challenger, m_Context)); - break; - } + if (g is DuelContextGump dcg && dcg.Context == m_Context) + { + m_Challenger.SendGump(new DuelContextGump(m_Challenger, m_Context)); + break; } } } diff --git a/Projects/UOContent/Engines/ConPVP/DuelContext.cs b/Projects/UOContent/Engines/ConPVP/DuelContext.cs index a900d809c..bbb8986d6 100644 --- a/Projects/UOContent/Engines/ConPVP/DuelContext.cs +++ b/Projects/UOContent/Engines/ConPVP/DuelContext.cs @@ -135,9 +135,9 @@ namespace Server.Engines.ConPVP string title = move switch { - NinjaMove => "Bushido", + NinjaMove => "Bushido", SamuraiMove => "Ninjitsu", - _ => null + _ => null }; if (title == null || name == null || Ruleset.GetOption(title, name)) @@ -199,15 +199,15 @@ namespace Server.Engines.ConPVP case MagerySpell magerySpell: title = magerySpell.Circle switch { - SpellCircle.First => "1st Circle", - SpellCircle.Second => "2nd Circle", - SpellCircle.Third => "3rd Circle", - SpellCircle.Fourth => "4th Circle", - SpellCircle.Fifth => "5th Circle", - SpellCircle.Sixth => "6th Circle", + SpellCircle.First => "1st Circle", + SpellCircle.Second => "2nd Circle", + SpellCircle.Third => "3rd Circle", + SpellCircle.Fourth => "4th Circle", + SpellCircle.Fifth => "5th Circle", + SpellCircle.Sixth => "6th Circle", SpellCircle.Seventh => "7th Circle", - SpellCircle.Eighth => "8th Circle", - _ => null + SpellCircle.Eighth => "8th Circle", + _ => null }; option = magerySpell.Name; @@ -1431,7 +1431,6 @@ namespace Server.Engines.ConPVP if (prefs != null) { - e.Mobile.CloseGump(); e.Mobile.SendGump(new PreferencesGump(e.Mobile, prefs)); } } @@ -1542,23 +1541,18 @@ namespace Server.Engines.ConPVP p.Nullify(pl); pm.DuelPlayer = null; - var ns = init.NetState; - - if (ns != null) + foreach (var g in init.GetAllGumps()) { - foreach (var g in ns.Gumps) + if (g is ParticipantGump pg && pg.Participant == p) { - if (g is ParticipantGump pg && pg.Participant == p) - { - init.SendGump(new ParticipantGump(init, dc, p)); - break; - } + init.SendGump(new ParticipantGump(init, dc, p)); + break; + } - if (g is DuelContextGump dcg && dcg.Context == dc) - { - init.SendGump(new DuelContextGump(init, dc)); - break; - } + if (g is DuelContextGump dcg && dcg.Context == dc) + { + init.SendGump(new DuelContextGump(init, dc)); + break; } } } @@ -1580,34 +1574,29 @@ namespace Server.Engines.ConPVP p.Nullify(pl); pm.DuelPlayer = null; - var ns = init.NetState; + var send = true; - if (ns != null) + foreach (var g in init.GetAllGumps()) { - var send = true; - - foreach (var g in ns.Gumps) + if (g is ParticipantGump pg && pg.Participant == p) { - if (g is ParticipantGump pg && pg.Participant == p) - { - init.SendGump(new ParticipantGump(init, dc, p)); - send = false; - break; - } - - if (g is DuelContextGump dcg && dcg.Context == dc) - { - init.SendGump(new DuelContextGump(init, dc)); - send = false; - break; - } + init.SendGump(new ParticipantGump(init, dc, p)); + send = false; + break; } - if (send) + if (g is DuelContextGump dcg && dcg.Context == dc) { init.SendGump(new DuelContextGump(init, dc)); + send = false; + break; } } + + if (send) + { + init.SendGump(new DuelContextGump(init, dc)); + } } } else @@ -1629,34 +1618,29 @@ namespace Server.Engines.ConPVP p.Nullify(pl); pm.DuelPlayer = null; - var ns = init.NetState; + var send = true; - if (ns != null) + foreach (var g in init.GetAllGumps()) { - var send = true; - - foreach (var g in ns.Gumps) + if (g is ParticipantGump pg && pg.Participant == p) { - if (g is ParticipantGump pg && pg.Participant == p) - { - init.SendGump(new ParticipantGump(init, dc, p)); - send = false; - break; - } - - if (g is DuelContextGump dcg && dcg.Context == dc) - { - init.SendGump(new DuelContextGump(init, dc)); - send = false; - break; - } + init.SendGump(new ParticipantGump(init, dc, p)); + send = false; + break; } - if (send) + if (g is DuelContextGump dcg && dcg.Context == dc) { init.SendGump(new DuelContextGump(init, dc)); + send = false; + break; } } + + if (send) + { + init.SendGump(new DuelContextGump(init, dc)); + } } } } @@ -1714,13 +1698,15 @@ namespace Server.Engines.ConPVP public void CloseAllGumps(DuelPlayer pl) { - pl.Mobile.CloseGump(); - pl.Mobile.CloseGump(); - pl.Mobile.CloseGump(); - pl.Mobile.CloseGump(); - pl.Mobile.CloseGump(); - pl.Mobile.CloseGump(); - pl.Mobile.CloseGump(); + var gumps = pl.Mobile.GetGumps(); + + gumps.Close(); + gumps.Close(); + gumps.Close(); + gumps.Close(); + gumps.Close(); + gumps.Close(); + gumps.Close(); } public void CloseAllGumps() @@ -1799,9 +1785,11 @@ namespace Server.Engines.ConPVP } // Close all of them? - mob.CloseGump(); - mob.CloseGump(); - mob.CloseGump(); + var gumps = mob.GetGumps(); + + gumps.Close(); + gumps.Close(); + gumps.Close(); } } @@ -2194,10 +2182,12 @@ namespace Server.Engines.ConPVP { if (count == 10) { - mob.CloseGump(); - mob.CloseGump(); - mob.CloseGump(); - mob.SendGump(new BeginGump(count)); + var gumps = mob.GetGumps(); + + gumps.Close(); + gumps.Close(); + gumps.Close(); + gumps.Send(new BeginGump(count)); } mob.Frozen = true; @@ -2256,8 +2246,7 @@ namespace Server.Engines.ConPVP if (mob != null && m_Tournament == null) { - mob.CloseGump(); - mob.SendGump(new ReadyUpGump(mob, this)); + mob.SendGump(new ReadyUpGump(mob, this), true); } } } @@ -2512,8 +2501,7 @@ namespace Server.Engines.ConPVP { if (m_Tournament == null) { - mob.CloseGump(); - mob.SendGump(new ReadyGump(mob, this, count)); + mob.SendGump(new ReadyGump(mob, this, count), true); } } else diff --git a/Projects/UOContent/Engines/ConPVP/Games/BombingRun.cs b/Projects/UOContent/Engines/ConPVP/Games/BombingRun.cs index 6e87cef44..71311ba2d 100644 --- a/Projects/UOContent/Engines/ConPVP/Games/BombingRun.cs +++ b/Projects/UOContent/Engines/ConPVP/Games/BombingRun.cs @@ -1057,7 +1057,6 @@ namespace Server.Engines.ConPVP { if (m_TeamInfo?.Game != null) { - from.CloseGump(); from.SendGump(new BRBoardGump(from, m_TeamInfo.Game)); } } @@ -1082,7 +1081,7 @@ namespace Server.Engines.ConPVP private const int LabelColor32 = 0xFFFFFF; private const int BlackColor32 = 0x000000; - // private BRGame m_Game; + public override bool Singleton => true; public BRBoardGump(Mobile mob, BRGame game, BRTeamInfo section = null) : base(60, 60) { @@ -1719,7 +1718,6 @@ namespace Server.Engines.ConPVP } } - mob.CloseGump(); mob.SendGump(new BRBoardGump(mob, this)); m_Context.Requip(mob, corpse); @@ -1918,7 +1916,6 @@ namespace Server.Engines.ConPVP if (dp?.Mobile != null) { - dp.Mobile.CloseGump(); dp.Mobile.SendGump(new BRBoardGump(dp.Mobile, this)); } } diff --git a/Projects/UOContent/Engines/ConPVP/Games/CTF.cs b/Projects/UOContent/Engines/ConPVP/Games/CTF.cs index eea8bb3fa..033475c38 100644 --- a/Projects/UOContent/Engines/ConPVP/Games/CTF.cs +++ b/Projects/UOContent/Engines/ConPVP/Games/CTF.cs @@ -29,7 +29,6 @@ namespace Server.Engines.ConPVP { if (m_TeamInfo?.Game != null) { - from.CloseGump(); from.SendGump(new CTFBoardGump(from, m_TeamInfo.Game)); } } @@ -56,6 +55,8 @@ namespace Server.Engines.ConPVP private CTFGame m_Game; + public override bool Singleton => true; + public CTFBoardGump(Mobile mob, CTFGame game, CTFTeamInfo section = null) : base(60, 60) { @@ -1059,7 +1060,6 @@ namespace Server.Engines.ConPVP } } - mob.CloseGump(); mob.SendGump(new CTFBoardGump(mob, this)); m_Context.Requip(mob, corpse); @@ -1258,7 +1258,6 @@ namespace Server.Engines.ConPVP if (dp?.Mobile != null) { - dp.Mobile.CloseGump(); dp.Mobile.SendGump(new CTFBoardGump(dp.Mobile, this)); } } diff --git a/Projects/UOContent/Engines/ConPVP/Games/DoubleDom.cs b/Projects/UOContent/Engines/ConPVP/Games/DoubleDom.cs index 8644f6631..e06bc2864 100644 --- a/Projects/UOContent/Engines/ConPVP/Games/DoubleDom.cs +++ b/Projects/UOContent/Engines/ConPVP/Games/DoubleDom.cs @@ -27,7 +27,6 @@ namespace Server.Engines.ConPVP { if (m_TeamInfo?.Game != null) { - from.CloseGump(); from.SendGump(new DDBoardGump(from, m_TeamInfo.Game)); } } @@ -52,7 +51,7 @@ namespace Server.Engines.ConPVP private const int LabelColor32 = 0xFFFFFF; private const int BlackColor32 = 0x000000; - // private DDGame m_Game; + public override bool Singleton => true; public DDBoardGump(Mobile mob, DDGame game, DDTeamInfo section = null) : base(60, 60) @@ -605,7 +604,6 @@ namespace Server.Engines.ConPVP } } - mob.CloseGump(); mob.SendGump(new DDBoardGump(mob, this)); m_Context.Requip(mob, corpse); @@ -820,7 +818,6 @@ namespace Server.Engines.ConPVP if (dp?.Mobile != null) { - dp.Mobile.CloseGump(); dp.Mobile.SendGump(new DDBoardGump(dp.Mobile, this)); } } diff --git a/Projects/UOContent/Engines/ConPVP/Games/KingOfTheHill.cs b/Projects/UOContent/Engines/ConPVP/Games/KingOfTheHill.cs index ddd09d80b..f1d20e90f 100644 --- a/Projects/UOContent/Engines/ConPVP/Games/KingOfTheHill.cs +++ b/Projects/UOContent/Engines/ConPVP/Games/KingOfTheHill.cs @@ -311,7 +311,6 @@ namespace Server.Engines.ConPVP { if (m_Game != null) { - from.CloseGump(); from.SendGump(new KHBoardGump(from, m_Game)); } else @@ -353,6 +352,8 @@ namespace Server.Engines.ConPVP private KHGame m_Game; + public override bool Singleton => true; + public KHBoardGump(Mobile mob, KHGame game) : base(60, 60) { @@ -989,7 +990,6 @@ namespace Server.Engines.ConPVP } } - mob.CloseGump(); mob.SendGump(new KHBoardGump(mob, this)); m_Context.Requip(mob, corpse); @@ -1199,7 +1199,6 @@ namespace Server.Engines.ConPVP if (dp?.Mobile != null) { - dp.Mobile.CloseGump(); dp.Mobile.SendGump(new KHBoardGump(dp.Mobile, this)); } } diff --git a/Projects/UOContent/Engines/ConPVP/Gumps/ArenaGump.cs b/Projects/UOContent/Engines/ConPVP/Gumps/ArenaGump.cs index 63ba39031..67f8a0047 100644 --- a/Projects/UOContent/Engines/ConPVP/Gumps/ArenaGump.cs +++ b/Projects/UOContent/Engines/ConPVP/Gumps/ArenaGump.cs @@ -50,7 +50,6 @@ namespace Server.Engines.ConPVP return false; } - from.CloseGump(); from.SendGump(new ArenaGump(from, this)); if (!from.Hidden || from.AccessLevel == AccessLevel.Player) @@ -84,6 +83,8 @@ namespace Server.Engines.ConPVP private int m_ColumnX = 12; + public override bool Singleton => true; + public ArenaGump(Mobile from, ArenasMoongate gate) : base(50, 50) { m_From = from; diff --git a/Projects/UOContent/Engines/ConPVP/Gumps/ConfirmSignupGump.cs b/Projects/UOContent/Engines/ConPVP/Gumps/ConfirmSignupGump.cs index 4ca656f78..376042f72 100644 --- a/Projects/UOContent/Engines/ConPVP/Gumps/ConfirmSignupGump.cs +++ b/Projects/UOContent/Engines/ConPVP/Gumps/ConfirmSignupGump.cs @@ -19,6 +19,8 @@ namespace Server.Engines.ConPVP private readonly Mobile m_Registrar; private readonly Tournament m_Tournament; + public override bool Singleton => true; + public ConfirmSignupGump(Mobile from, Mobile registrar, Tournament tourney, List players) : base(50, 50) { m_From = from; @@ -26,10 +28,11 @@ namespace Server.Engines.ConPVP m_Tournament = tourney; m_Players = players; - m_From.CloseGump(); - m_From.CloseGump(); - m_From.CloseGump(); - m_From.CloseGump(); + var gumps = m_From.GetGumps(); + + gumps.Close(); + gumps.Close(); + gumps.Close(); var ruleset = tourney.Ruleset; var basedef = ruleset.Base; diff --git a/Projects/UOContent/Engines/ConPVP/Gumps/DuelContextGump.cs b/Projects/UOContent/Engines/ConPVP/Gumps/DuelContextGump.cs index 157eafb70..ac1b11556 100644 --- a/Projects/UOContent/Engines/ConPVP/Gumps/DuelContextGump.cs +++ b/Projects/UOContent/Engines/ConPVP/Gumps/DuelContextGump.cs @@ -5,14 +5,17 @@ namespace Server.Engines.ConPVP { public class DuelContextGump : Gump { + public override bool Singleton => true; + public DuelContextGump(Mobile from, DuelContext context) : base(50, 50) { From = from; Context = context; - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); + var gumps = from.GetGumps(); + + gumps.Close(); + gumps.Close(); var count = context.Participants.Count; diff --git a/Projects/UOContent/Engines/ConPVP/Gumps/LadderGump.cs b/Projects/UOContent/Engines/ConPVP/Gumps/LadderGump.cs index 8debcacfc..088d26789 100644 --- a/Projects/UOContent/Engines/ConPVP/Gumps/LadderGump.cs +++ b/Projects/UOContent/Engines/ConPVP/Gumps/LadderGump.cs @@ -52,8 +52,7 @@ namespace Server.Engines.ConPVP if (ladder != null) { - from.CloseGump(); - from.SendGump(new LadderGump(ladder)); + from.SendGump(new LadderGump(ladder), true); } } else diff --git a/Projects/UOContent/Engines/ConPVP/Gumps/ParticipantGump.cs b/Projects/UOContent/Engines/ConPVP/Gumps/ParticipantGump.cs index d74646c19..6aad2ce69 100644 --- a/Projects/UOContent/Engines/ConPVP/Gumps/ParticipantGump.cs +++ b/Projects/UOContent/Engines/ConPVP/Gumps/ParticipantGump.cs @@ -7,15 +7,18 @@ namespace Server.Engines.ConPVP { public class ParticipantGump : Gump { + public override bool Singleton => true; + public ParticipantGump(Mobile from, DuelContext context, Participant p) : base(50, 50) { From = from; Context = context; Participant = p; - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); + var gumps = from.GetGumps(); + + gumps.Close(); + gumps.Close(); var count = p.Players.Length; diff --git a/Projects/UOContent/Engines/ConPVP/Gumps/RulesetGump.cs b/Projects/UOContent/Engines/ConPVP/Gumps/RulesetGump.cs index e5ed4c5bc..96397455e 100644 --- a/Projects/UOContent/Engines/ConPVP/Gumps/RulesetGump.cs +++ b/Projects/UOContent/Engines/ConPVP/Gumps/RulesetGump.cs @@ -12,6 +12,8 @@ namespace Server.Engines.ConPVP private readonly bool m_ReadOnly; private readonly Ruleset m_Ruleset; + public override bool Singleton => true; + public RulesetGump(Mobile from, Ruleset ruleset, RulesetLayout page, DuelContext duelContext, bool readOnly = false) : base(readOnly ? 310 : 50, 50) { @@ -23,9 +25,10 @@ namespace Server.Engines.ConPVP Draggable = !readOnly; - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); + var gumps = from.GetGumps(); + + gumps.Close(); + gumps.Close(); var depthCounter = page; diff --git a/Projects/UOContent/Engines/ConPVP/Preferences.cs b/Projects/UOContent/Engines/ConPVP/Preferences.cs index 4b761a6ca..1a63a87e8 100644 --- a/Projects/UOContent/Engines/ConPVP/Preferences.cs +++ b/Projects/UOContent/Engines/ConPVP/Preferences.cs @@ -179,6 +179,8 @@ namespace Server.Engines.ConPVP private readonly PreferencesEntry m_Entry; private int m_ColumnX = 12; + public override bool Singleton => true; + public PreferencesGump(Mobile from, Preferences prefs) : base(50, 50) { m_Entry = prefs.Find(from); diff --git a/Projects/UOContent/Engines/ConPVP/TournamentBracketItem.cs b/Projects/UOContent/Engines/ConPVP/TournamentBracketItem.cs index bcc3bb037..5fc71cb29 100644 --- a/Projects/UOContent/Engines/ConPVP/TournamentBracketItem.cs +++ b/Projects/UOContent/Engines/ConPVP/TournamentBracketItem.cs @@ -1,3 +1,5 @@ +using Server.Gumps; + namespace Server.Engines.ConPVP { public class TournamentBracketItem : Item @@ -26,8 +28,7 @@ namespace Server.Engines.ConPVP if (tourney != null) { - from.CloseGump(); - from.SendGump(new TournamentBracketGump(from, tourney, TourneyBracketGumpType.Index)); + from.SendGump(new TournamentBracketGump(from, tourney, TourneyBracketGumpType.Index), true); } } } diff --git a/Projects/UOContent/Engines/ConPVP/TournamentController.cs b/Projects/UOContent/Engines/ConPVP/TournamentController.cs index 88a352320..4cf5c8adb 100644 --- a/Projects/UOContent/Engines/ConPVP/TournamentController.cs +++ b/Projects/UOContent/Engines/ConPVP/TournamentController.cs @@ -66,9 +66,11 @@ namespace Server.Engines.ConPVP { if (from.AccessLevel >= AccessLevel.GameMaster && Tournament != null) { - from.CloseGump(); - from.CloseGump(); - from.SendGump(new PickRulesetGump(from, null, Tournament.Ruleset)); + var gumps = from.GetGumps(); + + gumps.Close(); + gumps.Close(); + gumps.Send(new PickRulesetGump(from, null, Tournament.Ruleset)); } } diff --git a/Projects/UOContent/Engines/ConPVP/TournamentSignupItem.cs b/Projects/UOContent/Engines/ConPVP/TournamentSignupItem.cs index 2e086545a..40733e15f 100644 --- a/Projects/UOContent/Engines/ConPVP/TournamentSignupItem.cs +++ b/Projects/UOContent/Engines/ConPVP/TournamentSignupItem.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using Server.Factions; +using Server.Gumps; using Server.Mobiles; namespace Server.Engines.ConPVP @@ -146,7 +147,6 @@ namespace Server.Engines.ConPVP } else if (!tourney.HasParticipant(from)) { - from.CloseGump(); from.SendGump(new ConfirmSignupGump(from, Registrar, tourney, new List { from })); } else diff --git a/Projects/UOContent/Engines/Craft/Core/CraftGump.cs b/Projects/UOContent/Engines/Craft/Core/CraftGump.cs index 96ff059ac..c9c55bfb7 100644 --- a/Projects/UOContent/Engines/Craft/Core/CraftGump.cs +++ b/Projects/UOContent/Engines/Craft/Core/CraftGump.cs @@ -24,6 +24,8 @@ public class CraftGump : DynamicGump private readonly BaseTool _tool; private readonly TextDefinition _notice; + public override bool Singleton => true; + public CraftGump( Mobile from, CraftSystem craftSystem, BaseTool tool, TextDefinition notice, CraftPage page = CraftPage.None ) : base(40, 40) @@ -419,7 +421,6 @@ public class CraftGump : DynamicGump public override void SendTo(NetState ns) { - _from.CloseGump(); _from.CloseGump(); base.SendTo(ns); diff --git a/Projects/UOContent/Engines/Craft/Core/CraftGumpItem.cs b/Projects/UOContent/Engines/Craft/Core/CraftGumpItem.cs index e016665f5..a8938b511 100644 --- a/Projects/UOContent/Engines/Craft/Core/CraftGumpItem.cs +++ b/Projects/UOContent/Engines/Craft/Core/CraftGumpItem.cs @@ -27,6 +27,8 @@ namespace Server.Engines.Craft private bool m_ShowExceptionalChance; + public override bool Singleton => true; + public CraftGumpItem(Mobile from, CraftSystem craftSystem, CraftItem craftItem, BaseTool tool) : base(40, 40) { m_From = from; @@ -34,9 +36,6 @@ namespace Server.Engines.Craft m_CraftItem = craftItem; m_Tool = tool; - from.CloseGump(); - from.CloseGump(); - AddPage(0); AddBackground(0, 0, 530, 417, 5054); AddImageTiled(10, 10, 510, 22, 2624); diff --git a/Projects/UOContent/Engines/Craft/Core/CraftItem.cs b/Projects/UOContent/Engines/Craft/Core/CraftItem.cs index 86633d2f2..42e7856f7 100644 --- a/Projects/UOContent/Engines/Craft/Core/CraftItem.cs +++ b/Projects/UOContent/Engines/Craft/Core/CraftItem.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using Server.Commands; using Server.Factions; +using Server.Gumps; using Server.Items; using Server.Logging; using Server.Mobiles; diff --git a/Projects/UOContent/Engines/Craft/Core/Enhance.cs b/Projects/UOContent/Engines/Craft/Core/Enhance.cs index 99a70464f..58f4280cc 100644 --- a/Projects/UOContent/Engines/Craft/Core/Enhance.cs +++ b/Projects/UOContent/Engines/Craft/Core/Enhance.cs @@ -1,4 +1,5 @@ using System; +using Server.Gumps; using Server.Items; using Server.Targeting; diff --git a/Projects/UOContent/Engines/Craft/Core/QueryMakersMarkGump.cs b/Projects/UOContent/Engines/Craft/Core/QueryMakersMarkGump.cs index dba819d19..60f6fec45 100644 --- a/Projects/UOContent/Engines/Craft/Core/QueryMakersMarkGump.cs +++ b/Projects/UOContent/Engines/Craft/Core/QueryMakersMarkGump.cs @@ -14,13 +14,13 @@ namespace Server.Engines.Craft private readonly BaseTool m_Tool; private readonly Type m_TypeRes; + public override bool Singleton => true; + public QueryMakersMarkGump( int quality, Mobile from, CraftItem craftItem, CraftSystem craftSystem, Type typeRes, BaseTool tool ) : base(100, 200) { - from.CloseGump(); - m_Quality = quality; m_From = from; m_CraftItem = craftItem; diff --git a/Projects/UOContent/Engines/Craft/Core/Repair.cs b/Projects/UOContent/Engines/Craft/Core/Repair.cs index 391b76382..d8bb2ae7e 100644 --- a/Projects/UOContent/Engines/Craft/Core/Repair.cs +++ b/Projects/UOContent/Engines/Craft/Core/Repair.cs @@ -1,4 +1,5 @@ using System; +using Server.Gumps; using Server.Items; using Server.Mobiles; using Server.Targeting; diff --git a/Projects/UOContent/Engines/Craft/Core/Resmelt.cs b/Projects/UOContent/Engines/Craft/Core/Resmelt.cs index 05dbe1e6f..8ea625822 100644 --- a/Projects/UOContent/Engines/Craft/Core/Resmelt.cs +++ b/Projects/UOContent/Engines/Craft/Core/Resmelt.cs @@ -1,4 +1,5 @@ using Server.Ethics; +using Server.Gumps; using Server.Items; using Server.Targeting; diff --git a/Projects/UOContent/Engines/Craft/DefTinkering.cs b/Projects/UOContent/Engines/Craft/DefTinkering.cs index 009a9e34e..836ca0978 100644 --- a/Projects/UOContent/Engines/Craft/DefTinkering.cs +++ b/Projects/UOContent/Engines/Craft/DefTinkering.cs @@ -1,5 +1,6 @@ using System; using Server.Factions; +using Server.Gumps; using Server.Items; using Server.Targeting; diff --git a/Projects/UOContent/Engines/Factions/Core/Faction.cs b/Projects/UOContent/Engines/Factions/Core/Faction.cs index b5ae2d8f0..a7171c0c2 100644 --- a/Projects/UOContent/Engines/Factions/Core/Faction.cs +++ b/Projects/UOContent/Engines/Factions/Core/Faction.cs @@ -5,6 +5,7 @@ using Server.Commands.Generic; using Server.Engines.ConPVP; using Server.Ethics; using Server.Guilds; +using Server.Gumps; using Server.Items; using Server.Mobiles; using Server.Prompts; diff --git a/Projects/UOContent/Engines/Factions/Core/Keywords.cs b/Projects/UOContent/Engines/Factions/Core/Keywords.cs index c2c6e95d3..099af414d 100644 --- a/Projects/UOContent/Engines/Factions/Core/Keywords.cs +++ b/Projects/UOContent/Engines/Factions/Core/Keywords.cs @@ -1,3 +1,4 @@ +using Server.Gumps; using Server.Mobiles; namespace Server.Factions; diff --git a/Projects/UOContent/Engines/Factions/Items/FactionStone.cs b/Projects/UOContent/Engines/Factions/Items/FactionStone.cs index fbfce0845..f17d61a88 100644 --- a/Projects/UOContent/Engines/Factions/Items/FactionStone.cs +++ b/Projects/UOContent/Engines/Factions/Items/FactionStone.cs @@ -1,3 +1,4 @@ +using Server.Gumps; using Server.Mobiles; namespace Server.Factions; diff --git a/Projects/UOContent/Engines/Factions/Items/JoinStone.cs b/Projects/UOContent/Engines/Factions/Items/JoinStone.cs index 92abdaa14..19369d163 100644 --- a/Projects/UOContent/Engines/Factions/Items/JoinStone.cs +++ b/Projects/UOContent/Engines/Factions/Items/JoinStone.cs @@ -1,3 +1,4 @@ +using Server.Gumps; using Server.Mobiles; namespace Server.Factions; diff --git a/Projects/UOContent/Engines/Factions/Items/TownStone.cs b/Projects/UOContent/Engines/Factions/Items/TownStone.cs index 7bf02bce8..0c9b560c9 100644 --- a/Projects/UOContent/Engines/Factions/Items/TownStone.cs +++ b/Projects/UOContent/Engines/Factions/Items/TownStone.cs @@ -1,3 +1,4 @@ +using Server.Gumps; using Server.Mobiles; namespace Server.Factions; diff --git a/Projects/UOContent/Engines/Factions/Mobiles/Vendors/FactionHorseVendor.cs b/Projects/UOContent/Engines/Factions/Mobiles/Vendors/FactionHorseVendor.cs index 3bacb042c..b170399fe 100644 --- a/Projects/UOContent/Engines/Factions/Mobiles/Vendors/FactionHorseVendor.cs +++ b/Projects/UOContent/Engines/Factions/Mobiles/Vendors/FactionHorseVendor.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using ModernUO.Serialization; +using Server.Gumps; using Server.Items; using Server.Mobiles; diff --git a/Projects/UOContent/Engines/Help/HelpGump.cs b/Projects/UOContent/Engines/Help/HelpGump.cs index 5d28a4fe6..d23552a35 100644 --- a/Projects/UOContent/Engines/Help/HelpGump.cs +++ b/Projects/UOContent/Engines/Help/HelpGump.cs @@ -58,6 +58,8 @@ public sealed class HelpGump : DynamicGump { private readonly Mobile _from; + public override bool Singleton => true; + public HelpGump(Mobile from) : base(0, 0) => _from = from; protected override void BuildLayout(ref DynamicGumpBuilder builder) @@ -206,12 +208,6 @@ public sealed class HelpGump : DynamicGump builder.AddHtmlLocalized(180, y + 150, 335, 40, 1001015); // NO - I meant to ask for help with another matter. } - public override void SendTo(NetState ns) - { - _from.CloseGump(); - base.SendTo(ns); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] private static void AddOption( ref DynamicGumpBuilder builder, int y, int buttonId, int localizedName, GumpButtonType type = GumpButtonType.Reply, @@ -237,12 +233,9 @@ public sealed class HelpGump : DynamicGump public static void HelpRequest(Mobile m) { - foreach (var gump in m.NetState.Gumps) + if (m.HasGump()) { - if (gump is HelpGump) - { - return; - } + return; } if (!PageQueue.CheckAllowedToPage(m)) diff --git a/Projects/UOContent/Engines/Help/PagePromptGump.cs b/Projects/UOContent/Engines/Help/PagePromptGump.cs index bfa38695b..7814ffedd 100644 --- a/Projects/UOContent/Engines/Help/PagePromptGump.cs +++ b/Projects/UOContent/Engines/Help/PagePromptGump.cs @@ -8,6 +8,8 @@ public sealed class PagePromptGump : StaticGump private readonly Mobile _from; private readonly PageType _type; + public override bool Singleton => true; + public PagePromptGump(Mobile from, PageType type) : base(0, 0) { _from = from; @@ -31,12 +33,6 @@ public sealed class PagePromptGump : StaticGump builder. AddButton(405, 355, 2073, 2072, 0); // Cancel } - public override void SendTo(NetState ns) - { - _from.CloseGump(); - base.SendTo(ns); - } - public override void OnResponse(NetState sender, in RelayInfo info) { if (info.ButtonID == 0) diff --git a/Projects/UOContent/Engines/Help/PageQueue.cs b/Projects/UOContent/Engines/Help/PageQueue.cs index 6a248f857..eac51bf81 100644 --- a/Projects/UOContent/Engines/Help/PageQueue.cs +++ b/Projects/UOContent/Engines/Help/PageQueue.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Server.Gumps; using Server.Misc; using Server.Mobiles; using Server.Network; diff --git a/Projects/UOContent/Engines/Help/PageQueueGump.cs b/Projects/UOContent/Engines/Help/PageQueueGump.cs index 779d1fcdd..aa2bc3bd1 100644 --- a/Projects/UOContent/Engines/Help/PageQueueGump.cs +++ b/Projects/UOContent/Engines/Help/PageQueueGump.cs @@ -118,9 +118,7 @@ namespace Server.Engines.Help { if (PageQueue.List.IndexOf(m_List[info.ButtonID - 1]) >= 0) { - var g = new PageEntryGump(state.Mobile, m_List[info.ButtonID - 1]); - - g.SendTo(state); + state.SendGump(new PageEntryGump(state.Mobile, m_List[info.ButtonID - 1])); } else { @@ -224,13 +222,13 @@ namespace Server.Engines.Help private readonly Mobile m_From; private readonly PredefinedResponse m_Response; + public override bool Singleton => true; + public PredefGump(Mobile from, PredefinedResponse response) : base(30, 30) { m_From = from; m_Response = response; - from.CloseGump(); - var canEdit = from.AccessLevel >= AccessLevel.GameMaster; AddPage(0); @@ -593,9 +591,7 @@ namespace Server.Engines.Help public void Resend(NetState state) { - var g = new PageEntryGump(m_Mobile, m_Entry); - - g.SendTo(state); + state.SendGump(new PageEntryGump(m_Mobile, m_Entry)); } public override void OnResponse(NetState state, in RelayInfo info) @@ -613,9 +609,7 @@ namespace Server.Engines.Help { if (m_Entry.Handler != state.Mobile) { - var g = new PageQueueGump(); - - g.SendTo(state); + state.SendGump(new PageQueueGump()); } break; @@ -722,10 +716,7 @@ namespace Server.Engines.Help PageQueue.Remove(m_Entry); state.Mobile.SendMessage("You delete the page."); - - var g = new PageQueueGump(); - - g.SendTo(state); + state.SendGump(new PageQueueGump()); } else { @@ -764,10 +755,7 @@ namespace Server.Engines.Help m_Entry.Handler = null; state.Mobile.SendMessage("You mark the page as handled, and remove it from the queue."); - - var g = new PageQueueGump(); - - g.SendTo(state); + state.SendGump(new PageQueueGump()); } else { diff --git a/Projects/UOContent/Engines/Khaldun/PuzzleChest.cs b/Projects/UOContent/Engines/Khaldun/PuzzleChest.cs index 5de709331..48a1edd9d 100644 --- a/Projects/UOContent/Engines/Khaldun/PuzzleChest.cs +++ b/Projects/UOContent/Engines/Khaldun/PuzzleChest.cs @@ -290,9 +290,11 @@ namespace Server.Items ); } - from.CloseGump(); - from.CloseGump(); - from.SendGump(new PuzzleGump(from, this, solution, 0)); + var gumps = from.GetGumps(); + + gumps.Close(); + gumps.Close(); + gumps.Send(new PuzzleGump(from, this, solution, 0)); return true; } diff --git a/Projects/UOContent/Engines/ML Quests/Gumps/BaseQuestGump.cs b/Projects/UOContent/Engines/ML Quests/Gumps/BaseQuestGump.cs index 7cc76025b..4651454ba 100644 --- a/Projects/UOContent/Engines/ML Quests/Gumps/BaseQuestGump.cs +++ b/Projects/UOContent/Engines/ML Quests/Gumps/BaseQuestGump.cs @@ -268,12 +268,13 @@ namespace Server.Engines.MLQuests.Gumps */ public static void CloseOtherGumps(PlayerMobile pm) { - pm.CloseGump(); - pm.CloseGump(); - pm.CloseGump(); - pm.CloseGump(); - // pm.CloseGump( typeof( UnknownGump807 ) ); - pm.CloseGump(); + var gumps = pm.GetGumps(); + + gumps.Close(); + gumps.Close(); + gumps.Close(); + gumps.Close(); + gumps.Close(); } private struct ButtonInfo diff --git a/Projects/UOContent/Engines/ML Quests/Gumps/QuestLogDetailedGump.cs b/Projects/UOContent/Engines/ML Quests/Gumps/QuestLogDetailedGump.cs index 53bcb3c0e..b4f0da864 100644 --- a/Projects/UOContent/Engines/ML Quests/Gumps/QuestLogDetailedGump.cs +++ b/Projects/UOContent/Engines/ML Quests/Gumps/QuestLogDetailedGump.cs @@ -8,6 +8,8 @@ namespace Server.Engines.MLQuests.Gumps private readonly bool m_CloseGumps; private readonly MLQuestInstance m_Instance; + public override bool Singleton => true; + public QuestLogDetailedGump(MLQuestInstance instance, bool closeGumps = true) : base(1046026) // Quest Log { @@ -20,7 +22,6 @@ namespace Server.Engines.MLQuests.Gumps if (closeGumps) { CloseOtherGumps(pm); - pm.CloseGump(); } SetTitle(quest.Title); diff --git a/Projects/UOContent/Engines/ML Quests/Gumps/QuestLogGump.cs b/Projects/UOContent/Engines/ML Quests/Gumps/QuestLogGump.cs index cb957a8b0..6927ce544 100644 --- a/Projects/UOContent/Engines/ML Quests/Gumps/QuestLogGump.cs +++ b/Projects/UOContent/Engines/ML Quests/Gumps/QuestLogGump.cs @@ -9,6 +9,8 @@ namespace Server.Engines.MLQuests.Gumps private readonly bool m_CloseGumps; private readonly PlayerMobile m_Owner; + public override bool Singleton => true; + public QuestLogGump(PlayerMobile pm, bool closeGumps = true) : base(1046026) // Quest Log { @@ -17,7 +19,6 @@ namespace Server.Engines.MLQuests.Gumps if (closeGumps) { - pm.CloseGump(); pm.CloseGump(); } diff --git a/Projects/UOContent/Engines/ML Quests/Gumps/QuestOfferGump.cs b/Projects/UOContent/Engines/ML Quests/Gumps/QuestOfferGump.cs index 85b6152b2..76314649f 100644 --- a/Projects/UOContent/Engines/ML Quests/Gumps/QuestOfferGump.cs +++ b/Projects/UOContent/Engines/ML Quests/Gumps/QuestOfferGump.cs @@ -9,6 +9,8 @@ namespace Server.Engines.MLQuests.Gumps private readonly MLQuest m_Quest; private readonly IQuestGiver m_Quester; + public override bool Singleton => true; + public QuestOfferGump(MLQuest quest, IQuestGiver quester, PlayerMobile pm) : base(1049010) // Quest Offer { @@ -16,7 +18,6 @@ namespace Server.Engines.MLQuests.Gumps m_Quester = quester; CloseOtherGumps(pm); - pm.CloseGump(); SetTitle(quest.Title); RegisterButton(ButtonPosition.Left, ButtonGraphic.Accept, 1); diff --git a/Projects/UOContent/Engines/ML Quests/Gumps/RaceChangeGump.cs b/Projects/UOContent/Engines/ML Quests/Gumps/RaceChangeGump.cs index 667f56ca1..42d161a8a 100644 --- a/Projects/UOContent/Engines/ML Quests/Gumps/RaceChangeGump.cs +++ b/Projects/UOContent/Engines/ML Quests/Gumps/RaceChangeGump.cs @@ -27,11 +27,11 @@ namespace Server.Engines.MLQuests.Gumps private readonly IRaceChanger m_Owner; private readonly Race m_Race; + public override bool Singleton => true; + public RaceChangeConfirmGump(IRaceChanger owner, PlayerMobile from, Race targetRace) : base(50, 50) { - from.CloseGump(); - m_Owner = owner; m_From = from; m_Race = targetRace; diff --git a/Projects/UOContent/Engines/ML Quests/MLQuest.cs b/Projects/UOContent/Engines/ML Quests/MLQuest.cs index e714cae40..b0ec81a0d 100644 --- a/Projects/UOContent/Engines/ML Quests/MLQuest.cs +++ b/Projects/UOContent/Engines/ML Quests/MLQuest.cs @@ -5,6 +5,7 @@ using Server.Engines.MLQuests.Gumps; using Server.Engines.MLQuests.Objectives; using Server.Engines.MLQuests.Rewards; using Server.Engines.Spawners; +using Server.Gumps; using Server.Mobiles; namespace Server.Engines.MLQuests diff --git a/Projects/UOContent/Engines/ML Quests/MLQuestEntry.cs b/Projects/UOContent/Engines/ML Quests/MLQuestEntry.cs index 598a45995..167780444 100644 --- a/Projects/UOContent/Engines/ML Quests/MLQuestEntry.cs +++ b/Projects/UOContent/Engines/ML Quests/MLQuestEntry.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using Server.Engines.MLQuests.Gumps; using Server.Engines.MLQuests.Objectives; +using Server.Gumps; using Server.Mobiles; namespace Server.Engines.MLQuests diff --git a/Projects/UOContent/Engines/ML Quests/Mobiles/BoonCollector.cs b/Projects/UOContent/Engines/ML Quests/Mobiles/BoonCollector.cs index a128bfba5..6dd4e4782 100644 --- a/Projects/UOContent/Engines/ML Quests/Mobiles/BoonCollector.cs +++ b/Projects/UOContent/Engines/ML Quests/Mobiles/BoonCollector.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using ModernUO.Serialization; using Server.Engines.MLQuests.Definitions; using Server.Engines.MLQuests.Gumps; +using Server.Gumps; using Server.Items; using Server.Mobiles; diff --git a/Projects/UOContent/Engines/Plants/PlantPourTarget.cs b/Projects/UOContent/Engines/Plants/PlantPourTarget.cs index fc0a6144f..6be83a241 100644 --- a/Projects/UOContent/Engines/Plants/PlantPourTarget.cs +++ b/Projects/UOContent/Engines/Plants/PlantPourTarget.cs @@ -1,3 +1,4 @@ +using Server.Gumps; using Server.Targeting; namespace Server.Engines.Plants @@ -21,12 +22,7 @@ namespace Server.Engines.Plants if (!m_Plant.Deleted && m_Plant.PlantStatus < PlantStatus.DecorativePlant && from.InRange(m_Plant.GetWorldLocation(), 3) && m_Plant.IsUsableBy(from)) { - if (from.HasGump()) - { - from.CloseGump(); - } - - from.SendGump(new MainPlantGump(m_Plant)); + from.SendGump(new MainPlantGump(m_Plant), true); } } } diff --git a/Projects/UOContent/Engines/Plants/PollinateTarget.cs b/Projects/UOContent/Engines/Plants/PollinateTarget.cs index 9b85b2a2a..720060afc 100644 --- a/Projects/UOContent/Engines/Plants/PollinateTarget.cs +++ b/Projects/UOContent/Engines/Plants/PollinateTarget.cs @@ -1,3 +1,4 @@ +using Server.Gumps; using Server.Targeting; namespace Server.Engines.Plants diff --git a/Projects/UOContent/Engines/Quests/Collector/Mobiles/Impresario.cs b/Projects/UOContent/Engines/Quests/Collector/Mobiles/Impresario.cs index efef0d89e..68cec5725 100644 --- a/Projects/UOContent/Engines/Quests/Collector/Mobiles/Impresario.cs +++ b/Projects/UOContent/Engines/Quests/Collector/Mobiles/Impresario.cs @@ -55,7 +55,6 @@ public partial class Impresario : BaseQuester if (obj.IsInRightTheater()) { - player.CloseGump(); player.SendGump(new SheetMusicOfferGump()); } else @@ -68,6 +67,8 @@ public partial class Impresario : BaseQuester public class SheetMusicOfferGump : BaseQuestGump { + public override bool Singleton => true; + public SheetMusicOfferGump() : base(75, 25) { Closable = false; diff --git a/Projects/UOContent/Engines/Quests/Core/QuestObjective.cs b/Projects/UOContent/Engines/Quests/Core/QuestObjective.cs index 01f49da5a..f5abbe49b 100644 --- a/Projects/UOContent/Engines/Quests/Core/QuestObjective.cs +++ b/Projects/UOContent/Engines/Quests/Core/QuestObjective.cs @@ -130,6 +130,8 @@ namespace Server.Engines.Quests { private readonly QuestSystem m_System; + public override bool Singleton => true; + public QuestLogUpdatedGump(QuestSystem system) : base(3, 30) { m_System = system; diff --git a/Projects/UOContent/Engines/Quests/Core/QuestSystem.cs b/Projects/UOContent/Engines/Quests/Core/QuestSystem.cs index 11a3de25e..2b0ace340 100644 --- a/Projects/UOContent/Engines/Quests/Core/QuestSystem.cs +++ b/Projects/UOContent/Engines/Quests/Core/QuestSystem.cs @@ -264,7 +264,6 @@ namespace Server.Engines.Quests public virtual void ShowQuestLogUpdated() { - From.CloseGump(); From.SendGump(new QuestLogUpdatedGump(this)); } @@ -272,18 +271,19 @@ namespace Server.Engines.Quests { if (Objectives.Count > 0) { - From.CloseGump(); - From.CloseGump(); - From.CloseGump(); - From.CloseGump(); + var gumps = From.GetGumps(); + gumps.Close(); + gumps.Close(); + gumps.Close(); + gumps.Close(); - From.SendGump(new QuestObjectivesGump(Objectives)); + gumps.Send(new QuestObjectivesGump(Objectives)); var last = Objectives[^1]; if (last.Info != null) { - From.SendGump(new QuestItemInfoGump(last.Info)); + gumps.Send(new QuestItemInfoGump(last.Info)); } } } @@ -292,11 +292,13 @@ namespace Server.Engines.Quests { if (Conversations.Count > 0) { - From.CloseGump(); - From.CloseGump(); - From.CloseGump(); + var gumps = From.GetGumps(); - From.SendGump(new QuestConversationsGump(Conversations)); + gumps.Close(); + gumps.Close(); + gumps.Close(); + + gumps.Send(new QuestConversationsGump(Conversations)); var last = Conversations[^1]; @@ -389,10 +391,10 @@ namespace Server.Engines.Quests Conversations.Add(conv); } - From.CloseGump(); - From.CloseGump(); - From.CloseGump(); - From.SendGump(conv.Logged ? new QuestConversationsGump(Conversations) : new QuestConversationsGump(conv)); + var gumps = From.GetGumps(); + gumps.Close(); + gumps.Close(); + gumps.Send(conv.Logged ? new QuestConversationsGump(Conversations) : new QuestConversationsGump(conv)); if (conv.Info != null) { diff --git a/Projects/UOContent/Engines/Quests/Dark Tides/Mobiles/Mardoth.cs b/Projects/UOContent/Engines/Quests/Dark Tides/Mobiles/Mardoth.cs index 325de1dd6..d5086fbd2 100644 --- a/Projects/UOContent/Engines/Quests/Dark Tides/Mobiles/Mardoth.cs +++ b/Projects/UOContent/Engines/Quests/Dark Tides/Mobiles/Mardoth.cs @@ -186,7 +186,6 @@ public partial class Mardoth : BaseQuester m.PlaySound(0x214); m.FixedEffect(0x376A, 10, 16); - m.CloseGump(); m.SendGump(new ResurrectGump(m, ResurrectMessage.Healer)); } } diff --git a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Mobiles/Emino.cs b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Mobiles/Emino.cs index b0fa07fb7..2e4826d87 100644 --- a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Mobiles/Emino.cs +++ b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Mobiles/Emino.cs @@ -203,7 +203,6 @@ public partial class Emino : BaseQuester m.PlaySound(0x214); m.FixedEffect(0x376A, 10, 16); - m.CloseGump(); m.SendGump(new ResurrectGump(m, ResurrectMessage.Healer)); } } diff --git a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Mobiles/Zoel.cs b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Mobiles/Zoel.cs index 38e199612..a204af2d8 100644 --- a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Mobiles/Zoel.cs +++ b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Mobiles/Zoel.cs @@ -105,7 +105,6 @@ public partial class Zoel : BaseQuester m.PlaySound(0x214); m.FixedEffect(0x376A, 10, 16); - m.CloseGump(); m.SendGump(new ResurrectGump(m, ResurrectMessage.Healer)); } } diff --git a/Projects/UOContent/Engines/Quests/Regions/CancelQuestRegion.cs b/Projects/UOContent/Engines/Quests/Regions/CancelQuestRegion.cs index 4772df0ce..34aa56731 100644 --- a/Projects/UOContent/Engines/Quests/Regions/CancelQuestRegion.cs +++ b/Projects/UOContent/Engines/Quests/Regions/CancelQuestRegion.cs @@ -1,4 +1,5 @@ using System; +using Server.Gumps; using Server.Regions; using Server.Mobiles; diff --git a/Projects/UOContent/Engines/Quests/The Summoning/Mobiles/Chyloth.cs b/Projects/UOContent/Engines/Quests/The Summoning/Mobiles/Chyloth.cs index 7eb7b6a90..9a333909f 100644 --- a/Projects/UOContent/Engines/Quests/The Summoning/Mobiles/Chyloth.cs +++ b/Projects/UOContent/Engines/Quests/The Summoning/Mobiles/Chyloth.cs @@ -220,7 +220,6 @@ public partial class Chyloth : BaseQuester AngryAt = null; } - member.CloseGump(); member.SendGump(new ChylothPartyGump(from, member)); } } diff --git a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/Schmendrick.cs b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/Schmendrick.cs index c603f1b5d..1db6a6f2b 100644 --- a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/Schmendrick.cs +++ b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/Schmendrick.cs @@ -130,7 +130,6 @@ public partial class Schmendrick : BaseQuester m.PlaySound(0x214); m.FixedEffect(0x376A, 10, 16); - m.CloseGump(); m.SendGump(new ResurrectGump(m, ResurrectMessage.Healer)); } } diff --git a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/Uzeraan.cs b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/Uzeraan.cs index 4c69002ab..2e46d1686 100644 --- a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/Uzeraan.cs +++ b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/Uzeraan.cs @@ -391,7 +391,6 @@ public partial class Uzeraan : BaseQuester m.PlaySound(0x214); m.FixedEffect(0x376A, 10, 16); - m.CloseGump(); m.SendGump(new ResurrectGump(m, ResurrectMessage.Healer)); } } diff --git a/Projects/UOContent/Engines/Spawners/BaseSpawner.cs b/Projects/UOContent/Engines/Spawners/BaseSpawner.cs index fa3387ab3..28e423313 100644 --- a/Projects/UOContent/Engines/Spawners/BaseSpawner.cs +++ b/Projects/UOContent/Engines/Spawners/BaseSpawner.cs @@ -4,6 +4,7 @@ using System.Reflection; using System.Text.Json; using ModernUO.Serialization; using Server.Commands; +using Server.Gumps; using Server.Items; using Server.Json; using Server.Mobiles; diff --git a/Projects/UOContent/Engines/Treasures of Tokuno/TreasuresOfTokuno.cs b/Projects/UOContent/Engines/Treasures of Tokuno/TreasuresOfTokuno.cs index 0ff5f1b73..353016c07 100644 --- a/Projects/UOContent/Engines/Treasures of Tokuno/TreasuresOfTokuno.cs +++ b/Projects/UOContent/Engines/Treasures of Tokuno/TreasuresOfTokuno.cs @@ -291,6 +291,8 @@ namespace Server.Mobiles { if (m.Alive && m is PlayerMobile pm) { + var gumps = pm.GetGumps(); + if (pm.Alive && (Z - pm.Z).Abs() < 16 && InRange(m, 3) && !InRange(oldLocation, 3)) { if (pm.ToTItemsTurnedIn >= TreasuresOfTokuno.ItemsPerReward) @@ -298,11 +300,11 @@ namespace Server.Mobiles // Congratulations! You have turned in enough minor treasures to earn a greater reward. SayTo(pm, 1070980); - pm.CloseGump(); // Sanity + gumps.Close(); // Sanity if (!pm.HasGump()) { - pm.SendGump(new ToTRedeemGump(this, false)); + gumps.Send(new ToTRedeemGump(this, false)); } } else @@ -325,7 +327,7 @@ namespace Server.Mobiles if (buttons?.Count > 0 && !pm.HasGump()) { - pm.SendGump(new ToTTurnInGump(this, buttons)); + gumps.Send(new ToTTurnInGump(this, buttons)); } } } @@ -334,8 +336,8 @@ namespace Server.Mobiles if (!InRange(m, leaveRange) && InRange(oldLocation, leaveRange)) { - pm.CloseGump(); - pm.CloseGump(); + gumps.Close(); + gumps.Close(); } } } @@ -412,16 +414,18 @@ namespace Server.Gumps item.Delete(); + var gumps = pm.GetGumps(); + if (++pm.ToTItemsTurnedIn >= TreasuresOfTokuno.ItemsPerReward) { // Congratulations! You have turned in enough minor treasures to earn a greater reward. m_Collector.SayTo(pm, 1070980); - pm.CloseGump(); // Sanity + gumps.Close(); // Sanity - if (!pm.HasGump()) + if (!gumps.Has()) { - pm.SendGump(new ToTRedeemGump(m_Collector, false)); + gumps.Send(new ToTRedeemGump(m_Collector, false)); } } else @@ -434,11 +438,11 @@ namespace Server.Gumps var buttons = FindRedeemableItems(pm); - pm.CloseGump(); // Sanity + gumps.Close(); // Sanity if (buttons?.Count > 0) { - pm.SendGump(new ToTTurnInGump(m_Collector, buttons)); + gumps.Send(new ToTTurnInGump(m_Collector, buttons)); } } } @@ -594,9 +598,7 @@ namespace Server.Gumps if (t.Type == typeof(PigmentsOfTokuno)) // Special case of course. { pm.CloseGump(); // Sanity - pm.CloseGump(); - - pm.SendGump(new ToTRedeemGump(m_Collector, true)); + pm.SendGump(new ToTRedeemGump(m_Collector, true), true); return; } diff --git a/Projects/UOContent/Engines/Veteran Rewards/Character Statue Maker/CharacterStatue.cs b/Projects/UOContent/Engines/Veteran Rewards/Character Statue Maker/CharacterStatue.cs index b60da0188..5a8b128ab 100644 --- a/Projects/UOContent/Engines/Veteran Rewards/Character Statue Maker/CharacterStatue.cs +++ b/Projects/UOContent/Engines/Veteran Rewards/Character Statue Maker/CharacterStatue.cs @@ -591,8 +591,7 @@ public class CharacterStatueTarget : Target _maker.Delete(); statue.Sculpt(from); - from.CloseGump(); - from.SendGump(new CharacterStatueGump(_maker, statue, from)); + from.SendGump(new CharacterStatueGump(_maker, statue, from), true); return; } diff --git a/Projects/UOContent/Engines/Veteran Rewards/RewardChoiceGump.cs b/Projects/UOContent/Engines/Veteran Rewards/RewardChoiceGump.cs index 037aeaf01..887d728a6 100644 --- a/Projects/UOContent/Engines/Veteran Rewards/RewardChoiceGump.cs +++ b/Projects/UOContent/Engines/Veteran Rewards/RewardChoiceGump.cs @@ -8,12 +8,12 @@ namespace Server.Engines.VeteranRewards { private readonly Mobile m_From; + public override bool Singleton => true; + public RewardChoiceGump(Mobile from) : base(0, 0) { m_From = from; - from.CloseGump(); - RenderBackground(); RenderCategories(); } diff --git a/Projects/UOContent/Engines/Veteran Rewards/RewardConfirmGump.cs b/Projects/UOContent/Engines/Veteran Rewards/RewardConfirmGump.cs index 5a9502a07..200f73d91 100644 --- a/Projects/UOContent/Engines/Veteran Rewards/RewardConfirmGump.cs +++ b/Projects/UOContent/Engines/Veteran Rewards/RewardConfirmGump.cs @@ -9,13 +9,13 @@ namespace Server.Engines.VeteranRewards private readonly RewardEntry m_Entry; private readonly Mobile m_From; + public override bool Singleton => true; + public RewardConfirmGump(Mobile from, RewardEntry entry) : base(0, 0) { m_From = from; m_Entry = entry; - from.CloseGump(); - AddPage(0); AddBackground(10, 10, 500, 300, 2600); diff --git a/Projects/UOContent/Engines/Veteran Rewards/RewardDemolitionGump.cs b/Projects/UOContent/Engines/Veteran Rewards/RewardDemolitionGump.cs index 270c2af29..33df28c6e 100644 --- a/Projects/UOContent/Engines/Veteran Rewards/RewardDemolitionGump.cs +++ b/Projects/UOContent/Engines/Veteran Rewards/RewardDemolitionGump.cs @@ -8,6 +8,8 @@ namespace Server.Gumps { private readonly IAddon m_Addon; + public override bool Singleton => true; + public RewardDemolitionGump(IAddon addon, int question) : base(150, 50) { m_Addon = addon; diff --git a/Projects/UOContent/Engines/Veteran Rewards/RewardNoticeGump.cs b/Projects/UOContent/Engines/Veteran Rewards/RewardNoticeGump.cs index 4c62a312a..dc1294822 100644 --- a/Projects/UOContent/Engines/Veteran Rewards/RewardNoticeGump.cs +++ b/Projects/UOContent/Engines/Veteran Rewards/RewardNoticeGump.cs @@ -7,12 +7,12 @@ namespace Server.Engines.VeteranRewards { private readonly Mobile m_From; + public override bool Singleton => true; + public RewardNoticeGump(Mobile from) : base(0, 0) { m_From = from; - from.CloseGump(); - AddPage(0); AddBackground(10, 10, 500, 135, 2600); diff --git a/Projects/UOContent/Engines/Veteran Rewards/RewardOptionGump.cs b/Projects/UOContent/Engines/Veteran Rewards/RewardOptionGump.cs index cd474c56b..1b2b0bb7b 100644 --- a/Projects/UOContent/Engines/Veteran Rewards/RewardOptionGump.cs +++ b/Projects/UOContent/Engines/Veteran Rewards/RewardOptionGump.cs @@ -14,6 +14,8 @@ namespace Server.Gumps private readonly IRewardOption m_Option; private readonly RewardOptionList m_Options = new(); + public override bool Singleton => true; + public RewardOptionGump(IRewardOption option, int title = 0) : base(60, 36) { m_Option = option; diff --git a/Projects/UOContent/Engines/Veteran Rewards/RewardSystem.cs b/Projects/UOContent/Engines/Veteran Rewards/RewardSystem.cs index be9b74909..6d486f7fe 100644 --- a/Projects/UOContent/Engines/Veteran Rewards/RewardSystem.cs +++ b/Projects/UOContent/Engines/Veteran Rewards/RewardSystem.cs @@ -1,5 +1,6 @@ using System; using Server.Accounting; +using Server.Gumps; using Server.Items; using Server.Mobiles; diff --git a/Projects/UOContent/Engines/Virtues/Sacrifice.cs b/Projects/UOContent/Engines/Virtues/Sacrifice.cs index 8f31e9acc..0cf9d612f 100644 --- a/Projects/UOContent/Engines/Virtues/Sacrifice.cs +++ b/Projects/UOContent/Engines/Virtues/Sacrifice.cs @@ -74,7 +74,6 @@ public static class SacrificeVirtue * We need to wait for them to accept the gump or they can just use * Sacrifice and cancel to have items in their backpack for free. */ - from.CloseGump(); from.SendGump(new ResurrectGump(from, fromSacrifice: true)); } else diff --git a/Projects/UOContent/Engines/Virtues/VirtueGump.cs b/Projects/UOContent/Engines/Virtues/VirtueGump.cs index 4767447d7..7beb2f401 100644 --- a/Projects/UOContent/Engines/Virtues/VirtueGump.cs +++ b/Projects/UOContent/Engines/Virtues/VirtueGump.cs @@ -36,8 +36,7 @@ public class VirtueGump : Gump } else if (beholder.Map == beheld.Map && beholder.InRange(beheld, 12)) { - beholder.CloseGump(); - beholder.SendGump(new VirtueGump(beholder, beheld)); + beholder.SendGump(new VirtueGump(beholder, beheld), true); } } diff --git a/Projects/UOContent/Gumps/AdminGump.cs b/Projects/UOContent/Gumps/AdminGump.cs index 0d4b3fff4..17d1f693a 100644 --- a/Projects/UOContent/Gumps/AdminGump.cs +++ b/Projects/UOContent/Gumps/AdminGump.cs @@ -74,13 +74,13 @@ namespace Server.Gumps private readonly AdminGumpPage m_PageType; private readonly object m_State; + public override bool Singleton => true; + public AdminGump( Mobile from, AdminGumpPage pageType, int listPage = 0, List list = null, string notice = null, object state = null ) : base(50, 40) { - from.CloseGump(); - m_From = from; m_PageType = pageType; m_ListPage = listPage; diff --git a/Projects/Server/Gumps/BaseGump.cs b/Projects/UOContent/Gumps/Base/BaseGump.cs similarity index 82% rename from Projects/Server/Gumps/BaseGump.cs rename to Projects/UOContent/Gumps/Base/BaseGump.cs index 9b3fc5d65..a3b393b7a 100644 --- a/Projects/Server/Gumps/BaseGump.cs +++ b/Projects/UOContent/Gumps/Base/BaseGump.cs @@ -15,12 +15,14 @@ using Server.Network; using System; +using System.Buffers; using System.Runtime.CompilerServices; namespace Server.Gumps; public abstract class BaseGump { + private static readonly byte[] _packetBuffer = GC.AllocateUninitializedArray(0x10000); private static Serial nextSerial = (Serial)1; public int TypeID { get; protected set; } @@ -30,9 +32,13 @@ public abstract class BaseGump public abstract int TextEntries { get; } public int X { get; set; } - public int Y { get; set; } + /** + * If true, only one instance of this gump can be open at a time per player. + */ + public virtual bool Singleton => false; + public BaseGump(int x, int y) : this() { X = x; @@ -45,7 +51,17 @@ public abstract class BaseGump TypeID = GetTypeId(GetType()); } - public abstract void SendTo(NetState ns); + public virtual void SendTo(NetState ns) + { + var writer = new SpanWriter(_packetBuffer); + Compile(ref writer); + + ns.Send(writer.Span); + + writer.Dispose(); + } + + public abstract void Compile(ref SpanWriter writer); public virtual void OnResponse(NetState sender, in RelayInfo info) { diff --git a/Projects/Server/Gumps/DynamicGump.cs b/Projects/UOContent/Gumps/Base/DynamicGump.cs similarity index 84% rename from Projects/Server/Gumps/DynamicGump.cs rename to Projects/UOContent/Gumps/Base/DynamicGump.cs index ab45e949f..34f580050 100644 --- a/Projects/Server/Gumps/DynamicGump.cs +++ b/Projects/UOContent/Gumps/Base/DynamicGump.cs @@ -13,7 +13,6 @@ * along with this program. If not, see . * *************************************************************************/ -using System; using System.Buffers; using System.IO; using Server.Network; @@ -22,8 +21,6 @@ namespace Server.Gumps; public abstract class DynamicGump : BaseGump { - private static readonly byte[] _packetBuffer = GC.AllocateUninitializedArray(0x10000); - private int _switches; private int _textEntries; @@ -36,7 +33,7 @@ public abstract class DynamicGump : BaseGump protected abstract void BuildLayout(ref DynamicGumpBuilder builder); - public void CreatePacket(ref SpanWriter writer) + public override void Compile(ref SpanWriter writer) { writer.Write((byte)0xDD); // Packet ID writer.Seek(2, SeekOrigin.Current); @@ -62,16 +59,4 @@ public abstract class DynamicGump : BaseGump writer.WritePacketLength(); } - - public override void SendTo(NetState ns) - { - ns.AddGump(this); - - var writer = new SpanWriter(_packetBuffer); - CreatePacket(ref writer); - - ns.Send(writer.Span); - - writer.Dispose(); - } } diff --git a/Projects/Server/Gumps/DynamicGumpBuilder.cs b/Projects/UOContent/Gumps/Base/DynamicGumpBuilder.cs similarity index 100% rename from Projects/Server/Gumps/DynamicGumpBuilder.cs rename to Projects/UOContent/Gumps/Base/DynamicGumpBuilder.cs diff --git a/Projects/Server/Gumps/Grid/Grid.cs b/Projects/UOContent/Gumps/Base/Grid/Grid.cs similarity index 100% rename from Projects/Server/Gumps/Grid/Grid.cs rename to Projects/UOContent/Gumps/Base/Grid/Grid.cs diff --git a/Projects/Server/Gumps/Grid/GumpGrid.cs b/Projects/UOContent/Gumps/Base/Grid/GumpGrid.cs similarity index 100% rename from Projects/Server/Gumps/Grid/GumpGrid.cs rename to Projects/UOContent/Gumps/Base/Grid/GumpGrid.cs diff --git a/Projects/Server/Gumps/GumpFlags.cs b/Projects/UOContent/Gumps/Base/GumpFlags.cs similarity index 100% rename from Projects/Server/Gumps/GumpFlags.cs rename to Projects/UOContent/Gumps/Base/GumpFlags.cs diff --git a/Projects/Server/Gumps/GumpLayoutBuilder.cs b/Projects/UOContent/Gumps/Base/GumpLayoutBuilder.cs similarity index 100% rename from Projects/Server/Gumps/GumpLayoutBuilder.cs rename to Projects/UOContent/Gumps/Base/GumpLayoutBuilder.cs diff --git a/Projects/Server/Gumps/GumpStringsBuilder.cs b/Projects/UOContent/Gumps/Base/GumpStringsBuilder.cs similarity index 100% rename from Projects/Server/Gumps/GumpStringsBuilder.cs rename to Projects/UOContent/Gumps/Base/GumpStringsBuilder.cs diff --git a/Projects/UOContent/Gumps/Base/GumpSystem.IncomingPackets.cs b/Projects/UOContent/Gumps/Base/GumpSystem.IncomingPackets.cs new file mode 100644 index 000000000..ca4f5e968 --- /dev/null +++ b/Projects/UOContent/Gumps/Base/GumpSystem.IncomingPackets.cs @@ -0,0 +1,198 @@ +/************************************************************************* + * ModernUO * + * Copyright 2019-2023 - ModernUO Development Team * + * Email: hi@modernuo.com * + * File: IncomingGumpPackets.cs * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *************************************************************************/ + +using Server.Diagnostics; +using Server.Engines.Virtues; +using Server.Exceptions; +using Server.Mobiles; +using Server.Network; +using System; +using System.Buffers; +using System.Buffers.Binary; +using System.Diagnostics; +using System.IO; +using System.Runtime.InteropServices; + +namespace Server.Gumps; + +public static partial class GumpSystem +{ + public static void DisplayGumpResponse(NetState state, SpanReader reader) + { + var serial = (Serial)reader.ReadUInt32(); + var typeId = reader.ReadInt32(); + var buttonId = reader.ReadInt32(); + + BaseGump baseGump = null; + + foreach (var g in GetAll(state)) + { + if (g.Serial != serial || g.TypeID != typeId) + { + continue; + } + + baseGump = g; + break; + } + + if (baseGump != null) + { + if (baseGump is Gump gump) + { + var buttonExists = buttonId == 0; // 0 is always 'close' + + if (!buttonExists) + { + foreach (var e in gump.Entries) + { + if ((e as GumpButton)?.ButtonID == buttonId) + { + buttonExists = true; + break; + } + + if ((e as GumpImageTileButton)?.ButtonID == buttonId) + { + buttonExists = true; + break; + } + } + } + + if (!buttonExists) + { + state.LogInfo("Invalid gump response, disconnecting..."); + var exception = new InvalidGumpResponseException($"Button {buttonId} doesn't exist"); + exception.SetStackTrace(new StackTrace()); + NetState.TraceException(exception); + return; + } + } + + var switchCount = reader.ReadInt32(); + + if (switchCount < 0 || switchCount > baseGump.Switches) + { + state.LogInfo("Invalid gump response, disconnecting..."); + var exception = new InvalidGumpResponseException($"Bad switch count {switchCount}"); + exception.SetStackTrace(new StackTrace()); + NetState.TraceException(exception); + return; + } + + int switchByteCount = switchCount * 4; + + // Read all the integers + ReadOnlySpan switchBlock = + MemoryMarshal.Cast(reader.Buffer.Slice(reader.Position, switchByteCount)); + + reader.Seek(switchByteCount, SeekOrigin.Current); + + scoped ReadOnlySpan switches; + + // Swap the endianness if necessary + if (BitConverter.IsLittleEndian) + { + Span reversedSwitches = stackalloc int[switchCount]; + BinaryPrimitives.ReverseEndianness(switchBlock, reversedSwitches); + switches = reversedSwitches; + } + else + { + switches = switchBlock; + } + + var textCount = reader.ReadInt32(); + if (textCount < 0 || textCount > baseGump.TextEntries) + { + state.LogInfo("Invalid gump response, disconnecting..."); + var exception = new InvalidGumpResponseException($"Bad text entry count {textCount}"); + exception.SetStackTrace(new StackTrace()); + NetState.TraceException(exception); + return; + } + + Span textIds = stackalloc ushort[textCount]; + Span textFields = stackalloc Range[textCount]; + + var textOffset = reader.Position; + for (var i = 0; i < textCount; i++) + { + var textId = reader.ReadUInt16(); + var textLength = reader.ReadUInt16(); + + if (textLength > 239) + { + state.LogInfo("Invalid gump response, disconnecting..."); + var exception = new InvalidGumpResponseException($"Text entry {i} is too long ({textLength})"); + exception.SetStackTrace(new StackTrace()); + NetState.TraceException(exception); + return; + } + + textIds[i] = textId; + var offset = reader.Position - textOffset; + var length = textLength * 2; + textFields[i] = offset..(offset + length); + reader.Seek(length, SeekOrigin.Current); + } + + var textBlock = reader.Buffer.Slice(textOffset, reader.Position - textOffset); + + Remove(state, baseGump); + + var prof = GumpProfile.Acquire(baseGump.GetType()); + + prof?.Start(); + + var relayInfo = new RelayInfo( + buttonId, + switches, + textIds, + textFields, + textBlock + ); + baseGump.OnResponse(state, relayInfo); + + prof?.Finish(); + } + + if (typeId == 461) + { + // Virtue gump + var switchCount = reader.Remaining >= 4 ? reader.ReadInt32() : 0; + + if (buttonId == 1 && switchCount > 0) + { + var beheld = World.FindEntity((Serial)reader.ReadUInt32()); + + if (beheld != null) + { + VirtueGump.RequestVirtueGump((PlayerMobile)state.Mobile, beheld); + } + } + else + { + var beheld = World.FindMobile(serial); + + if (beheld != null) + { + VirtueGump.RequestVirtueItem((PlayerMobile)state.Mobile, beheld, buttonId); + } + } + } + } +} diff --git a/Projects/UOContent/Gumps/Base/GumpSystem.cs b/Projects/UOContent/Gumps/Base/GumpSystem.cs new file mode 100644 index 000000000..fa96b627d --- /dev/null +++ b/Projects/UOContent/Gumps/Base/GumpSystem.cs @@ -0,0 +1,289 @@ +/************************************************************************* + * ModernUO * + * Copyright 2019-2023 - ModernUO Development Team * + * Email: hi@modernuo.com * + * File: GumpSystem.cs * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *************************************************************************/ + +using Server.Gumps.Base; +using Server.Logging; +using Server.Network; +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace Server.Gumps; + +public static partial class GumpSystem +{ + private const int GumpCap = 512; + private const int InitialCapacity = 4; + + private static readonly Dictionary> _gumps = []; + private static readonly ILogger _logger = LogFactory.GetLogger(typeof(GumpSystem)); + + public static unsafe void Configure() + { + IncomingPackets.Register(0xB1, 0, true, &DisplayGumpResponse); + + EventSink.Disconnected += EventSink_Disconnected; + } + + private static void EventSink_Disconnected(Mobile m) + { + if (m.NetState != null && _gumps.Remove(m.NetState, out var gumps)) + { + gumps.Clear(); + } + } + + private static ReadOnlySpan GetAll(NetState ns) => + _gumps.TryGetValue(ns, out var gumps) ? CollectionsMarshal.AsSpan(gumps) : []; + + private static T Find(NetState ns) where T : BaseGump + { + if (ns == null || !_gumps.TryGetValue(ns, out var gumps)) + { + return null; + } + + var gumpsSpan = CollectionsMarshal.AsSpan(gumps); + for (int i = 0; i < gumpsSpan.Length; i++) + { + if (gumpsSpan[i] is T tGump) + { + return tGump; + } + } + + return null; + } + + private static void Add(NetState ns, BaseGump gump) + { + if (ns == null || gump == null) + { + return; + } + + if (!_gumps.TryGetValue(ns, out var gumps)) + { + gumps = new List(InitialCapacity); + _gumps.Add(ns, gumps); + } + + if (gumps.Count < GumpCap) + { + gumps.Add(gump); + } + else + { + _logger.Information("Exceeded gump cap, disconnecting..."); + ns.Disconnect("Exceeded gump cap."); + } + } + + private static void Remove(NetState ns, BaseGump gump) + { + if (_gumps.TryGetValue(ns, out var gumps)) + { + for (int i = 0; i < gumps.Count; i++) + { + if (gumps[i] == gump) + { + gumps.RemoveAt(i); + return; + } + } + } + } + + private static bool Remove(NetState ns, out T gump) where T : BaseGump + { + if (ns != null && _gumps.TryGetValue(ns, out var gumps)) + { + var gumpsSpan = CollectionsMarshal.AsSpan(gumps); + for (int i = 0; i < gumpsSpan.Length; i++) + { + if (gumpsSpan[i] is T tGump) + { + gumps.RemoveAt(i); + gump = tGump; + return true; + } + } + } + + gump = null; + return false; + } + + private static void Send(NetState ns, BaseGump gump, bool singleton) + { + if (ns.CannotSendPackets()) // Handles ns null check too + { + return; + } + + ref List list = ref CollectionsMarshal.GetValueRefOrAddDefault(_gumps, ns, out bool exists); + + if (exists) + { + bool replaced = false; + + if (singleton || gump.Singleton) + { + for (int i = 0; i < list.Count; i++) + { + BaseGump old = list[i]; + + if (old.TypeID == gump.TypeID) + { + ns.SendCloseGump(old.TypeID, 0); + old.OnServerClose(ns); + + list[i] = gump; + replaced = true; + break; + } + } + } + + if (!replaced) + { + list.Add(gump); + } + } + else + { + list = [gump]; + } + + gump.SendTo(ns); + } + + private static bool Close(NetState ns) where T : BaseGump + { + if (Remove(ns, out var gump)) + { + ns.SendCloseGump(gump.TypeID, 0); + gump.OnServerClose(ns); + return true; + } + + return false; + } + + private static readonly List _emptyList = []; + + private static NetStateGumps Get(NetState ns) + { + if (ns == null) + { + return new NetStateGumps(_emptyList, null); + } + + ref List list = ref CollectionsMarshal.GetValueRefOrAddDefault(_gumps, ns, out bool exists); + + if (!exists) + { + list = []; + } + + return new NetStateGumps(list, ns); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool HasGump([DisallowNull] this Mobile m) where T : BaseGump + { + ArgumentNullException.ThrowIfNull(m); + return Find(m.NetState) != null; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T FindGump([DisallowNull] this Mobile m) where T : BaseGump + { + ArgumentNullException.ThrowIfNull(m); + return Find(m.NetState); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool CloseGump([DisallowNull] this Mobile m) where T : BaseGump + { + ArgumentNullException.ThrowIfNull(m); + return Close(m.NetState); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void SendGump([DisallowNull] this Mobile m, BaseGump g, bool singleton = false) + { + ArgumentNullException.ThrowIfNull(m); + Send(m.NetState, g, singleton); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ReadOnlySpan GetAllGumps([DisallowNull] this Mobile m) + { + ArgumentNullException.ThrowIfNull(m); + return GetAll(m.NetState); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static NetStateGumps GetGumps([DisallowNull] this Mobile m) + { + ArgumentNullException.ThrowIfNull(m); + return Get(m.NetState); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool HasGump([DisallowNull] this NetState ns) where T : BaseGump + { + ArgumentNullException.ThrowIfNull(ns); + return Find(ns) != null; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void SendGump([DisallowNull] this NetState ns, BaseGump g, bool singleton = false) + { + ArgumentNullException.ThrowIfNull(ns); + Send(ns, g, singleton); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool CloseGump([DisallowNull] this NetState ns) where T : BaseGump + { + ArgumentNullException.ThrowIfNull(ns); + return Close(ns); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ReadOnlySpan GetAllGumps([DisallowNull] this NetState ns) + { + ArgumentNullException.ThrowIfNull(ns); + return GetAll(ns); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void AddGump([DisallowNull] this NetState ns, BaseGump gump) + { + ArgumentNullException.ThrowIfNull(ns); + Add(ns, gump); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static NetStateGumps GetGumps([DisallowNull] this NetState ns) + { + ArgumentNullException.ThrowIfNull(ns); + return Get(ns); + } +} diff --git a/Projects/Server/Gumps/InvalidGumpResponseException.cs b/Projects/UOContent/Gumps/Base/InvalidGumpResponseException.cs similarity index 100% rename from Projects/Server/Gumps/InvalidGumpResponseException.cs rename to Projects/UOContent/Gumps/Base/InvalidGumpResponseException.cs diff --git a/Projects/Server/Gumps/Legacy/Gump.cs b/Projects/UOContent/Gumps/Base/Legacy/Gump.cs similarity index 78% rename from Projects/Server/Gumps/Legacy/Gump.cs rename to Projects/UOContent/Gumps/Base/Legacy/Gump.cs index ac058dbf1..0bcd9dd3c 100644 --- a/Projects/Server/Gumps/Legacy/Gump.cs +++ b/Projects/UOContent/Gumps/Base/Legacy/Gump.cs @@ -13,13 +13,21 @@ * along with this program. If not, see . * *************************************************************************/ -using System.Collections.Generic; +using Server.Collections; using Server.Network; +using System; +using System.Buffers; +using System.Collections.Generic; +using System.IO; namespace Server.Gumps; public class Gump : BaseGump { + private static readonly byte[] _layoutBuffer = GC.AllocateUninitializedArray(0x20000); + private static readonly byte[] _stringsBuffer = GC.AllocateUninitializedArray(0x20000); + private static readonly OrderedSet _stringsList = new(); + private int _switches; private int _textEntries; @@ -240,10 +248,70 @@ public class Gump : BaseGump return Strings.Count - 1; } - public override void SendTo(NetState state) + public override void Compile(ref SpanWriter writer) { - state.AddGump(this); - state.SendDisplayGump(this, out _switches, out _textEntries); + _textEntries = 0; + _switches = 0; + + var layoutWriter = new SpanWriter(_layoutBuffer); + + if (!Draggable) + { + layoutWriter.Write("{ nomove }"u8); + } + + if (!Closable) + { + layoutWriter.Write("{ noclose }"u8); + } + + if (!Disposable) + { + layoutWriter.Write("{ nodispose }"u8); + } + + if (!Resizable) + { + layoutWriter.Write("{ noresize }"u8); + } + + foreach (var entry in Entries) + { + entry.AppendTo(ref layoutWriter, _stringsList, ref _textEntries, ref _switches); + } + + var stringsWriter = new SpanWriter(_stringsBuffer); + + foreach (var str in _stringsList) + { + var s = str ?? ""; + stringsWriter.Write((ushort)s.Length); + stringsWriter.WriteBigUni(s); + } + + writer.Write((byte)0xDD); // Packet ID + writer.Seek(2, SeekOrigin.Current); + + writer.Write(Serial); + writer.Write(TypeID); + writer.Write(X); + writer.Write(Y); + + layoutWriter.Write((byte)0); // Layout text terminator + OutgoingGumpPackets.WritePacked(layoutWriter.Span, ref writer); + + writer.Write(_stringsList.Count); + OutgoingGumpPackets.WritePacked(stringsWriter.Span, ref writer); + + writer.WritePacketLength(); + + layoutWriter.Dispose(); // Just in case + stringsWriter.Dispose(); // Just in case + + if (_stringsList.Count > 0) + { + _stringsList.Clear(); + } } protected void Reset() diff --git a/Projects/Server/Gumps/Legacy/GumpAlphaRegion.cs b/Projects/UOContent/Gumps/Base/Legacy/GumpAlphaRegion.cs similarity index 100% rename from Projects/Server/Gumps/Legacy/GumpAlphaRegion.cs rename to Projects/UOContent/Gumps/Base/Legacy/GumpAlphaRegion.cs diff --git a/Projects/Server/Gumps/Legacy/GumpBackground.cs b/Projects/UOContent/Gumps/Base/Legacy/GumpBackground.cs similarity index 100% rename from Projects/Server/Gumps/Legacy/GumpBackground.cs rename to Projects/UOContent/Gumps/Base/Legacy/GumpBackground.cs diff --git a/Projects/Server/Gumps/Legacy/GumpButton.cs b/Projects/UOContent/Gumps/Base/Legacy/GumpButton.cs similarity index 100% rename from Projects/Server/Gumps/Legacy/GumpButton.cs rename to Projects/UOContent/Gumps/Base/Legacy/GumpButton.cs diff --git a/Projects/Server/Gumps/Legacy/GumpCheck.cs b/Projects/UOContent/Gumps/Base/Legacy/GumpCheck.cs similarity index 100% rename from Projects/Server/Gumps/Legacy/GumpCheck.cs rename to Projects/UOContent/Gumps/Base/Legacy/GumpCheck.cs diff --git a/Projects/Server/Gumps/Legacy/GumpECHandleInput.cs b/Projects/UOContent/Gumps/Base/Legacy/GumpECHandleInput.cs similarity index 100% rename from Projects/Server/Gumps/Legacy/GumpECHandleInput.cs rename to Projects/UOContent/Gumps/Base/Legacy/GumpECHandleInput.cs diff --git a/Projects/Server/Gumps/Legacy/GumpEntry.cs b/Projects/UOContent/Gumps/Base/Legacy/GumpEntry.cs similarity index 100% rename from Projects/Server/Gumps/Legacy/GumpEntry.cs rename to Projects/UOContent/Gumps/Base/Legacy/GumpEntry.cs diff --git a/Projects/Server/Gumps/Legacy/GumpGroup.cs b/Projects/UOContent/Gumps/Base/Legacy/GumpGroup.cs similarity index 100% rename from Projects/Server/Gumps/Legacy/GumpGroup.cs rename to Projects/UOContent/Gumps/Base/Legacy/GumpGroup.cs diff --git a/Projects/Server/Gumps/Legacy/GumpHtml.cs b/Projects/UOContent/Gumps/Base/Legacy/GumpHtml.cs similarity index 100% rename from Projects/Server/Gumps/Legacy/GumpHtml.cs rename to Projects/UOContent/Gumps/Base/Legacy/GumpHtml.cs diff --git a/Projects/Server/Gumps/Legacy/GumpHtmlLocalized.cs b/Projects/UOContent/Gumps/Base/Legacy/GumpHtmlLocalized.cs similarity index 100% rename from Projects/Server/Gumps/Legacy/GumpHtmlLocalized.cs rename to Projects/UOContent/Gumps/Base/Legacy/GumpHtmlLocalized.cs diff --git a/Projects/Server/Gumps/Legacy/GumpImage.cs b/Projects/UOContent/Gumps/Base/Legacy/GumpImage.cs similarity index 100% rename from Projects/Server/Gumps/Legacy/GumpImage.cs rename to Projects/UOContent/Gumps/Base/Legacy/GumpImage.cs diff --git a/Projects/Server/Gumps/Legacy/GumpImageTileButton.cs b/Projects/UOContent/Gumps/Base/Legacy/GumpImageTileButton.cs similarity index 100% rename from Projects/Server/Gumps/Legacy/GumpImageTileButton.cs rename to Projects/UOContent/Gumps/Base/Legacy/GumpImageTileButton.cs diff --git a/Projects/Server/Gumps/Legacy/GumpImageTiled.cs b/Projects/UOContent/Gumps/Base/Legacy/GumpImageTiled.cs similarity index 100% rename from Projects/Server/Gumps/Legacy/GumpImageTiled.cs rename to Projects/UOContent/Gumps/Base/Legacy/GumpImageTiled.cs diff --git a/Projects/Server/Gumps/Legacy/GumpItem.cs b/Projects/UOContent/Gumps/Base/Legacy/GumpItem.cs similarity index 100% rename from Projects/Server/Gumps/Legacy/GumpItem.cs rename to Projects/UOContent/Gumps/Base/Legacy/GumpItem.cs diff --git a/Projects/Server/Gumps/Legacy/GumpItemProperty.cs b/Projects/UOContent/Gumps/Base/Legacy/GumpItemProperty.cs similarity index 100% rename from Projects/Server/Gumps/Legacy/GumpItemProperty.cs rename to Projects/UOContent/Gumps/Base/Legacy/GumpItemProperty.cs diff --git a/Projects/Server/Gumps/Legacy/GumpLabel.cs b/Projects/UOContent/Gumps/Base/Legacy/GumpLabel.cs similarity index 100% rename from Projects/Server/Gumps/Legacy/GumpLabel.cs rename to Projects/UOContent/Gumps/Base/Legacy/GumpLabel.cs diff --git a/Projects/Server/Gumps/Legacy/GumpLabelCropped.cs b/Projects/UOContent/Gumps/Base/Legacy/GumpLabelCropped.cs similarity index 100% rename from Projects/Server/Gumps/Legacy/GumpLabelCropped.cs rename to Projects/UOContent/Gumps/Base/Legacy/GumpLabelCropped.cs diff --git a/Projects/Server/Gumps/Legacy/GumpMasterGump.cs b/Projects/UOContent/Gumps/Base/Legacy/GumpMasterGump.cs similarity index 100% rename from Projects/Server/Gumps/Legacy/GumpMasterGump.cs rename to Projects/UOContent/Gumps/Base/Legacy/GumpMasterGump.cs diff --git a/Projects/Server/Gumps/Legacy/GumpPage.cs b/Projects/UOContent/Gumps/Base/Legacy/GumpPage.cs similarity index 100% rename from Projects/Server/Gumps/Legacy/GumpPage.cs rename to Projects/UOContent/Gumps/Base/Legacy/GumpPage.cs diff --git a/Projects/Server/Gumps/Legacy/GumpRadio.cs b/Projects/UOContent/Gumps/Base/Legacy/GumpRadio.cs similarity index 100% rename from Projects/Server/Gumps/Legacy/GumpRadio.cs rename to Projects/UOContent/Gumps/Base/Legacy/GumpRadio.cs diff --git a/Projects/Server/Gumps/Legacy/GumpSpriteImage.cs b/Projects/UOContent/Gumps/Base/Legacy/GumpSpriteImage.cs similarity index 100% rename from Projects/Server/Gumps/Legacy/GumpSpriteImage.cs rename to Projects/UOContent/Gumps/Base/Legacy/GumpSpriteImage.cs diff --git a/Projects/Server/Gumps/Legacy/GumpTextEntry.cs b/Projects/UOContent/Gumps/Base/Legacy/GumpTextEntry.cs similarity index 100% rename from Projects/Server/Gumps/Legacy/GumpTextEntry.cs rename to Projects/UOContent/Gumps/Base/Legacy/GumpTextEntry.cs diff --git a/Projects/Server/Gumps/Legacy/GumpTextEntryLimited.cs b/Projects/UOContent/Gumps/Base/Legacy/GumpTextEntryLimited.cs similarity index 100% rename from Projects/Server/Gumps/Legacy/GumpTextEntryLimited.cs rename to Projects/UOContent/Gumps/Base/Legacy/GumpTextEntryLimited.cs diff --git a/Projects/Server/Gumps/Legacy/GumpTooltip.cs b/Projects/UOContent/Gumps/Base/Legacy/GumpTooltip.cs similarity index 100% rename from Projects/Server/Gumps/Legacy/GumpTooltip.cs rename to Projects/UOContent/Gumps/Base/Legacy/GumpTooltip.cs diff --git a/Projects/UOContent/Gumps/Base/NetStateGumps.cs b/Projects/UOContent/Gumps/Base/NetStateGumps.cs new file mode 100644 index 000000000..626ee7fcd --- /dev/null +++ b/Projects/UOContent/Gumps/Base/NetStateGumps.cs @@ -0,0 +1,87 @@ +using Server.Network; +using System.Collections.Generic; + +namespace Server.Gumps.Base; + +public readonly ref struct NetStateGumps +{ + private readonly List _gumps; + private readonly NetState _state; + + public NetStateGumps(List gumps, NetState state) + { + _gumps = gumps; + _state = state; + } + + public bool Close() where T : BaseGump + { + if (_state == null || _gumps == null) + { + return false; + } + + for (int i = 0; i < _gumps.Count; i++) + { + if (_gumps[i] is T tGump) + { + _state.SendCloseGump(tGump.TypeID, 0); + tGump.OnServerClose(_state); + + _gumps.RemoveAt(i); + return true; + } + } + + return false; + } + + public T Find() where T : BaseGump + { + if (_state == null || _gumps == null) + { + return null; + } + + for (int i = 0; i < _gumps.Count; i++) + { + if (_gumps[i] is T tGump) + { + return tGump; + } + } + + return null; + } + + public bool Has() where T : BaseGump => Find() != null; + + public void Send(BaseGump gump, bool singleton = false) + { + if (_state.CannotSendPackets()) // Cannot send packets handles _state null check + { + return; + } + + if (singleton || gump.Singleton) + { + for (int i = 0; i < _gumps.Count; i++) + { + BaseGump old = _gumps[i]; + + if (old.TypeID == gump.TypeID) + { + _state.SendCloseGump(old.TypeID, 0); + old.OnServerClose(_state); + + _gumps[i] = gump; + gump.SendTo(_state); + return; + } + } + } + + _gumps.Add(gump); + gump.SendTo(_state); + } +} diff --git a/Projects/Server/Network/Packets/OutgoingGumpPackets.cs b/Projects/UOContent/Gumps/Base/OutgoingGumpPackets.cs similarity index 56% rename from Projects/Server/Network/Packets/OutgoingGumpPackets.cs rename to Projects/UOContent/Gumps/Base/OutgoingGumpPackets.cs index cc89cc94d..9657962dd 100644 --- a/Projects/Server/Network/Packets/OutgoingGumpPackets.cs +++ b/Projects/UOContent/Gumps/Base/OutgoingGumpPackets.cs @@ -2,7 +2,7 @@ * ModernUO * * Copyright 2019-2023 - ModernUO Development Team * * Email: hi@modernuo.com * - * File: OutgoingGumpPackets.cs * + * File: OutgoingGumpPackets.cs * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -13,42 +13,19 @@ * along with this program. If not, see . * *************************************************************************/ +using Server.Compression; +using Server.Logging; +using Server.Network; using System; using System.Buffers; using System.IO; using System.Runtime.CompilerServices; -using Server.Collections; -using Server.Compression; -using Server.Gumps; -using Server.Logging; -namespace Server.Network; +namespace Server.Gumps; public static class OutgoingGumpPackets { - private static readonly ILogger logger = LogFactory.GetLogger(typeof(OutgoingGumpPackets)); - - public static void SendCloseGump(this NetState ns, int typeId, int buttonId) - { - if (ns.CannotSendPackets()) - { - return; - } - - var writer = new SpanWriter(stackalloc byte[13]); - writer.Write((byte)0xBF); // Packet ID - writer.Write((ushort)13); - - writer.Write((short)0x04); - writer.Write(typeId); - writer.Write(buttonId); - - ns.Send(writer.Span); - } - - private static readonly byte[] _layoutBuffer = GC.AllocateUninitializedArray(0x20000); - private static readonly byte[] _stringsBuffer = GC.AllocateUninitializedArray(0x20000); - private static readonly OrderedSet _stringsList = new(); + private static readonly ILogger _logger = LogFactory.GetLogger(typeof(OutgoingGumpPackets)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void WritePacked(ReadOnlySpan span, ref SpanWriter writer) @@ -66,7 +43,7 @@ public static class OutgoingGumpPackets var bytesPacked = Deflate.Standard.Pack(dest, span); if (bytesPacked == 0) { - logger.Warning("Gump compression failed"); + _logger.Warning("Gump compression failed"); writer.Write(4); writer.Write(0); @@ -78,83 +55,6 @@ public static class OutgoingGumpPackets writer.Seek(bytesPacked, SeekOrigin.Current); } - public static void SendDisplayGump(this NetState ns, Gump gump, out int switches, out int entries) - { - switches = 0; - entries = 0; - - if (ns.CannotSendPackets()) - { - return; - } - - var layoutWriter = new SpanWriter(_layoutBuffer); - - if (!gump.Draggable) - { - layoutWriter.Write("{ nomove }"u8); - } - - if (!gump.Closable) - { - layoutWriter.Write("{ noclose }"u8); - } - - if (!gump.Disposable) - { - layoutWriter.Write("{ nodispose }"u8); - } - - if (!gump.Resizable) - { - layoutWriter.Write("{ noresize }"u8); - } - - foreach (var entry in gump.Entries) - { - entry.AppendTo(ref layoutWriter, _stringsList, ref entries, ref switches); - } - - var stringsWriter = new SpanWriter(_stringsBuffer); - - foreach (var str in _stringsList) - { - var s = str ?? ""; - stringsWriter.Write((ushort)s.Length); - stringsWriter.WriteBigUni(s); - } - - - var writer = new SpanWriter(0x10000); - writer.Write((byte)0xDD); // Packet ID - writer.Seek(2, SeekOrigin.Current); - - writer.Write(gump.Serial); - writer.Write(gump.TypeID); - writer.Write(gump.X); - writer.Write(gump.Y); - - layoutWriter.Write((byte)0); // Layout text terminator - WritePacked(layoutWriter.Span, ref writer); - - writer.Write(_stringsList.Count); - WritePacked(stringsWriter.Span, ref writer); - - writer.WritePacketLength(); - - ns.Send(writer.Span); - - layoutWriter.Dispose(); // Just in case - stringsWriter.Dispose(); // Just in case - - if (_stringsList.Count > 0) - { - _stringsList.Clear(); - } - - writer.Dispose(); - } - public static void SendDisplaySignGump(this NetState ns, Serial serial, int gumpId, string unknown, string caption) { if (ns.CannotSendPackets()) @@ -179,4 +79,22 @@ public static class OutgoingGumpPackets ns.Send(writer.Span); } + + public static void SendCloseGump(this NetState ns, int typeId, int buttonId) + { + if (ns.CannotSendPackets()) + { + return; + } + + var writer = new SpanWriter(stackalloc byte[13]); + writer.Write((byte)0xBF); // Packet ID + writer.Write((ushort)13); + + writer.Write((short)0x04); + writer.Write(typeId); + writer.Write(buttonId); + + ns.Send(writer.Span); + } } diff --git a/Projects/Server/Gumps/RelayInfo.cs b/Projects/UOContent/Gumps/Base/RelayInfo.cs similarity index 100% rename from Projects/Server/Gumps/RelayInfo.cs rename to Projects/UOContent/Gumps/Base/RelayInfo.cs diff --git a/Projects/Server/Gumps/StaticGump.cs b/Projects/UOContent/Gumps/Base/StaticGump.cs similarity index 94% rename from Projects/Server/Gumps/StaticGump.cs rename to Projects/UOContent/Gumps/Base/StaticGump.cs index ace9c55ff..c0f5eb920 100644 --- a/Projects/Server/Gumps/StaticGump.cs +++ b/Projects/UOContent/Gumps/Base/StaticGump.cs @@ -24,8 +24,6 @@ namespace Server.Gumps; public abstract class StaticGump : BaseGump where TSelf : StaticGump { - private static readonly byte[] _packetBuffer = GC.AllocateUninitializedArray(0x10000); - private static int _switches; private static int _textEntries; private static byte[] _compressedLayoutData; @@ -48,7 +46,18 @@ public abstract class StaticGump : BaseGump where TSelf : StaticGump(layoutLength); + writer.Span.Slice(layoutPos, layoutLength).CopyTo(_compressedLayoutData); + } + + public override void Compile(ref SpanWriter writer) { writer.Write((byte)0xDD); // Packet ID writer.Seek(2, SeekOrigin.Current); @@ -153,27 +162,4 @@ public abstract class StaticGump : BaseGump where TSelf : StaticGump(layoutLength); - writer.Span.Slice(layoutPos, layoutLength).CopyTo(_compressedLayoutData); - } - - public override void SendTo(NetState ns) - { - ns.AddGump(this); - - var writer = new SpanWriter(_packetBuffer); - CreatePacket(ref writer); - - ns.Send(writer.Span); - - writer.Dispose(); - } } diff --git a/Projects/Server/Gumps/StaticGumpBuilder.cs b/Projects/UOContent/Gumps/Base/StaticGumpBuilder.cs similarity index 100% rename from Projects/Server/Gumps/StaticGumpBuilder.cs rename to Projects/UOContent/Gumps/Base/StaticGumpBuilder.cs diff --git a/Projects/UOContent/Gumps/CommentsGump.cs b/Projects/UOContent/Gumps/CommentsGump.cs index 329ca2ca7..73fb4d44d 100644 --- a/Projects/UOContent/Gumps/CommentsGump.cs +++ b/Projects/UOContent/Gumps/CommentsGump.cs @@ -104,8 +104,7 @@ namespace Server.Gumps public override void OnCancel(Mobile from) { - from.CloseGump(); - from.SendGump(new CommentsGump(m_Acct)); + from.SendGump(new CommentsGump(m_Acct), true); base.OnCancel(from); } @@ -115,8 +114,7 @@ namespace Server.Gumps from.SendMessage("Comment added."); // m_Acct.AddComment( from.Name, text ); m_Acct.Comments.Add(new AccountComment(from.Name, text)); - from.CloseGump(); - from.SendGump(new CommentsGump(m_Acct)); + from.SendGump(new CommentsGump(m_Acct), true); } } } diff --git a/Projects/UOContent/Gumps/ConfirmHeritageGump.cs b/Projects/UOContent/Gumps/ConfirmHeritageGump.cs index 9aa8ff3ec..470168e56 100644 --- a/Projects/UOContent/Gumps/ConfirmHeritageGump.cs +++ b/Projects/UOContent/Gumps/ConfirmHeritageGump.cs @@ -9,6 +9,8 @@ namespace Server.Gumps private readonly Type[] m_Selected; private readonly HeritageToken m_Token; + public override bool Singleton => true; + public ConfirmHeritageGump(HeritageToken token, Type[] selected, int cliloc) : base(60, 36) { m_Token = token; diff --git a/Projects/UOContent/Gumps/ConfirmHouseResizeGump.cs b/Projects/UOContent/Gumps/ConfirmHouseResizeGump.cs index f06fd6995..d5b897da5 100644 --- a/Projects/UOContent/Gumps/ConfirmHouseResizeGump.cs +++ b/Projects/UOContent/Gumps/ConfirmHouseResizeGump.cs @@ -1,5 +1,4 @@ using Server.Guilds; -using Server.Items; using Server.Mobiles; using Server.Multis; using Server.Network; diff --git a/Projects/UOContent/Gumps/ConfirmReleaseGump.cs b/Projects/UOContent/Gumps/ConfirmReleaseGump.cs index 0afae0efe..1863881a1 100644 --- a/Projects/UOContent/Gumps/ConfirmReleaseGump.cs +++ b/Projects/UOContent/Gumps/ConfirmReleaseGump.cs @@ -8,6 +8,8 @@ public class ConfirmReleaseGump : StaticGump private readonly Mobile _from; private readonly BaseCreature _pet; + public override bool Singleton => true; + public ConfirmReleaseGump(Mobile from, BaseCreature pet) : base(50, 50) { _from = from; @@ -31,12 +33,6 @@ public class ConfirmReleaseGump : StaticGump builder.AddHtmlLocalized(170, 80, 75, 20, 1011012); // CANCEL } - public override void SendTo(NetState ns) - { - _from.CloseGump(); - base.SendTo(ns); - } - public override void OnResponse(NetState sender, in RelayInfo info) { if (info.ButtonID != 2 || _pet.Deleted || diff --git a/Projects/UOContent/Gumps/Go/GoGump.cs b/Projects/UOContent/Gumps/Go/GoGump.cs index 5f22c6dbd..cacc8619c 100644 --- a/Projects/UOContent/Gumps/Go/GoGump.cs +++ b/Projects/UOContent/Gumps/Go/GoGump.cs @@ -25,10 +25,10 @@ public class GoGump : Gump private readonly LocationTree _tree; + public override bool Singleton => true; + private GoGump(int page, Mobile from, LocationTree tree, GoCategory node) : base(50, 50) { - from.CloseGump(); - if (node == tree.Root) { tree.LastBranch.Remove(from); diff --git a/Projects/UOContent/Gumps/Guilds/GuildGump.cs b/Projects/UOContent/Gumps/Guilds/GuildGump.cs index fff700886..42e5bfa07 100644 --- a/Projects/UOContent/Gumps/Guilds/GuildGump.cs +++ b/Projects/UOContent/Gumps/Guilds/GuildGump.cs @@ -102,17 +102,19 @@ namespace Server.Gumps public static void EnsureClosed(Mobile m) { - m.CloseGump(); - m.CloseGump(); - m.CloseGump(); - m.CloseGump(); - m.CloseGump(); - m.CloseGump(); - m.CloseGump(); - m.CloseGump(); - m.CloseGump(); - m.CloseGump(); - m.CloseGump(); + var gumps = m.GetGumps(); + + gumps.Close(); + gumps.Close(); + gumps.Close(); + gumps.Close(); + gumps.Close(); + gumps.Close(); + gumps.Close(); + gumps.Close(); + gumps.Close(); + gumps.Close(); + gumps.Close(); } public static bool BadLeader(Mobile m, Guild g) diff --git a/Projects/UOContent/Gumps/Guilds/New Guild System/BaseGuildGump.cs b/Projects/UOContent/Gumps/Guilds/New Guild System/BaseGuildGump.cs index d863c8299..ee4c36dce 100644 --- a/Projects/UOContent/Gumps/Guilds/New Guild System/BaseGuildGump.cs +++ b/Projects/UOContent/Gumps/Guilds/New Guild System/BaseGuildGump.cs @@ -7,12 +7,12 @@ namespace Server.Guilds { public abstract class BaseGuildGump : Gump { + public override bool Singleton => true; + public BaseGuildGump(PlayerMobile pm, Guild g, int x = 10, int y = 10) : base(x, y) { guild = g; player = pm; - - pm.CloseGump(); } protected Guild guild { get; } diff --git a/Projects/UOContent/Gumps/Guilds/New Guild System/CreateGuildGump.cs b/Projects/UOContent/Gumps/Guilds/New Guild System/CreateGuildGump.cs index a24787e32..0029f8b93 100644 --- a/Projects/UOContent/Gumps/Guilds/New Guild System/CreateGuildGump.cs +++ b/Projects/UOContent/Gumps/Guilds/New Guild System/CreateGuildGump.cs @@ -6,9 +6,10 @@ namespace Server.Guilds { public class CreateGuildGump : Gump { + public override bool Singleton => true; + public CreateGuildGump(PlayerMobile pm, string guildName = "Guild Name", string guildAbbrev = "") : base(10, 10) { - pm.CloseGump(); pm.CloseGump(); AddPage(0); diff --git a/Projects/UOContent/Gumps/Guilds/New Guild System/GuildInfoGump.cs b/Projects/UOContent/Gumps/Guilds/New Guild System/GuildInfoGump.cs index cb8ab9f56..37d21beed 100644 --- a/Projects/UOContent/Gumps/Guilds/New Guild System/GuildInfoGump.cs +++ b/Projects/UOContent/Gumps/Guilds/New Guild System/GuildInfoGump.cs @@ -158,8 +158,7 @@ namespace Server.Guilds // Guild Faction if (Guild.OrderChaos && IsLeader(pm, guild)) { - pm.CloseGump(); - pm.SendGump(new GuildChangeTypeGump(pm, guild)); + pm.SendGump(new GuildChangeTypeGump(pm, guild), true); } break; diff --git a/Projects/UOContent/Gumps/HeritageTokenGump.cs b/Projects/UOContent/Gumps/HeritageTokenGump.cs index 98347828c..685959bf9 100644 --- a/Projects/UOContent/Gumps/HeritageTokenGump.cs +++ b/Projects/UOContent/Gumps/HeritageTokenGump.cs @@ -705,7 +705,6 @@ namespace Server.Gumps if (types?.Length > 0 && cliloc > 0) { - sender.Mobile.CloseGump(); sender.Mobile.SendGump(new ConfirmHeritageGump(m_Token, types, cliloc)); } else diff --git a/Projects/UOContent/Gumps/HouseDemolishGump.cs b/Projects/UOContent/Gumps/HouseDemolishGump.cs index f8278a0e4..ca77b4cfc 100644 --- a/Projects/UOContent/Gumps/HouseDemolishGump.cs +++ b/Projects/UOContent/Gumps/HouseDemolishGump.cs @@ -11,13 +11,13 @@ namespace Server.Gumps private readonly BaseHouse m_House; private readonly Mobile m_Mobile; + public override bool Singleton => true; + public HouseDemolishGump(Mobile mobile, BaseHouse house) : base(110, 100) { m_Mobile = mobile; m_House = house; - mobile.CloseGump(); - Closable = false; AddPage(0); diff --git a/Projects/UOContent/Gumps/HouseGump.cs b/Projects/UOContent/Gumps/HouseGump.cs index da4dcefa5..36dca7bd0 100644 --- a/Projects/UOContent/Gumps/HouseGump.cs +++ b/Projects/UOContent/Gumps/HouseGump.cs @@ -189,10 +189,12 @@ namespace Server.Gumps if (m_List.Count > 0) { - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); - from.SendGump(new HouseRemoveGump(m_Number, m_List, m_House, m_AccountOf)); + var gumps = from.GetGumps(); + + gumps.Close(); + gumps.Close(); + gumps.Close(); + gumps.Send(new HouseRemoveGump(m_Number, m_List, m_House, m_AccountOf)); return; } } @@ -206,6 +208,8 @@ namespace Server.Gumps { private readonly BaseHouse m_House; + public override bool Singleton => true; + public HouseGump(Mobile from, BaseHouse house) : base(20, 30) { if (house.Deleted) @@ -215,9 +219,10 @@ namespace Server.Gumps m_House = house; - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); + var gumps = from.GetGumps(); + + gumps.Close(); + gumps.Close(); var isCombatRestricted = house.IsCombatRestricted(from); @@ -453,6 +458,8 @@ namespace Server.Gumps return; } + var gumps = from.GetGumps(); + switch (info.ButtonID) { case 1: // Rename sign @@ -464,10 +471,10 @@ namespace Server.Gumps } case 2: // List of co-owners { - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); - from.SendGump(new HouseListGump(1011275, m_House.CoOwners, m_House, false)); + gumps.Close(); + gumps.Close(); + gumps.Close(); + gumps.Send(new HouseListGump(1011275, m_House.CoOwners, m_House, false)); break; } @@ -491,10 +498,10 @@ namespace Server.Gumps { if (isOwner) { - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); - from.SendGump(new HouseRemoveGump(1011274, m_House.CoOwners, m_House, false)); + gumps.Close(); + gumps.Close(); + gumps.Close(); + gumps.Send(new HouseRemoveGump(1011274, m_House.CoOwners, m_House, false)); } else { @@ -520,10 +527,10 @@ namespace Server.Gumps } case 6: // List friends { - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); - from.SendGump(new HouseListGump(1011273, m_House.Friends, m_House, false)); + gumps.Close(); + gumps.Close(); + gumps.Close(); + gumps.Send(new HouseListGump(1011273, m_House.Friends, m_House, false)); break; } @@ -547,10 +554,10 @@ namespace Server.Gumps { if (isCoOwner) { - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); - from.SendGump(new HouseRemoveGump(1011272, m_House.Friends, m_House, false)); + gumps.Close(); + gumps.Close(); + gumps.Close(); + gumps.Send(new HouseRemoveGump(1011272, m_House.Friends, m_House, false)); } else { @@ -590,19 +597,19 @@ namespace Server.Gumps } case 12: // List bans { - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); - from.SendGump(new HouseListGump(1011271, m_House.Bans, m_House, true)); + gumps.Close(); + gumps.Close(); + gumps.Close(); + gumps.Send(new HouseListGump(1011271, m_House.Bans, m_House, true)); break; } case 13: // Remove ban { - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); - from.SendGump(new HouseRemoveGump(1011269, m_House.Bans, m_House, true)); + gumps.Close(); + gumps.Close(); + gumps.Close(); + gumps.Send(new HouseRemoveGump(1011269, m_House.Bans, m_House, true)); break; } @@ -630,8 +637,7 @@ namespace Server.Gumps } else { - from.CloseGump(); - from.SendGump(new HouseDemolishGump(from, m_House)); + gumps.Send(new HouseDemolishGump(from, m_House)); } } else diff --git a/Projects/UOContent/Gumps/HouseGumpAOS.cs b/Projects/UOContent/Gumps/HouseGumpAOS.cs index 44fd2706f..3fae4590f 100644 --- a/Projects/UOContent/Gumps/HouseGumpAOS.cs +++ b/Projects/UOContent/Gumps/HouseGumpAOS.cs @@ -73,15 +73,13 @@ namespace Server.Gumps private List m_List; + public override bool Singleton => true; + public HouseGumpAOS(HouseGumpPageAOS page, Mobile from, BaseHouse house) : base(50, 40) { m_House = house; m_Page = page; - from.CloseGump(); - // from.CloseGump( typeof( HouseListGump ) ); - // from.CloseGump( typeof( HouseRemoveGump ) ); - var isCombatRestricted = house.IsCombatRestricted(from); var isOwner = house.IsOwner(from); @@ -1427,8 +1425,7 @@ namespace Server.Gumps } else { - from.CloseGump(); - from.SendGump(new HouseDemolishGump(from, m_House)); + from.SendGump(new HouseDemolishGump(from, m_House), true); } } diff --git a/Projects/UOContent/Gumps/HouseTransferGump.cs b/Projects/UOContent/Gumps/HouseTransferGump.cs index 25a69423e..e999d6519 100644 --- a/Projects/UOContent/Gumps/HouseTransferGump.cs +++ b/Projects/UOContent/Gumps/HouseTransferGump.cs @@ -9,6 +9,8 @@ namespace Server.Gumps private readonly BaseHouse m_House; private readonly Mobile m_To; + public override bool Singleton => true; + public HouseTransferGump(Mobile from, Mobile to, BaseHouse house) : base(110, 100) { m_From = from; diff --git a/Projects/UOContent/Gumps/PetResurrectGump.cs b/Projects/UOContent/Gumps/PetResurrectGump.cs index 592f52d3b..c2c28ded4 100644 --- a/Projects/UOContent/Gumps/PetResurrectGump.cs +++ b/Projects/UOContent/Gumps/PetResurrectGump.cs @@ -8,10 +8,10 @@ public class PetResurrectGump : StaticGump private readonly double _hitsScalar; private readonly BaseCreature _pet; + public override bool Singleton => true; + public PetResurrectGump(Mobile from, BaseCreature pet, double hitsScalar = 0.0) : base(50, 50) { - from.CloseGump(); - _pet = pet; _hitsScalar = hitsScalar; } diff --git a/Projects/UOContent/Gumps/PlayerVendorGumps.cs b/Projects/UOContent/Gumps/PlayerVendorGumps.cs index 0d8b1355c..df081ab12 100644 --- a/Projects/UOContent/Gumps/PlayerVendorGumps.cs +++ b/Projects/UOContent/Gumps/PlayerVendorGumps.cs @@ -12,6 +12,8 @@ namespace Server.Gumps private readonly PlayerVendor m_Vendor; private readonly VendorItem m_VI; + public override bool Singleton => true; + public PlayerVendorBuyGump(PlayerVendor vendor, VendorItem vi) : base(100, 200) { m_Vendor = vendor; @@ -497,13 +499,13 @@ namespace Server.Gumps private readonly Mobile m_Vendor; + public override bool Singleton => true; + public PlayerVendorCustomizeGump(Mobile v, Mobile from) : base(30, 40) { m_Vendor = v; int x, y; - from.CloseGump(); - AddPage(0); AddBackground(0, 0, 585, 393, 5054); AddBackground(195, 36, 387, 275, 3000); diff --git a/Projects/UOContent/Gumps/PricedResurrectGump.cs b/Projects/UOContent/Gumps/PricedResurrectGump.cs index 8151f4c2a..205e9a12a 100644 --- a/Projects/UOContent/Gumps/PricedResurrectGump.cs +++ b/Projects/UOContent/Gumps/PricedResurrectGump.cs @@ -14,6 +14,9 @@ public class PricedResurrectGump : StaticGump { _healer = healer; _price = price; + + // Close this gump when + TypeID = GetTypeId(typeof(ResurrectGump)); } protected override void BuildLayout(ref StaticGumpBuilder builder) diff --git a/Projects/UOContent/Gumps/ReclaimVendorGump.cs b/Projects/UOContent/Gumps/ReclaimVendorGump.cs index 48f7b1d77..927dd1b70 100644 --- a/Projects/UOContent/Gumps/ReclaimVendorGump.cs +++ b/Projects/UOContent/Gumps/ReclaimVendorGump.cs @@ -10,6 +10,8 @@ namespace Server.Gumps private readonly BaseHouse m_House; private readonly List m_Vendors; + public override bool Singleton => true; + public ReclaimVendorGump(BaseHouse house) : base(50, 50) { m_House = house; diff --git a/Projects/UOContent/Gumps/ResurrectGump.cs b/Projects/UOContent/Gumps/ResurrectGump.cs index cd3f51f7a..cb3e16e3a 100644 --- a/Projects/UOContent/Gumps/ResurrectGump.cs +++ b/Projects/UOContent/Gumps/ResurrectGump.cs @@ -23,6 +23,8 @@ public class ResurrectGump : DynamicGump private readonly double _hitsScalar; private readonly ResurrectMessage _resurrectMessage; + public override bool Singleton => true; + public static void TryGiveStatLoss(PlayerMobile player) { if (Core.AOS || player.ShortTermMurders < ShortMurdersForStatLoss) diff --git a/Projects/UOContent/Gumps/RunebookGump.cs b/Projects/UOContent/Gumps/RunebookGump.cs index d7d2c0dbb..58d771635 100644 --- a/Projects/UOContent/Gumps/RunebookGump.cs +++ b/Projects/UOContent/Gumps/RunebookGump.cs @@ -15,6 +15,8 @@ public class RunebookGump : DynamicGump private readonly Runebook _book; public Runebook Book => _book; + public override bool Singleton => true; + public RunebookGump(Runebook book) : base(150, 200) => _book = book; protected override void BuildLayout(ref DynamicGumpBuilder builder) diff --git a/Projects/UOContent/Gumps/SetSecureLevelGump.cs b/Projects/UOContent/Gumps/SetSecureLevelGump.cs index 3bc9b8a9e..5e0970d02 100644 --- a/Projects/UOContent/Gumps/SetSecureLevelGump.cs +++ b/Projects/UOContent/Gumps/SetSecureLevelGump.cs @@ -13,6 +13,8 @@ namespace Server.Gumps { private readonly ISecurable m_Info; + public override bool Singleton => true; + public SetSecureLevelGump(Mobile owner, ISecurable info, BaseHouse house) : base(50, 50) { m_Info = info; diff --git a/Projects/UOContent/Gumps/ToTAdminGump.cs b/Projects/UOContent/Gumps/ToTAdminGump.cs index 538b83845..10ea5b6b0 100644 --- a/Projects/UOContent/Gumps/ToTAdminGump.cs +++ b/Projects/UOContent/Gumps/ToTAdminGump.cs @@ -31,6 +31,8 @@ namespace Server.Gumps private readonly int m_ToTEras; + public override bool Singleton => true; + public ToTAdminGump() : base(30, 50) { Closable = true; @@ -123,11 +125,7 @@ namespace Server.Gumps [Usage("ToTAdmin"), Description("Displays a menu to configure Treasures of Tokuno.")] public static void ToTAdmin_OnCommand(CommandEventArgs e) { - ToTAdminGump tg; - - tg = new ToTAdminGump(); - e.Mobile.CloseGump(); - e.Mobile.SendGump(tg); + e.Mobile.SendGump(new ToTAdminGump()); } } } diff --git a/Projects/UOContent/Gumps/VendorInventoryGump.cs b/Projects/UOContent/Gumps/VendorInventoryGump.cs index 586280175..a8fb83a22 100644 --- a/Projects/UOContent/Gumps/VendorInventoryGump.cs +++ b/Projects/UOContent/Gumps/VendorInventoryGump.cs @@ -11,6 +11,8 @@ namespace Server.Gumps private readonly BaseHouse m_House; private readonly List m_Inventories; + public override bool Singleton => true; + public VendorInventoryGump(BaseHouse house, Mobile from) : base(50, 50) { m_House = house; diff --git a/Projects/UOContent/Gumps/VendorRentalGumps.cs b/Projects/UOContent/Gumps/VendorRentalGumps.cs index 9abac4117..589cdb60c 100644 --- a/Projects/UOContent/Gumps/VendorRentalGumps.cs +++ b/Projects/UOContent/Gumps/VendorRentalGumps.cs @@ -606,6 +606,8 @@ namespace Server.Gumps private readonly int m_RefundAmount; private readonly RentedVendor m_Vendor; + public override bool Singleton => true; + public VendorRentalRefundGump(RentedVendor vendor, Mobile landlord, int refundAmount) : base(50, 50) { m_Vendor = vendor; diff --git a/Projects/UOContent/Gumps/ViewHousesGump.cs b/Projects/UOContent/Gumps/ViewHousesGump.cs index d6ba01ec1..3a32b69ed 100644 --- a/Projects/UOContent/Gumps/ViewHousesGump.cs +++ b/Projects/UOContent/Gumps/ViewHousesGump.cs @@ -16,14 +16,14 @@ namespace Server.Gumps private readonly List m_List; private readonly BaseHouse m_Selection; + public override bool Singleton => true; + public ViewHousesGump(Mobile from, List list, BaseHouse sel) : base(50, 40) { m_From = from; m_List = list; m_Selection = sel; - from.CloseGump(); - AddPage(0); AddBackground(0, 0, 240, 360, 5054); diff --git a/Projects/UOContent/Gumps/VirtualCheckGump.cs b/Projects/UOContent/Gumps/VirtualCheckGump.cs new file mode 100644 index 000000000..11baa1896 --- /dev/null +++ b/Projects/UOContent/Gumps/VirtualCheckGump.cs @@ -0,0 +1,248 @@ +/************************************************************************* + * ModernUO * + * Copyright 2019-2024 - ModernUO Development Team * + * Email: hi@modernuo.com * + * File: VirtualCheckGump.cs * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *************************************************************************/ + +using Server.Items; +using Server.Network; + +namespace Server.Gumps; + +public sealed class VirtualCheckGump : Gump, IVirtualCheckGump +{ + public static unsafe void Configure() + { + VirtualCheck.GumpActivator = &Activator; + } + + private static VirtualCheckGump Activator(Mobile from, VirtualCheck check) => new(from, check); + + public enum Buttons + { + Close, + Clear, + Accept, + AllPlat, + AllGold + } + + private int _plat, _gold; + + public override bool Singleton => true; + + public VirtualCheckGump(Mobile user, VirtualCheck check) : base(50, 50) + { + User = user; + Check = check; + + _plat = Check.Plat; + _gold = Check.Gold; + + Closable = true; + Disposable = true; + Draggable = true; + Resizable = false; + + CompileLayout(); + } + + public Mobile User { get; } + public VirtualCheck Check { get; private set; } + + public override void OnServerClose(NetState owner) + { + base.OnServerClose(owner); + + if (Check?.Deleted == false) + { + Check.UpdateTrade(User); + } + } + + public void Close() + { + User.CloseGump(); + + if (Check?.Deleted == false) + { + Check.UpdateTrade(User); + } + else + { + Check = null; + } + } + + public void Send() + { + if (Check?.Deleted == false) + { + User.SendGump(this); + } + else + { + Close(); + } + } + + public void Refresh(bool recompile) + { + if (Check?.Deleted != false) + { + Close(); + return; + } + + if (recompile) + { + CompileLayout(); + } + + Close(); + Send(); + } + + private void CompileLayout() + { + if (Check?.Deleted != false) + { + return; + } + + Entries.ForEach(e => e.Parent = null); + Entries.Clear(); + + AddPage(0); + + AddBackground(0, 0, 400, 160, 3500); + + // Title + AddImageTiled(25, 35, 350, 3, 96); + AddImage(10, 8, 113); + AddImage(360, 8, 113); + + AddHtml(40, 15, 320, 20, $"BANK OF {User.RawName.ToUpper()}".Center(0x2F4F4F)); + + // Platinum Row + AddBackground(15, 60, 175, 20, 9300); + AddBackground(20, 45, 165, 30, 9350); + AddItem(20, 45, 3826); // Plat + AddLabel(60, 50, 0, User.Account.TotalPlat.ToString("#,0")); + + AddButton(195, 50, 95, 95, (int)Buttons.AllPlat); // -> + + AddBackground(210, 60, 175, 20, 9300); + AddBackground(215, 45, 165, 30, 9350); + AddTextEntry(225, 50, 145, 20, 0, 0, _plat.ToString(), User.Account.TotalPlat.ToString().Length); + + // Gold Row + AddBackground(15, 100, 175, 20, 9300); + AddBackground(20, 85, 165, 30, 9350); + AddItem(20, 85, 3823); // Gold + AddLabel(60, 90, 0, User.Account.TotalGold.ToString("#,0")); + + AddButton(195, 90, 95, 95, (int)Buttons.AllGold); // -> + + AddBackground(210, 100, 175, 20, 9300); + AddBackground(215, 85, 165, 30, 9350); + AddTextEntry(225, 90, 145, 20, 0, 1, _gold.ToString(), User.Account.TotalGold.ToString().Length); + + // Buttons + AddButton(20, 128, 12006, 12007, (int)Buttons.Close); + AddButton(215, 128, 12003, 12004, (int)Buttons.Clear); + AddButton(305, 128, 12000, 12002, (int)Buttons.Accept); + } + + public override void OnResponse(NetState sender, in RelayInfo info) + { + if (Check?.Deleted != false || sender.Mobile != User) + { + Close(); + return; + } + + var refresh = false; + var updated = false; + + switch ((Buttons)info.ButtonID) + { + case Buttons.Clear: + { + _plat = _gold = 0; + refresh = true; + break; + } + case Buttons.Accept: + { + var platText = info.GetTextEntry(0); + var goldText = info.GetTextEntry(1); + + if (!int.TryParse(platText, out _plat)) + { + User.SendMessage("That is not a valid amount of platinum."); + refresh = true; + } + else if (!int.TryParse(goldText, out _gold)) + { + User.SendMessage("That is not a valid amount of gold."); + refresh = true; + } + else + { + var totalPlat = User.Account.TotalPlat; + var totalGold = User.Account.TotalGold; + + if (totalPlat < _plat || totalGold < _gold) + { + _plat = User.Account.TotalPlat; + _gold = User.Account.TotalGold; + User.SendMessage("You do not have that much currency."); + refresh = true; + } + else + { + Check.Plat = _plat; + Check.Gold = _gold; + updated = true; + } + } + break; + } + case Buttons.AllPlat: + { + _plat = User.Account.TotalPlat; + refresh = true; + break; + } + case Buttons.AllGold: + { + _gold = User.Account.TotalGold; + refresh = true; + break; + } + } + + if (updated) + { + User.SendMessage("Your offer has been updated."); + } + + if (refresh && Check?.Deleted == false) + { + Refresh(true); + return; + } + + Close(); + } +} diff --git a/Projects/UOContent/Gumps/WhoGump.cs b/Projects/UOContent/Gumps/WhoGump.cs index 01c6d9859..e47802a71 100644 --- a/Projects/UOContent/Gumps/WhoGump.cs +++ b/Projects/UOContent/Gumps/WhoGump.cs @@ -25,6 +25,8 @@ public class WhoGump : DynamicGump private readonly List _mobiles; private readonly int _page; + public override bool Singleton => true; + public WhoGump(Mobile owner, string filter) : this(BuildList(owner, filter)) { } @@ -33,8 +35,6 @@ public class WhoGump : DynamicGump { _mobiles = list; _page = page; - - // Initialize(page); } public static void Configure() diff --git a/Projects/UOContent/Holiday Stuff/Christmas/2004/Mistletoe.cs b/Projects/UOContent/Holiday Stuff/Christmas/2004/Mistletoe.cs index 9748a61ef..f52e49dd7 100644 --- a/Projects/UOContent/Holiday Stuff/Christmas/2004/Mistletoe.cs +++ b/Projects/UOContent/Holiday Stuff/Christmas/2004/Mistletoe.cs @@ -104,7 +104,6 @@ public partial class MistletoeAddon : Item, IDyable, IAddon if (from.InRange(GetWorldLocation(), 3)) { - from.CloseGump(); from.SendGump(new MistletoeAddonGump(from, this)); } else @@ -118,6 +117,8 @@ public partial class MistletoeAddon : Item, IDyable, IAddon private readonly MistletoeAddon _addon; private readonly Mobile _from; + public override bool Singleton => true; + public MistletoeAddonGump(Mobile from, MistletoeAddon addon) : base(150, 50) { _from = from; diff --git a/Projects/UOContent/Holiday Stuff/Christmas/2010/Addons/FireFliesDeed.cs b/Projects/UOContent/Holiday Stuff/Christmas/2010/Addons/FireFliesDeed.cs index 643b31d4d..948e15196 100644 --- a/Projects/UOContent/Holiday Stuff/Christmas/2010/Addons/FireFliesDeed.cs +++ b/Projects/UOContent/Holiday Stuff/Christmas/2010/Addons/FireFliesDeed.cs @@ -46,7 +46,6 @@ public partial class Fireflies : Item, IAddon if (house?.IsOwner(from) == true) { - from.CloseGump(); // Do you wish to re-deed this decoration? from.SendGump(new RewardDemolitionGump(this, 1049783)); } @@ -86,7 +85,6 @@ public partial class FirefliesDeed : Item return; } - from.CloseGump(); from.SendGump(new FacingGump(this, from)); } @@ -95,6 +93,8 @@ public partial class FirefliesDeed : Item private readonly FirefliesDeed _deed; private readonly Mobile _placer; + public override bool Singleton => true; + public FacingGump(FirefliesDeed deed, Mobile player) : base(150, 50) { _deed = deed; diff --git a/Projects/UOContent/Items/Aquarium/Aquarium.cs b/Projects/UOContent/Items/Aquarium/Aquarium.cs index f124a354e..34990100a 100644 --- a/Projects/UOContent/Items/Aquarium/Aquarium.cs +++ b/Projects/UOContent/Items/Aquarium/Aquarium.cs @@ -4,6 +4,7 @@ using System.Runtime.CompilerServices; using ModernUO.Serialization; using Server.Collections; using Server.ContextMenus; +using Server.Gumps; using Server.Multis; using Server.Network; @@ -875,8 +876,7 @@ namespace Server.Items return; } - from.CloseGump(); - from.SendGump(new AquariumGump(this, HasAccess(from))); + from.SendGump(new AquariumGump(this, HasAccess(from)), true); from.PlaySound(0x5A4); } diff --git a/Projects/UOContent/Items/Construction/Ankhs.cs b/Projects/UOContent/Items/Construction/Ankhs.cs index de5fd58f8..985092f43 100644 --- a/Projects/UOContent/Items/Construction/Ankhs.cs +++ b/Projects/UOContent/Items/Construction/Ankhs.cs @@ -40,7 +40,6 @@ namespace Server.Items } else if (m.Map?.CanFit(m.Location, 16, false, false) == true) { - m.CloseGump(); m.SendGump(new ResurrectGump(m, ResurrectMessage.VirtueShrine)); } else diff --git a/Projects/UOContent/Items/Containers/TreasureMapChest.cs b/Projects/UOContent/Items/Containers/TreasureMapChest.cs index f230ee897..22c5101cf 100644 --- a/Projects/UOContent/Items/Containers/TreasureMapChest.cs +++ b/Projects/UOContent/Items/Containers/TreasureMapChest.cs @@ -433,7 +433,6 @@ public partial class TreasureMapChest : LockableContainer return; } - from.CloseGump(); from.SendGump(new RemoveGump(from, this)); } @@ -453,6 +452,8 @@ public partial class TreasureMapChest : LockableContainer private readonly TreasureMapChest _chest; private readonly Mobile _from; + public override bool Singleton => true; + public RemoveGump(Mobile from, TreasureMapChest chest) : base(15, 15) { _from = from; diff --git a/Projects/UOContent/Items/Deeds/HairRestylingDeed.cs b/Projects/UOContent/Items/Deeds/HairRestylingDeed.cs index 645ecb8fe..d9256bf8a 100644 --- a/Projects/UOContent/Items/Deeds/HairRestylingDeed.cs +++ b/Projects/UOContent/Items/Deeds/HairRestylingDeed.cs @@ -84,13 +84,13 @@ public partial class HairRestylingDeed : Item private readonly HairRestylingDeed m_Deed; private readonly Mobile m_From; + public override bool Singleton => true; + public InternalGump(Mobile from, HairRestylingDeed deed) : base(50, 50) { m_From = from; m_Deed = deed; - from.CloseGump(); - AddBackground(100, 10, 400, 385, 0xA28); AddHtmlLocalized(100, 25, 400, 35, 1013008); diff --git a/Projects/UOContent/Items/Deeds/HolidayTreeDeed.cs b/Projects/UOContent/Items/Deeds/HolidayTreeDeed.cs index 275cf0c0f..dcb8585e1 100644 --- a/Projects/UOContent/Items/Deeds/HolidayTreeDeed.cs +++ b/Projects/UOContent/Items/Deeds/HolidayTreeDeed.cs @@ -103,7 +103,6 @@ public partial class HolidayTreeDeed : Item public override void OnDoubleClick(Mobile from) { - from.CloseGump(); from.SendGump(new HolidayTreeChoiceGump(from, this)); } } @@ -113,6 +112,8 @@ public class HolidayTreeChoiceGump : Gump private readonly HolidayTreeDeed m_Deed; private readonly Mobile m_From; + public override bool Singleton => true; + public HolidayTreeChoiceGump(Mobile from, HolidayTreeDeed deed) : base(200, 200) { m_From = from; diff --git a/Projects/UOContent/Items/Deeds/NameChangeDeed.cs b/Projects/UOContent/Items/Deeds/NameChangeDeed.cs index 181b9479c..b21320604 100644 --- a/Projects/UOContent/Items/Deeds/NameChangeDeed.cs +++ b/Projects/UOContent/Items/Deeds/NameChangeDeed.cs @@ -17,7 +17,6 @@ public partial class NameChangeDeed : Item { if (RootParent == from) { - from.CloseGump(); from.SendGump(new NameChangeDeedGump(this)); } else @@ -31,6 +30,8 @@ public class NameChangeDeedGump : Gump { private readonly Item m_Sender; + public override bool Singleton => true; + public NameChangeDeedGump(Item sender) : base(50, 50) { m_Sender = sender; diff --git a/Projects/UOContent/Items/Deeds/VendorRentalContract.cs b/Projects/UOContent/Items/Deeds/VendorRentalContract.cs index a99bd3173..f2f7898c8 100644 --- a/Projects/UOContent/Items/Deeds/VendorRentalContract.cs +++ b/Projects/UOContent/Items/Deeds/VendorRentalContract.cs @@ -195,8 +195,7 @@ public partial class VendorRentalContract : Item { if (from.InRange(this, 5)) { - from.CloseGump(); - from.SendGump(new VendorRentalContractGump(this, from)); + from.SendGump(new VendorRentalContractGump(this, from), true); } else { @@ -232,8 +231,7 @@ public partial class VendorRentalContract : Item { if (target is VendorRentalContract contract && contract.IsUsableBy(from, true, true, true, true)) { - from.CloseGump(); - from.SendGump(new VendorRentalContractGump(contract, from)); + from.SendGump(new VendorRentalContractGump(contract, from), true); } } } diff --git a/Projects/UOContent/Items/Misc/HairDye.cs b/Projects/UOContent/Items/Misc/HairDye.cs index 6eb0c0495..a66bcde2e 100644 --- a/Projects/UOContent/Items/Misc/HairDye.cs +++ b/Projects/UOContent/Items/Misc/HairDye.cs @@ -17,7 +17,6 @@ public partial class HairDye : Item { if (from.InRange(GetWorldLocation(), 1)) { - from.CloseGump(); from.SendGump(new HairDyeGump(this)); } else @@ -47,6 +46,8 @@ public class HairDyeGump : Gump private HairDye _hairDye; + public override bool Singleton => true; + public HairDyeGump(HairDye dye) : base(50, 50) { _hairDye = dye; diff --git a/Projects/UOContent/Items/Misc/PlayerBulletinBoards.cs b/Projects/UOContent/Items/Misc/PlayerBulletinBoards.cs index 24a17d289..1a0c3d3bc 100644 --- a/Projects/UOContent/Items/Misc/PlayerBulletinBoards.cs +++ b/Projects/UOContent/Items/Misc/PlayerBulletinBoards.cs @@ -290,10 +290,10 @@ public class PlayerBBGump : Gump private BaseHouse _house; private int _page; + public override bool Singleton => true; + public PlayerBBGump(Mobile from, BaseHouse house, BasePlayerBB board, int page) : base(50, 10) { - from.CloseGump(); - _page = page; _from = from; _house = house; diff --git a/Projects/UOContent/Items/Misc/PromotionalToken.cs b/Projects/UOContent/Items/Misc/PromotionalToken.cs index 3714b8a62..90547b8e0 100644 --- a/Projects/UOContent/Items/Misc/PromotionalToken.cs +++ b/Projects/UOContent/Items/Misc/PromotionalToken.cs @@ -46,7 +46,6 @@ public abstract partial class PromotionalToken : Item } else { - from.CloseGump(); from.SendGump(new PromotionalTokenGump(this)); } } @@ -71,6 +70,8 @@ public abstract partial class PromotionalToken : Item { private readonly PromotionalToken m_Token; + public override bool Singleton => true; + public PromotionalTokenGump(PromotionalToken token) : base(10, 10) { m_Token = token; diff --git a/Projects/UOContent/Items/Misc/PublicMoongate.cs b/Projects/UOContent/Items/Misc/PublicMoongate.cs index 522bf892b..8355d71e8 100644 --- a/Projects/UOContent/Items/Misc/PublicMoongate.cs +++ b/Projects/UOContent/Items/Misc/PublicMoongate.cs @@ -84,7 +84,6 @@ public partial class PublicMoongate : Item return false; } - m.CloseGump(); m.SendGump(new MoongateGump(m, this)); if (!m.Hidden || m.AccessLevel == AccessLevel.Player) @@ -323,6 +322,8 @@ public class MoongateGump : Gump private Mobile _mobile; private Item _moongate; + public override bool Singleton => true; + public MoongateGump(Mobile mobile, Item moongate) : base(100, 100) { _mobile = mobile; diff --git a/Projects/UOContent/Items/Misc/SpecialBeardDye.cs b/Projects/UOContent/Items/Misc/SpecialBeardDye.cs index 3626e0009..6fba86026 100644 --- a/Projects/UOContent/Items/Misc/SpecialBeardDye.cs +++ b/Projects/UOContent/Items/Misc/SpecialBeardDye.cs @@ -21,7 +21,6 @@ public partial class SpecialBeardDye : Item { if (from.InRange(GetWorldLocation(), 1)) { - from.CloseGump(); from.SendGump(new SpecialBeardDyeGump(this)); } else @@ -47,6 +46,8 @@ public class SpecialBeardDyeGump : Gump private SpecialBeardDye _specialBeardDye; + public override bool Singleton => true; + public SpecialBeardDyeGump(SpecialBeardDye dye) : base(0, 0) { _specialBeardDye = dye; diff --git a/Projects/UOContent/Items/Misc/SpecialHairDye.cs b/Projects/UOContent/Items/Misc/SpecialHairDye.cs index 504a21fa1..09a8289b6 100644 --- a/Projects/UOContent/Items/Misc/SpecialHairDye.cs +++ b/Projects/UOContent/Items/Misc/SpecialHairDye.cs @@ -21,7 +21,6 @@ public partial class SpecialHairDye : Item { if (from.InRange(GetWorldLocation(), 1)) { - from.CloseGump(); from.SendGump(new SpecialHairDyeGump(this)); } else @@ -47,6 +46,8 @@ public class SpecialHairDyeGump : Gump private SpecialHairDye _specialHairDye; + public override bool Singleton => true; + public SpecialHairDyeGump(SpecialHairDye dye) : base(0, 0) { _specialHairDye = dye; diff --git a/Projects/UOContent/Items/Misc/WindChimes.cs b/Projects/UOContent/Items/Misc/WindChimes.cs index 022f6516e..dd3b1f9b4 100644 --- a/Projects/UOContent/Items/Misc/WindChimes.cs +++ b/Projects/UOContent/Items/Misc/WindChimes.cs @@ -1,4 +1,5 @@ using ModernUO.Serialization; +using Server.Gumps; using Server.Multis; namespace Server.Items; diff --git a/Projects/UOContent/Items/Skill Items/Magical/Misc/Moongate.cs b/Projects/UOContent/Items/Skill Items/Magical/Misc/Moongate.cs index a0dcd7760..b6b9a01c8 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Misc/Moongate.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Misc/Moongate.cs @@ -157,7 +157,6 @@ public partial class Moongate : Item from.SendSound(0x20E, from); } - from.CloseGump(); from.SendGump(new MoongateConfirmGump(from, this)); } else @@ -265,7 +264,6 @@ public partial class ConfirmationMoongate : Moongate { if (GumpWidth > 0 && GumpHeight > 0 && TitleNumber > 0 && Message?.IsEmpty == false) { - from.CloseGump(); from.SendGump( new WarningGump( TitleNumber, @@ -275,7 +273,8 @@ public partial class ConfirmationMoongate : Moongate GumpWidth, GumpHeight, okay => Warning_Callback(from, okay) - ) + ), + true ); } else @@ -307,6 +306,8 @@ public class MoongateConfirmGump : Gump private Mobile _from; private Moongate _gate; + public override bool Singleton => true; + public MoongateConfirmGump(Mobile from, Moongate gate) : base(Core.AOS ? 110 : 20, Core.AOS ? 100 : 30) { _from = from; diff --git a/Projects/UOContent/Items/Skill Items/Magical/Runebook.cs b/Projects/UOContent/Items/Skill Items/Magical/Runebook.cs index 40954b4e3..f8274acfa 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Runebook.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Runebook.cs @@ -170,25 +170,7 @@ public partial class Runebook : Item, ISecurable, ICraftable from.SendLocalizedMessage(502421); // You have removed the rune. } - public bool IsOpen(Mobile toCheck) - { - var ns = toCheck.NetState; - - if (ns == null) - { - return false; - } - - foreach (var gump in ns.Gumps) - { - if ((gump as RunebookGump)?.Book == this) - { - return true; - } - } - - return false; - } + public bool IsOpen(Mobile toCheck) => toCheck.FindGump()?.Book == this; public override void GetProperties(IPropertyList list) { @@ -268,9 +250,7 @@ public partial class Runebook : Item, ISecurable, ICraftable public void SendGumpTo(Mobile from) { - from.CloseGump(); - from.SendGump(new RunebookGump(this)); - + from.SendGump(new RunebookGump(this), true); Openers.Add(from); } diff --git a/Projects/UOContent/Items/Skill Items/Misc/Bandage.cs b/Projects/UOContent/Items/Skill Items/Misc/Bandage.cs index 0c0d4cf03..68f9b3580 100644 --- a/Projects/UOContent/Items/Skill Items/Misc/Bandage.cs +++ b/Projects/UOContent/Items/Skill Items/Misc/Bandage.cs @@ -277,7 +277,6 @@ public class BandageContext : Timer { healerNumber = 503255; // You are able to resurrect the creature. - master.CloseGump(); master.SendGump(new PetResurrectGump(Healer, petPatient)); } else @@ -294,7 +293,6 @@ public class BandageContext : Timer { healerNumber = 503255; // You are able to resurrect the creature. - friend.CloseGump(); friend.SendGump(new PetResurrectGump(Healer, petPatient)); found = true; @@ -310,7 +308,6 @@ public class BandageContext : Timer } else { - Patient.CloseGump(); Patient.SendGump(new ResurrectGump(Healer)); } } diff --git a/Projects/UOContent/Items/Skill Items/Tailor Items/Misc/Dyes.cs b/Projects/UOContent/Items/Skill Items/Tailor Items/Misc/Dyes.cs index 107331e7d..54fe45c94 100644 --- a/Projects/UOContent/Items/Skill Items/Tailor Items/Misc/Dyes.cs +++ b/Projects/UOContent/Items/Skill Items/Tailor Items/Misc/Dyes.cs @@ -1,4 +1,5 @@ using ModernUO.Serialization; +using Server.Gumps; using Server.HuePickers; using Server.Targeting; diff --git a/Projects/UOContent/Items/Skill Items/Thief/DisguiseKit.cs b/Projects/UOContent/Items/Skill Items/Thief/DisguiseKit.cs index bbd6c5c1c..1422cc6aa 100644 --- a/Projects/UOContent/Items/Skill Items/Thief/DisguiseKit.cs +++ b/Projects/UOContent/Items/Skill Items/Thief/DisguiseKit.cs @@ -102,14 +102,14 @@ public class DisguiseGump : Gump private readonly DisguiseKit m_Kit; private readonly bool m_Used; + public override bool Singleton => true; + public DisguiseGump(Mobile from, DisguiseKit kit, bool startAtHair, bool used) : base(50, 50) { m_From = from; m_Kit = kit; m_Used = used; - from.CloseGump(); - AddPage(0); AddBackground(100, 10, 400, 385, 2600); diff --git a/Projects/UOContent/Items/Skill Items/Tools/BaseTool.cs b/Projects/UOContent/Items/Skill Items/Tools/BaseTool.cs index 66340c7c2..4697c5379 100644 --- a/Projects/UOContent/Items/Skill Items/Tools/BaseTool.cs +++ b/Projects/UOContent/Items/Skill Items/Tools/BaseTool.cs @@ -1,6 +1,7 @@ using System; using ModernUO.Serialization; using Server.Engines.Craft; +using Server.Gumps; using Server.Network; namespace Server.Items; diff --git a/Projects/UOContent/Items/Special/8th Anniversary Items/Dawn's Music Box/DawnsMusicBox.cs b/Projects/UOContent/Items/Special/8th Anniversary Items/Dawn's Music Box/DawnsMusicBox.cs index d84724425..f20097f7a 100644 --- a/Projects/UOContent/Items/Special/8th Anniversary Items/Dawn's Music Box/DawnsMusicBox.cs +++ b/Projects/UOContent/Items/Special/8th Anniversary Items/Dawn's Music Box/DawnsMusicBox.cs @@ -212,7 +212,6 @@ public partial class DawnsMusicBox : Item, ISecurable } else { - from.CloseGump(); from.SendGump(new DawnsMusicBoxGump(this)); } } diff --git a/Projects/UOContent/Items/Special/8th Anniversary Items/Dawn's Music Box/DawnsMusicBoxGump.cs b/Projects/UOContent/Items/Special/8th Anniversary Items/Dawn's Music Box/DawnsMusicBoxGump.cs index 8ff4e32ed..3f737b595 100644 --- a/Projects/UOContent/Items/Special/8th Anniversary Items/Dawn's Music Box/DawnsMusicBoxGump.cs +++ b/Projects/UOContent/Items/Special/8th Anniversary Items/Dawn's Music Box/DawnsMusicBoxGump.cs @@ -1,4 +1,4 @@ -using Server.Items; +using Server.Items; using Server.Network; namespace Server.Gumps; @@ -7,6 +7,8 @@ public class DawnsMusicBoxGump : Gump { private readonly DawnsMusicBox m_Box; + public override bool Singleton => true; + public DawnsMusicBoxGump(DawnsMusicBox box) : base(60, 36) { m_Box = box; diff --git a/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenBed.cs b/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenBed.cs index caa193d53..d1b002002 100644 --- a/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenBed.cs +++ b/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenBed.cs @@ -45,7 +45,6 @@ public partial class BrokenBedDeed : BaseAddonDeed { if (IsChildOf(from.Backpack)) { - from.CloseGump(); from.SendGump(new InternalGump(this)); } else @@ -63,6 +62,8 @@ public partial class BrokenBedDeed : BaseAddonDeed { private readonly BrokenBedDeed _deed; + public override bool Singleton => true; + public InternalGump(BrokenBedDeed deed) : base(60, 36) { _deed = deed; diff --git a/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenVanity.cs b/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenVanity.cs index 6b1569612..06c0afa27 100644 --- a/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenVanity.cs +++ b/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenVanity.cs @@ -40,7 +40,6 @@ public partial class BrokenVanityDeed : BaseAddonDeed { if (IsChildOf(from.Backpack)) { - from.CloseGump(); from.SendGump(new InternalGump(this)); } else @@ -58,6 +57,8 @@ public partial class BrokenVanityDeed : BaseAddonDeed { private readonly BrokenVanityDeed _deed; + public override bool Singleton => true; + public InternalGump(BrokenVanityDeed deed) : base(60, 63) { _deed = deed; diff --git a/Projects/UOContent/Items/Special/Gifts/HearthOfHomeFire.cs b/Projects/UOContent/Items/Special/Gifts/HearthOfHomeFire.cs index df017f360..a2c64d180 100644 --- a/Projects/UOContent/Items/Special/Gifts/HearthOfHomeFire.cs +++ b/Projects/UOContent/Items/Special/Gifts/HearthOfHomeFire.cs @@ -47,7 +47,6 @@ public partial class HearthOfHomeFireDeed : BaseAddonDeed { if (IsChildOf(from.Backpack)) { - from.CloseGump(); from.SendGump(new InternalGump(this)); } else @@ -65,6 +64,8 @@ public partial class HearthOfHomeFireDeed : BaseAddonDeed { private readonly HearthOfHomeFireDeed _deed; + public override bool Singleton => true; + public InternalGump(HearthOfHomeFireDeed deed) : base(150, 50) { _deed = deed; diff --git a/Projects/UOContent/Items/Special/Gifts/TapestryOfSosaria.cs b/Projects/UOContent/Items/Special/Gifts/TapestryOfSosaria.cs index b834cfa80..9a04138bf 100644 --- a/Projects/UOContent/Items/Special/Gifts/TapestryOfSosaria.cs +++ b/Projects/UOContent/Items/Special/Gifts/TapestryOfSosaria.cs @@ -35,7 +35,6 @@ public partial class TapestryOfSosaria : Item, ISecurable { if (from.InRange(GetWorldLocation(), 2)) { - from.CloseGump(); from.SendGump(new InternalGump()); } else @@ -51,6 +50,8 @@ public partial class TapestryOfSosaria : Item, ISecurable private class InternalGump : Gump { + public override bool Singleton => true; + public InternalGump() : base(50, 50) { AddImage(0, 0, 0x2C95); diff --git a/Projects/UOContent/Items/Special/Heritage Items/Curtains.cs b/Projects/UOContent/Items/Special/Heritage Items/Curtains.cs index bc464d42c..60f6cb16d 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/Curtains.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/Curtains.cs @@ -92,7 +92,6 @@ public partial class CurtainsDeed : BaseAddonDeed { if (IsChildOf(from.Backpack)) { - from.CloseGump(); from.SendGump(new InternalGump(this)); } else @@ -110,6 +109,8 @@ public partial class CurtainsDeed : BaseAddonDeed { private readonly CurtainsDeed _deed; + public override bool Singleton => true; + public InternalGump(CurtainsDeed deed) : base(60, 36) { _deed = deed; diff --git a/Projects/UOContent/Items/Special/Heritage Items/HangingAxes.cs b/Projects/UOContent/Items/Special/Heritage Items/HangingAxes.cs index e09de11ac..ce82e6ec2 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/HangingAxes.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/HangingAxes.cs @@ -40,7 +40,6 @@ public partial class HangingAxesDeed : BaseAddonDeed { if (IsChildOf(from.Backpack)) { - from.CloseGump(); from.SendGump(new InternalGump(this)); } else @@ -58,6 +57,8 @@ public partial class HangingAxesDeed : BaseAddonDeed { private readonly HangingAxesDeed m_Deed; + public override bool Singleton => true; + public InternalGump(HangingAxesDeed deed) : base(60, 36) { m_Deed = deed; diff --git a/Projects/UOContent/Items/Special/Heritage Items/HangingSwords.cs b/Projects/UOContent/Items/Special/Heritage Items/HangingSwords.cs index 1e3591f92..3d23fc936 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/HangingSwords.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/HangingSwords.cs @@ -40,7 +40,6 @@ public partial class HangingSwordsDeed : BaseAddonDeed { if (IsChildOf(from.Backpack)) { - from.CloseGump(); from.SendGump(new InternalGump(this)); } else @@ -58,6 +57,8 @@ public partial class HangingSwordsDeed : BaseAddonDeed { private readonly HangingSwordsDeed m_Deed; + public override bool Singleton => true; + public InternalGump(HangingSwordsDeed deed) : base(60, 36) { m_Deed = deed; diff --git a/Projects/UOContent/Items/Special/Heritage Items/HouseLadder.cs b/Projects/UOContent/Items/Special/Heritage Items/HouseLadder.cs index e12d2b01c..f1a36692e 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/HouseLadder.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/HouseLadder.cs @@ -81,7 +81,6 @@ public partial class HouseLadderDeed : BaseAddonDeed { if (IsChildOf(from.Backpack)) { - from.CloseGump(); from.SendGump(new InternalGump(this)); } else @@ -99,6 +98,8 @@ public partial class HouseLadderDeed : BaseAddonDeed { private readonly HouseLadderDeed _deed; + public override bool Singleton => true; + public InternalGump(HouseLadderDeed deed) : base(60, 36) { _deed = deed; diff --git a/Projects/UOContent/Items/Special/Heritage Items/Statue.cs b/Projects/UOContent/Items/Special/Heritage Items/Statue.cs index b9100904f..a07b7980f 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/Statue.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/Statue.cs @@ -42,7 +42,6 @@ public partial class StoneStatueDeed : BaseAddonDeed { if (IsChildOf(from.Backpack)) { - from.CloseGump(); from.SendGump(new InternalGump(this)); } else @@ -60,6 +59,8 @@ public partial class StoneStatueDeed : BaseAddonDeed { private readonly StoneStatueDeed _deed; + public override bool Singleton => true; + public InternalGump(StoneStatueDeed deed) : base(60, 36) { _deed = deed; diff --git a/Projects/UOContent/Items/Special/Heritage Items/UnmadeBed.cs b/Projects/UOContent/Items/Special/Heritage Items/UnmadeBed.cs index 1fc22bae7..ca28c4312 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/UnmadeBed.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/UnmadeBed.cs @@ -44,7 +44,6 @@ public partial class UnmadeBedDeed : BaseAddonDeed { if (IsChildOf(from.Backpack)) { - from.CloseGump(); from.SendGump(new InternalGump(this)); } else @@ -62,6 +61,8 @@ public partial class UnmadeBedDeed : BaseAddonDeed { private readonly UnmadeBedDeed _deed; + public override bool Singleton => true; + public InternalGump(UnmadeBedDeed deed) : base(60, 36) { _deed = deed; diff --git a/Projects/UOContent/Items/Special/Heritage Items/Vanity.cs b/Projects/UOContent/Items/Special/Heritage Items/Vanity.cs index bb7151360..6dfcc3fff 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/Vanity.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/Vanity.cs @@ -41,7 +41,6 @@ public partial class VanityDeed : BaseAddonContainerDeed { if (IsChildOf(from.Backpack)) { - from.CloseGump(); from.SendGump(new InternalGump(this)); } else @@ -59,6 +58,8 @@ public partial class VanityDeed : BaseAddonContainerDeed { private readonly VanityDeed _deed; + public override bool Singleton => true; + public InternalGump(VanityDeed deed) : base(60, 36) { _deed = deed; diff --git a/Projects/UOContent/Items/Special/Heritage Items/WoodenCoffin.cs b/Projects/UOContent/Items/Special/Heritage Items/WoodenCoffin.cs index 1f3c5560a..b6cf3be6b 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/WoodenCoffin.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/WoodenCoffin.cs @@ -52,7 +52,6 @@ public partial class WoodenCoffinDeed : BaseAddonDeed { if (IsChildOf(from.Backpack)) { - from.CloseGump(); from.SendGump(new InternalGump(this)); } else @@ -70,6 +69,8 @@ public partial class WoodenCoffinDeed : BaseAddonDeed { private readonly WoodenCoffinDeed _deed; + public override bool Singleton => true; + public InternalGump(WoodenCoffinDeed deed) : base(60, 36) { _deed = deed; diff --git a/Projects/UOContent/Items/Special/HeritageToken.cs b/Projects/UOContent/Items/Special/HeritageToken.cs index b5dccc340..eb5aae65a 100644 --- a/Projects/UOContent/Items/Special/HeritageToken.cs +++ b/Projects/UOContent/Items/Special/HeritageToken.cs @@ -1,4 +1,4 @@ -using ModernUO.Serialization; +using ModernUO.Serialization; using Server.Gumps; namespace Server.Items; @@ -19,8 +19,7 @@ public partial class HeritageToken : Item { if (IsChildOf(from.Backpack)) { - from.CloseGump(); - from.SendGump(new HeritageTokenGump(this)); + from.SendGump(new HeritageTokenGump(this), true); } else { diff --git a/Projects/UOContent/Items/Special/Holiday/HolidayPottedPlant.cs b/Projects/UOContent/Items/Special/Holiday/HolidayPottedPlant.cs index 7179aab90..475c56491 100644 --- a/Projects/UOContent/Items/Special/Holiday/HolidayPottedPlant.cs +++ b/Projects/UOContent/Items/Special/Holiday/HolidayPottedPlant.cs @@ -33,7 +33,6 @@ public partial class PottedPlantDeed : Item { if (IsChildOf(from.Backpack)) { - from.CloseGump(); from.SendGump(new InternalGump(this)); } else @@ -46,6 +45,8 @@ public partial class PottedPlantDeed : Item { private readonly PottedPlantDeed _deed; + public override bool Singleton => true; + public InternalGump(PottedPlantDeed deed) : base(100, 200) { _deed = deed; diff --git a/Projects/UOContent/Items/Special/Holiday/SnowStatue.cs b/Projects/UOContent/Items/Special/Holiday/SnowStatue.cs index 07f25da96..5ae65c20a 100644 --- a/Projects/UOContent/Items/Special/Holiday/SnowStatue.cs +++ b/Projects/UOContent/Items/Special/Holiday/SnowStatue.cs @@ -65,7 +65,6 @@ public partial class SnowStatueDeed : Item { if (IsChildOf(from.Backpack)) { - from.CloseGump(); from.SendGump(new InternalGump(from, this)); } else @@ -78,6 +77,8 @@ public partial class SnowStatueDeed : Item { private readonly SnowStatueDeed _deed; + public override bool Singleton => true; + public InternalGump(Mobile from, SnowStatueDeed deed) : base(100, 200) { _deed = deed; diff --git a/Projects/UOContent/Items/Special/Holiday/Wreath.cs b/Projects/UOContent/Items/Special/Holiday/Wreath.cs index dbf198e21..f5de38f7c 100644 --- a/Projects/UOContent/Items/Special/Holiday/Wreath.cs +++ b/Projects/UOContent/Items/Special/Holiday/Wreath.cs @@ -96,7 +96,6 @@ public partial class WreathAddon : Item, IDyable, IAddon { if (from.InRange(GetWorldLocation(), 3)) { - from.CloseGump(); from.SendGump(new WreathAddonGump(from, this)); } else @@ -111,6 +110,8 @@ public partial class WreathAddon : Item, IDyable, IAddon private readonly WreathAddon _addon; private readonly Mobile _from; + public override bool Singleton => true; + public WreathAddonGump(Mobile from, WreathAddon addon) : base(150, 50) { _from = from; diff --git a/Projects/UOContent/Items/Special/House Raffle/HouseRaffleDeed.cs b/Projects/UOContent/Items/Special/House Raffle/HouseRaffleDeed.cs index a6823090d..0d7f1f9bf 100644 --- a/Projects/UOContent/Items/Special/House Raffle/HouseRaffleDeed.cs +++ b/Projects/UOContent/Items/Special/House Raffle/HouseRaffleDeed.cs @@ -84,7 +84,6 @@ public partial class HouseRaffleDeed : Item if (IsChildOf(from.Backpack)) { - from.CloseGump(); from.SendGump(new WritOfLeaseGump(this)); } else @@ -95,6 +94,8 @@ public partial class HouseRaffleDeed : Item private class WritOfLeaseGump : Gump { + public override bool Singleton => true; + public WritOfLeaseGump(HouseRaffleDeed deed) : base(150, 50) { AddPage(0); diff --git a/Projects/UOContent/Items/Special/MonsterStatuette.cs b/Projects/UOContent/Items/Special/MonsterStatuette.cs index 2f7dd6752..8d49dd0e4 100644 --- a/Projects/UOContent/Items/Special/MonsterStatuette.cs +++ b/Projects/UOContent/Items/Special/MonsterStatuette.cs @@ -1,5 +1,6 @@ using ModernUO.Serialization; using Server.Engines.VeteranRewards; +using Server.Gumps; using Server.Multis; namespace Server.Items; diff --git a/Projects/UOContent/Items/Special/SoulStone.cs b/Projects/UOContent/Items/Special/SoulStone.cs index 0ce4e592d..8cb6aa19c 100644 --- a/Projects/UOContent/Items/Special/SoulStone.cs +++ b/Projects/UOContent/Items/Special/SoulStone.cs @@ -226,19 +226,21 @@ public partial class SoulStone : Item, ISecurable return; } - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); + var gumps = from.GetGumps(); + + gumps.Close(); + gumps.Close(); + gumps.Close(); + gumps.Close(); + gumps.Close(); if (IsEmpty) { - from.SendGump(new SelectSkillGump(this, from)); + gumps.Send(new SelectSkillGump(this, from)); } else { - from.SendGump(new ConfirmTransferGump(this, from)); + gumps.Send(new ConfirmTransferGump(this, from)); } } diff --git a/Projects/UOContent/Items/Special/Special Scrolls/SpecialScroll.cs b/Projects/UOContent/Items/Special/Special Scrolls/SpecialScroll.cs index 94be83389..3bb4ca068 100644 --- a/Projects/UOContent/Items/Special/Special Scrolls/SpecialScroll.cs +++ b/Projects/UOContent/Items/Special/Special Scrolls/SpecialScroll.cs @@ -72,7 +72,6 @@ public abstract partial class SpecialScroll : Item return; } - from.CloseGump(); from.SendGump(new InternalGump(from, this)); } @@ -81,6 +80,8 @@ public abstract partial class SpecialScroll : Item private readonly Mobile _mobile; private readonly SpecialScroll _scroll; + public override bool Singleton => true; + public InternalGump(Mobile mobile, SpecialScroll scroll) : base(25, 50) { _mobile = mobile; diff --git a/Projects/UOContent/Items/Special/Veteran Rewards/AnkhOfSacrifice.cs b/Projects/UOContent/Items/Special/Veteran Rewards/AnkhOfSacrifice.cs index fad9d5eb9..49950b13c 100644 --- a/Projects/UOContent/Items/Special/Veteran Rewards/AnkhOfSacrifice.cs +++ b/Projects/UOContent/Items/Special/Veteran Rewards/AnkhOfSacrifice.cs @@ -61,7 +61,6 @@ public partial class AnkhOfSacrificeComponent : AddonComponent } else { - m.CloseGump(); m.SendGump(new AnkhResurrectGump(m, ResurrectMessage.VirtueShrine)); } } @@ -215,7 +214,6 @@ public partial class AnkhOfSacrificeDeed : BaseAddonDeed, IRewardItem, IRewardOp if (IsChildOf(from.Backpack)) { - from.CloseGump(); from.SendGump(new RewardOptionGump(this)); } else diff --git a/Projects/UOContent/Items/Special/Veteran Rewards/Banner.cs b/Projects/UOContent/Items/Special/Veteran Rewards/Banner.cs index b2ea44b17..823ce8604 100644 --- a/Projects/UOContent/Items/Special/Veteran Rewards/Banner.cs +++ b/Projects/UOContent/Items/Special/Veteran Rewards/Banner.cs @@ -77,7 +77,6 @@ public partial class Banner : Item, IAddon, IDyable, IRewardItem if (house?.IsOwner(from) == true) { - from.CloseGump(); from.SendGump(new RewardDemolitionGump(this, 1018318)); // Do you wish to re-deed this banner? } else @@ -133,7 +132,6 @@ public partial class BannerDeed : Item, IRewardItem if (house?.IsOwner(from) == true) { - from.CloseGump(); from.SendGump(new InternalGump(this)); } else @@ -154,6 +152,8 @@ public partial class BannerDeed : Item, IRewardItem private readonly BannerDeed _banner; + public override bool Singleton => true; + public InternalGump(BannerDeed banner) : base(100, 200) { _banner = banner; @@ -274,7 +274,6 @@ public partial class BannerDeed : Item, IRewardItem if (north && west) { - from.CloseGump(); from.SendGump(new FacingGump(_banner, _itemID, p3d, house)); } else if (north || west) @@ -301,6 +300,8 @@ public partial class BannerDeed : Item, IRewardItem private readonly int m_ItemID; private readonly Point3D m_Location; + public override bool Singleton => true; + public FacingGump(BannerDeed banner, int itemID, Point3D location, BaseHouse house) : base(150, 50) { m_Banner = banner; diff --git a/Projects/UOContent/Items/Special/Veteran Rewards/Brazier.cs b/Projects/UOContent/Items/Special/Veteran Rewards/Brazier.cs index 7075cc8a4..437a8de63 100644 --- a/Projects/UOContent/Items/Special/Veteran Rewards/Brazier.cs +++ b/Projects/UOContent/Items/Special/Veteran Rewards/Brazier.cs @@ -136,7 +136,6 @@ public partial class RewardBrazierDeed : Item, IRewardItem return; } - from.CloseGump(); from.SendGump(new InternalGump(this)); } @@ -154,6 +153,8 @@ public partial class RewardBrazierDeed : Item, IRewardItem { private readonly RewardBrazierDeed _brazier; + public override bool Singleton => true; + public InternalGump(RewardBrazierDeed brazier) : base(100, 200) { _brazier = brazier; diff --git a/Projects/UOContent/Items/Special/Veteran Rewards/Cannon.cs b/Projects/UOContent/Items/Special/Veteran Rewards/Cannon.cs index aae6d1b47..9d7c7d691 100644 --- a/Projects/UOContent/Items/Special/Veteran Rewards/Cannon.cs +++ b/Projects/UOContent/Items/Special/Veteran Rewards/Cannon.cs @@ -420,7 +420,6 @@ public partial class CannonDeed : BaseAddonDeed, IRewardItem, IRewardOption if (IsChildOf(from.Backpack)) { - from.CloseGump(); from.SendGump(new RewardOptionGump(this)); } else diff --git a/Projects/UOContent/Items/Special/Veteran Rewards/DecorativeShield.cs b/Projects/UOContent/Items/Special/Veteran Rewards/DecorativeShield.cs index 95fb35205..26838a7ee 100644 --- a/Projects/UOContent/Items/Special/Veteran Rewards/DecorativeShield.cs +++ b/Projects/UOContent/Items/Special/Veteran Rewards/DecorativeShield.cs @@ -61,7 +61,6 @@ public partial class DecorativeShield : Item, IAddon, IRewardItem if (house?.IsOwner(from) == true) { - from.CloseGump(); from.SendGump(new RewardDemolitionGump(this, 1049783)); // Do you wish to re-deed this decoration? } else @@ -113,7 +112,6 @@ public partial class DecorativeShieldDeed : Item, IRewardItem if (IsChildOf(from.Backpack)) { - from.CloseGump(); from.SendGump(new InternalGump(this)); } else @@ -141,6 +139,8 @@ public partial class DecorativeShieldDeed : Item, IRewardItem private readonly DecorativeShieldDeed _shield; + public override bool Singleton => true; + public InternalGump(DecorativeShieldDeed shield) : base(150, 50) { _shield = shield; @@ -267,7 +267,6 @@ public partial class DecorativeShieldDeed : Item, IRewardItem if (north && west) { - from.CloseGump(); from.SendGump(new FacingGump(_shield, _itemID, p3d, house)); } else if (north || west) @@ -294,6 +293,8 @@ public partial class DecorativeShieldDeed : Item, IRewardItem private readonly Point3D _location; private readonly DecorativeShieldDeed _shield; + public override bool Singleton => true; + public FacingGump(DecorativeShieldDeed shield, int itemID, Point3D location, BaseHouse house) : base(150, 50) { _shield = shield; diff --git a/Projects/UOContent/Items/Special/Veteran Rewards/FlamingHead.cs b/Projects/UOContent/Items/Special/Veteran Rewards/FlamingHead.cs index bdeb95b8c..198628300 100644 --- a/Projects/UOContent/Items/Special/Veteran Rewards/FlamingHead.cs +++ b/Projects/UOContent/Items/Special/Veteran Rewards/FlamingHead.cs @@ -75,7 +75,6 @@ public partial class FlamingHead : StoneFaceTrapNoDamage, IAddon, IRewardItem if (house?.IsOwner(from) == true) { - from.CloseGump(); from.SendGump(new RewardDemolitionGump(this, 1018329)); // Do you wish to re-deed this skull? } else diff --git a/Projects/UOContent/Items/Special/Veteran Rewards/HangingSkeleton.cs b/Projects/UOContent/Items/Special/Veteran Rewards/HangingSkeleton.cs index 0fb1edb2d..728a35d7d 100644 --- a/Projects/UOContent/Items/Special/Veteran Rewards/HangingSkeleton.cs +++ b/Projects/UOContent/Items/Special/Veteran Rewards/HangingSkeleton.cs @@ -65,7 +65,6 @@ public partial class HangingSkeleton : Item, IAddon, IRewardItem if (house?.IsOwner(from) == true) { - from.CloseGump(); from.SendGump(new RewardDemolitionGump(this, 1049783)); // Do you wish to re-deed this decoration? } else @@ -129,7 +128,6 @@ public partial class HangingSkeletonDeed : Item, IRewardItem return; } - from.CloseGump(); from.SendGump(new InternalGump(this)); } @@ -147,6 +145,8 @@ public partial class HangingSkeletonDeed : Item, IRewardItem { private readonly HangingSkeletonDeed _deed; + public override bool Singleton => true; + public InternalGump(HangingSkeletonDeed skeleton) : base(100, 200) { _deed = skeleton; @@ -253,7 +253,6 @@ public partial class HangingSkeletonDeed : Item, IRewardItem if (north && west) { - from.CloseGump(); from.SendGump(new FacingGump(_deed, _itemID, p3d, house)); } else if (north || west) @@ -280,6 +279,8 @@ public partial class HangingSkeletonDeed : Item, IRewardItem private readonly Point3D _location; private readonly HangingSkeletonDeed _skeleton; + public override bool Singleton => true; + public FacingGump(HangingSkeletonDeed banner, int itemID, Point3D location, BaseHouse house) : base(150, 50) { _skeleton = banner; diff --git a/Projects/UOContent/Items/Special/Veteran Rewards/MiningCart.cs b/Projects/UOContent/Items/Special/Veteran Rewards/MiningCart.cs index 47db9eee1..f677de888 100644 --- a/Projects/UOContent/Items/Special/Veteran Rewards/MiningCart.cs +++ b/Projects/UOContent/Items/Special/Veteran Rewards/MiningCart.cs @@ -368,7 +368,6 @@ public partial class MiningCartDeed : BaseAddonDeed, IRewardItem, IRewardOption if (IsChildOf(from.Backpack)) { - from.CloseGump(); from.SendGump(new RewardOptionGump(this)); } else diff --git a/Projects/UOContent/Items/Special/Veteran Rewards/MinotaurStatue.cs b/Projects/UOContent/Items/Special/Veteran Rewards/MinotaurStatue.cs index b435b16e4..3c4a9a130 100644 --- a/Projects/UOContent/Items/Special/Veteran Rewards/MinotaurStatue.cs +++ b/Projects/UOContent/Items/Special/Veteran Rewards/MinotaurStatue.cs @@ -110,7 +110,6 @@ public partial class MinotaurStatueDeed : BaseAddonDeed, IRewardItem, IRewardOpt if (IsChildOf(from.Backpack)) { - from.CloseGump(); from.SendGump(new RewardOptionGump(this)); } else diff --git a/Projects/UOContent/Items/Special/Veteran Rewards/PottedCactus.cs b/Projects/UOContent/Items/Special/Veteran Rewards/PottedCactus.cs index c1f4e48a7..cbafbc7b0 100644 --- a/Projects/UOContent/Items/Special/Veteran Rewards/PottedCactus.cs +++ b/Projects/UOContent/Items/Special/Veteran Rewards/PottedCactus.cs @@ -50,7 +50,6 @@ public partial class PottedCactusDeed : Item, IRewardItem if (IsChildOf(from.Backpack)) { - from.CloseGump(); from.SendGump(new InternalGump(this)); } else @@ -73,6 +72,8 @@ public partial class PottedCactusDeed : Item, IRewardItem { private readonly PottedCactusDeed _deed; + public override bool Singleton => true; + public InternalGump(PottedCactusDeed cactus) : base(100, 200) { _deed = cactus; diff --git a/Projects/UOContent/Items/Special/Veteran Rewards/StoneAnkh.cs b/Projects/UOContent/Items/Special/Veteran Rewards/StoneAnkh.cs index 2deb30ca0..b520563cc 100644 --- a/Projects/UOContent/Items/Special/Veteran Rewards/StoneAnkh.cs +++ b/Projects/UOContent/Items/Special/Veteran Rewards/StoneAnkh.cs @@ -76,7 +76,6 @@ public partial class StoneAnkh : BaseAddon, IRewardItem if (house?.IsOwner(from) == true) { - from.CloseGump(); from.SendGump(new RewardDemolitionGump(this, 1049783)); // Do you wish to re-deed this decoration? } else @@ -122,7 +121,6 @@ public partial class StoneAnkhDeed : BaseAddonDeed, IRewardItem if (IsChildOf(from.Backpack)) { - from.CloseGump(); from.SendGump(new InternalGump(this)); } else @@ -150,6 +148,8 @@ public partial class StoneAnkhDeed : BaseAddonDeed, IRewardItem { private readonly StoneAnkhDeed _deed; + public override bool Singleton => true; + public InternalGump(StoneAnkhDeed deed) : base(150, 50) { _deed = deed; diff --git a/Projects/UOContent/Items/Special/Veteran Rewards/TreeStump.cs b/Projects/UOContent/Items/Special/Veteran Rewards/TreeStump.cs index a453afcf2..5f4fa7cd1 100644 --- a/Projects/UOContent/Items/Special/Veteran Rewards/TreeStump.cs +++ b/Projects/UOContent/Items/Special/Veteran Rewards/TreeStump.cs @@ -203,7 +203,6 @@ public partial class TreeStumpDeed : BaseAddonDeed, IRewardItem, IRewardOption if (IsChildOf(from.Backpack)) { - from.CloseGump(); from.SendGump(new RewardOptionGump(this)); } else diff --git a/Projects/UOContent/Items/Special/Veteran Rewards/WallBanner.cs b/Projects/UOContent/Items/Special/Veteran Rewards/WallBanner.cs index b70871ef2..14a1b6e07 100644 --- a/Projects/UOContent/Items/Special/Veteran Rewards/WallBanner.cs +++ b/Projects/UOContent/Items/Special/Veteran Rewards/WallBanner.cs @@ -304,7 +304,6 @@ public partial class WallBannerDeed : BaseAddonDeed, IRewardItem if (IsChildOf(from.Backpack)) { - from.CloseGump(); from.SendGump(new InternalGump(this)); } else @@ -324,6 +323,8 @@ public partial class WallBannerDeed : BaseAddonDeed, IRewardItem { private readonly WallBannerDeed _wallBanner; + public override bool Singleton => true; + public InternalGump(WallBannerDeed wallBanner) : base(150, 50) { _wallBanner = wallBanner; diff --git a/Projects/UOContent/Items/Special/Veteran Rewards/WeaponEngravingTool.cs b/Projects/UOContent/Items/Special/Veteran Rewards/WeaponEngravingTool.cs index bffbb5f48..95af438d8 100644 --- a/Projects/UOContent/Items/Special/Veteran Rewards/WeaponEngravingTool.cs +++ b/Projects/UOContent/Items/Special/Veteran Rewards/WeaponEngravingTool.cs @@ -174,7 +174,6 @@ public partial class WeaponEngravingTool : Item, IUsesRemaining, IRewardItem if (targeted is BaseWeapon item) { - from.CloseGump(); from.SendGump(new InternalGump(_tool, item)); } else @@ -189,6 +188,8 @@ public partial class WeaponEngravingTool : Item, IUsesRemaining, IRewardItem private readonly BaseWeapon _target; private readonly WeaponEngravingTool _tool; + public override bool Singleton => true; + public InternalGump(WeaponEngravingTool tool, BaseWeapon target) : base(0, 0) { _tool = tool; diff --git a/Projects/UOContent/Mobiles/Healers/BaseHealer.cs b/Projects/UOContent/Mobiles/Healers/BaseHealer.cs index 54e41cf82..f80acda72 100644 --- a/Projects/UOContent/Mobiles/Healers/BaseHealer.cs +++ b/Projects/UOContent/Mobiles/Healers/BaseHealer.cs @@ -86,7 +86,6 @@ public abstract partial class BaseHealer : BaseVendor m.PlaySound(0x1F2); m.FixedEffect(0x376A, 10, 16); - m.CloseGump(); m.SendGump(new ResurrectGump(m, ResurrectMessage.Healer)); } diff --git a/Projects/UOContent/Mobiles/Healers/PricedHealer.cs b/Projects/UOContent/Mobiles/Healers/PricedHealer.cs index 2648cec2d..4517cbceb 100644 --- a/Projects/UOContent/Mobiles/Healers/PricedHealer.cs +++ b/Projects/UOContent/Mobiles/Healers/PricedHealer.cs @@ -36,7 +36,6 @@ public partial class PricedHealer : BaseHealer m.PlaySound(0x214); m.FixedEffect(0x376A, 10, 16); - m.CloseGump(); m.SendGump(new PricedResurrectGump(this, Price)); } diff --git a/Projects/UOContent/Mobiles/Monsters/Misc/Magic/EtherealWarrior.cs b/Projects/UOContent/Mobiles/Monsters/Misc/Magic/EtherealWarrior.cs index 6bdb83ca9..64b81daf4 100644 --- a/Projects/UOContent/Mobiles/Monsters/Misc/Magic/EtherealWarrior.cs +++ b/Projects/UOContent/Mobiles/Monsters/Misc/Magic/EtherealWarrior.cs @@ -77,7 +77,6 @@ namespace Server.Mobiles Direction = GetDirectionTo(from); from.PlaySound(0x1F2); from.FixedEffect(0x376A, 10, 16); - from.CloseGump(); from.SendGump(new ResurrectGump(from, ResurrectMessage.Healer)); } } diff --git a/Projects/UOContent/Mobiles/PlayerMobile.cs b/Projects/UOContent/Mobiles/PlayerMobile.cs index 6c9123179..dd015ee04 100644 --- a/Projects/UOContent/Mobiles/PlayerMobile.cs +++ b/Projects/UOContent/Mobiles/PlayerMobile.cs @@ -900,17 +900,17 @@ namespace Server.Mobiles { Direction.North => itemIDs[0], Direction.South => itemIDs[0], - Direction.East => itemIDs[1], - Direction.West => itemIDs[1], - _ => item.ItemID + Direction.East => itemIDs[1], + Direction.West => itemIDs[1], + _ => item.ItemID }, 4 => dir switch { Direction.South => itemIDs[0], - Direction.East => itemIDs[1], + Direction.East => itemIDs[1], Direction.North => itemIDs[2], - Direction.West => itemIDs[3], - _ => item.ItemID + Direction.West => itemIDs[3], + _ => item.ItemID }, _ => item.ItemID }; @@ -981,7 +981,7 @@ namespace Server.Mobiles } if (skillId == 35) - // AnimalTaming.DeferredTarget = true; + // AnimalTaming.DeferredTarget = true; { AnimalTaming.DisableMessage = false; } @@ -1723,22 +1723,10 @@ namespace Server.Mobiles public override bool Move(Direction d) { - var ns = NetState; - - if (ns != null) + if (NetState != null && Alive && !NetState.CloseGump()) { - if (HasGump()) - { - if (Alive) - { - CloseGump(); - } - else - { - SendLocalizedMessage(500111); // You are frozen and cannot move. - return false; - } - } + SendLocalizedMessage(500111); // You are frozen and cannot move. + return false; } // var speed = ComputeMovementSpeed(d); @@ -1998,10 +1986,9 @@ namespace Server.Mobiles { var house = BaseHouse.FindHouseAt(this); - if (CheckAlive() && house?.IsOwner(this) == true && house.InternalizedVendors.Count > 0) + if (CheckAlive() && house?.IsOwner(this) == true && house.InternalizedVendors.Count > 0 && NetState is NetState { } ns) { - CloseGump(); - SendGump(new ReclaimVendorGump(house)); + ns.SendGump(new ReclaimVendorGump(house)); } } @@ -3760,8 +3747,8 @@ namespace Server.Mobiles var name = ammo.Name ?? ammo switch { Arrow _ => $"arrow{(ammo.Amount != 1 ? "s" : "")}", - Bolt _ => $"bolt{(ammo.Amount != 1 ? "s" : "")}", - _ => $"#{ammo.LabelNumber}" + Bolt _ => $"bolt{(ammo.Amount != 1 ? "s" : "")}", + _ => $"#{ammo.LabelNumber}" }; PlaceInBackpack(ammo); @@ -3924,11 +3911,11 @@ namespace Server.Mobiles return; } - if (Core.SE) + if (Core.SE && NetState is { } ns) { - if (!HasGump()) + if (!ns.HasGump()) { - SendGump(new CancelRenewInventoryInsuranceGump(this, null)); + ns.SendGump(new CancelRenewInventoryInsuranceGump(this, null)); } } else @@ -3974,15 +3961,18 @@ namespace Server.Mobiles // TODO: Investigate item sorting - CloseGump(); + if (NetState is { } ns) + { + ns.CloseGump(); - if (queue.Count == 0) - { - SendLocalizedMessage(1114915, "", 0x35); // None of your current items meet the requirements for insurance. - } - else - { - SendGump(new ItemInsuranceMenuGump(this, queue.ToArray())); + if (queue.Count == 0) + { + SendLocalizedMessage(1114915, "", 0x35); // None of your current items meet the requirements for insurance. + } + else + { + ns.SendGump(new ItemInsuranceMenuGump(this, queue.ToArray())); + } } } @@ -4001,12 +3991,14 @@ namespace Server.Mobiles private void ToggleQuestItemTarget() { - BaseQuestGump.CloseOtherGumps(this); - CloseGump(); - CloseGump(); - CloseGump(); - // CloseGump( typeof( UnknownGump802 ) ); - // CloseGump( typeof( UnknownGump804 ) ); + if (NetState != null) + { + BaseQuestGump.CloseOtherGumps(this); + var gumps = this.GetGumps(); + gumps.Close(); + gumps.Close(); + gumps.Close(); + } BeginTarget(-1, false, TargetFlags.None, ToggleQuestItem_Callback); SendLocalizedMessage(1072352); // Target the item you wish to toggle Quest Item status on to cancel @@ -4456,7 +4448,10 @@ namespace Server.Mobiles private void SendYoungDeathNotice() { - SendGump(new YoungDeathNoticeGump()); + if (NetState is { } ns) + { + ns.SendGump(new YoungDeathNoticeGump()); + } } public override void OnSpeech(SpeechEventArgs e) diff --git a/Projects/UOContent/Mobiles/Townfolk/TownCrier.cs b/Projects/UOContent/Mobiles/Townfolk/TownCrier.cs index 56685da6b..a2dd13d14 100644 --- a/Projects/UOContent/Mobiles/Townfolk/TownCrier.cs +++ b/Projects/UOContent/Mobiles/Townfolk/TownCrier.cs @@ -197,13 +197,13 @@ public class TownCrierGump : Gump private readonly Mobile m_From; private readonly ITownCrierEntryList m_Owner; + public override bool Singleton => true; + public TownCrierGump(Mobile from, ITownCrierEntryList owner) : base(50, 50) { m_From = from; m_Owner = owner; - from.CloseGump(); - AddPage(0); var entries = owner.Entries; diff --git a/Projects/UOContent/Mobiles/Vendors/BaseVendor.cs b/Projects/UOContent/Mobiles/Vendors/BaseVendor.cs index bbc9667ab..2b3b0ffbc 100644 --- a/Projects/UOContent/Mobiles/Vendors/BaseVendor.cs +++ b/Projects/UOContent/Mobiles/Vendors/BaseVendor.cs @@ -4,6 +4,7 @@ using Server.Collections; using Server.ContextMenus; using Server.Engines.BulkOrders; using Server.Factions; +using Server.Gumps; using Server.Items; using Server.Misc; using Server.Mobiles; diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/AnimalTrainer.cs b/Projects/UOContent/Mobiles/Vendors/NPC/AnimalTrainer.cs index 855ecf1bc..467ea007b 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/AnimalTrainer.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/AnimalTrainer.cs @@ -99,7 +99,7 @@ namespace Server.Mobiles return max; } - private void CloseClaimList(Mobile from) + private static void CloseClaimList(Mobile from) { from.CloseGump(); } @@ -427,14 +427,14 @@ namespace Server.Mobiles private readonly List m_List; private readonly AnimalTrainer m_Trainer; + public override bool Singleton => true; + public ClaimListGump(AnimalTrainer trainer, Mobile from, List list) : base(50, 50) { m_Trainer = trainer; m_From = from; m_List = list; - from.CloseGump(); - AddPage(0); AddBackground(0, 0, 325, 50 + list.Count * 20, 9250); diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/CustomHairstylist.cs b/Projects/UOContent/Mobiles/Vendors/NPC/CustomHairstylist.cs index 3f67d07e5..819224578 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/CustomHairstylist.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/CustomHairstylist.cs @@ -155,16 +155,17 @@ namespace Server.Mobiles private readonly Mobile m_From; private readonly HairstylistBuyInfo[] m_SellList; private readonly Mobile m_Vendor; - + public override bool Singleton => true; public HairstylistBuyGump(Mobile from, Mobile vendor, HairstylistBuyInfo[] sellList) : base(50, 50) { m_From = from; m_Vendor = vendor; m_SellList = sellList; - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); + var gumps = from.GetGumps(); + + gumps.Close(); + gumps.Close(); var isFemale = from.Female || from.Body.IsFemale; @@ -327,6 +328,8 @@ namespace Server.Mobiles private readonly int m_Price; private readonly Mobile m_Vendor; + public override bool Singleton => true; + public ChangeHairHueGump( Mobile from, Mobile vendor, int price, bool hair, bool facialHair, ChangeHairHueEntry[] entries @@ -339,10 +342,6 @@ namespace Server.Mobiles m_FacialHair = facialHair; m_Entries = entries; - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); - AddPage(0); AddBackground(100, 10, 350, 370, 2600); @@ -496,6 +495,8 @@ namespace Server.Mobiles private readonly int m_Price; private readonly Mobile m_Vendor; + public override bool Singleton => true; + public ChangeHairstyleGump( Mobile from, Mobile vendor, int price, bool facialHair, ChangeHairstyleEntry[] entries ) : base(50, 50) @@ -506,9 +507,10 @@ namespace Server.Mobiles m_FacialHair = facialHair; m_Entries = entries; - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); + var gumps = from.GetGumps(); + + gumps.Close(); + gumps.Close(); var tableWidth = m_FacialHair ? 2 : 3; var tableHeight = (entries.Length + tableWidth - (m_FacialHair ? 1 : 2)) / tableWidth; diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/TinkerGuildmaster.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/TinkerGuildmaster.cs index eb28ed806..9e9dbad67 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/TinkerGuildmaster.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/TinkerGuildmaster.cs @@ -1,6 +1,7 @@ using ModernUO.Serialization; using Server.Collections; using Server.ContextMenus; +using Server.Gumps; using Server.Items; namespace Server.Mobiles diff --git a/Projects/UOContent/Mobiles/Vendors/PlayerBarkeeper.cs b/Projects/UOContent/Mobiles/Vendors/PlayerBarkeeper.cs index 90da5bd2d..78e63846b 100644 --- a/Projects/UOContent/Mobiles/Vendors/PlayerBarkeeper.cs +++ b/Projects/UOContent/Mobiles/Vendors/PlayerBarkeeper.cs @@ -513,7 +513,6 @@ namespace Server.Mobiles public void BeginChangeAppearance(Mobile from) { - from.CloseGump(); from.SendGump(new PlayerVendorCustomizeGump(this, from)); } @@ -682,13 +681,14 @@ namespace Server.Mobiles private readonly PlayerBarkeeper m_Barkeeper; private readonly Mobile m_From; + public override bool Singleton => true; + public BarkeeperTitleGump(Mobile from, PlayerBarkeeper barkeeper) : base(0, 0) { m_From = from; m_Barkeeper = barkeeper; from.CloseGump(); - from.CloseGump(); var entries = m_Entries; @@ -832,12 +832,13 @@ namespace Server.Mobiles private readonly PlayerBarkeeper m_Barkeeper; private readonly Mobile m_From; + public override bool Singleton => true; + public BarkeeperGump(Mobile from, PlayerBarkeeper barkeeper) : base(0, 0) { m_From = from; m_Barkeeper = barkeeper; - from.CloseGump(); from.CloseGump(); RenderBackground(); diff --git a/Projects/UOContent/Mobiles/Vendors/PlayerVendor.cs b/Projects/UOContent/Mobiles/Vendors/PlayerVendor.cs index 82c614d17..2721fadbd 100644 --- a/Projects/UOContent/Mobiles/Vendors/PlayerVendor.cs +++ b/Projects/UOContent/Mobiles/Vendors/PlayerVendor.cs @@ -668,19 +668,19 @@ public partial class PlayerVendor : Mobile public void SendOwnerGump(Mobile to) { + var gumps = to.GetGumps(); + if (BaseHouse.NewVendorSystem) { - to.CloseGump(); - to.CloseGump(); - - to.SendGump(new NewPlayerVendorOwnerGump(this)); + gumps.Close(); + gumps.Close(); + gumps.Send(new NewPlayerVendorOwnerGump(this)); } else { - to.CloseGump(); - to.CloseGump(); - - to.SendGump(new PlayerVendorOwnerGump(this)); + gumps.Close(); + gumps.Close(); + gumps.Send(new PlayerVendorOwnerGump(this)); } } @@ -723,7 +723,6 @@ public partial class PlayerVendor : Mobile } else { - from.CloseGump(); from.SendGump(new PlayerVendorBuyGump(vendor, vi)); } } diff --git a/Projects/UOContent/Mobiles/Vendors/RentedVendor.cs b/Projects/UOContent/Mobiles/Vendors/RentedVendor.cs index 1fb0a4b07..64977022a 100644 --- a/Projects/UOContent/Mobiles/Vendors/RentedVendor.cs +++ b/Projects/UOContent/Mobiles/Vendors/RentedVendor.cs @@ -203,15 +203,13 @@ public partial class RentedVendor : PlayerVendor if (vendor.IsOwner(from)) { - from.CloseGump(); - from.SendGump(new RenterVendorRentalGump(vendor)); + from.SendGump(new RenterVendorRentalGump(vendor), true); vendor.SendRentalExpireMessage(from); } else if (vendor.IsLandlord(from)) { - from.CloseGump(); - from.SendGump(new LandlordVendorRentalGump(vendor)); + from.SendGump(new LandlordVendorRentalGump(vendor), true); vendor.SendRentalExpireMessage(from); } @@ -313,7 +311,6 @@ public partial class RentedVendor : PlayerVendor { from.SendLocalizedMessage(1062504); // Please wait while the renter considers your offer. - owner.CloseGump(); owner.SendGump(new VendorRentalRefundGump(m_Vendor, from, amount)); } } diff --git a/Projects/UOContent/Multis/Boats/BaseBoat.cs b/Projects/UOContent/Multis/Boats/BaseBoat.cs index 779940bc4..9e367b455 100644 --- a/Projects/UOContent/Multis/Boats/BaseBoat.cs +++ b/Projects/UOContent/Multis/Boats/BaseBoat.cs @@ -4,6 +4,7 @@ using System.Runtime.CompilerServices; using ModernUO.Serialization; using Server.Collections; using Server.Engines.Spawners; +using Server.Gumps; using Server.Items; using Server.Multis.Boats; using Server.Network; diff --git a/Projects/UOContent/Multis/Houses/BaseHouse.cs b/Projects/UOContent/Multis/Houses/BaseHouse.cs index bd2c3ed03..5c42e9fa9 100644 --- a/Projects/UOContent/Multis/Houses/BaseHouse.cs +++ b/Projects/UOContent/Multis/Houses/BaseHouse.cs @@ -2248,7 +2248,6 @@ namespace Server.Multis } else { - to.CloseGump(); to.SendGump(new HouseTransferGump(from, to, this)); } } @@ -2281,7 +2280,6 @@ namespace Server.Multis if (CheckTransferPosition(from, to)) { - to.CloseGump(); to.SendGump(new HouseTransferGump(from, to, this)); } } @@ -2401,7 +2399,6 @@ namespace Server.Multis if (info != null) { - m.CloseGump(); m.SendGump(new SetSecureLevelGump(m_Owner, info, this)); } else if (item.Parent != null) @@ -2437,7 +2434,6 @@ namespace Server.Multis LockDowns.Remove(item); item.Movable = false; - m.CloseGump(); m.SendGump(new SetSecureLevelGump(m_Owner, info, this)); } } @@ -4368,7 +4364,6 @@ namespace Server.Multis if (sec != null) { - from.CloseGump(); from.SendGump(new SetSecureLevelGump(from, sec, BaseHouse.FindHouseAt(item))); } } diff --git a/Projects/UOContent/Multis/Houses/HousePlacementTool.cs b/Projects/UOContent/Multis/Houses/HousePlacementTool.cs index d03a61597..18f455f3c 100644 --- a/Projects/UOContent/Multis/Houses/HousePlacementTool.cs +++ b/Projects/UOContent/Multis/Houses/HousePlacementTool.cs @@ -41,13 +41,12 @@ public class HousePlacementCategoryGump : Gump private const int LabelColorDisabled = 0x4210; private readonly Mobile _from; + public override bool Singleton => true; + public HousePlacementCategoryGump(Mobile from) : base(50, 50) { _from = from; - from.CloseGump(); - from.CloseGump(); - AddPage(0); AddBackground(0, 0, 270, 145, 5054); @@ -107,14 +106,13 @@ public class HousePlacementListGump : Gump private readonly HousePlacementEntry[] _entries; private readonly Mobile _from; + public override bool Singleton => true; + public HousePlacementListGump(Mobile from, HousePlacementEntry[] entries) : base(50, 50) { _from = from; _entries = entries; - from.CloseGump(); - from.CloseGump(); - AddPage(0); AddBackground(0, 0, 520, 420, 5054); diff --git a/Projects/UOContent/Multis/Houses/HouseSign.cs b/Projects/UOContent/Multis/Houses/HouseSign.cs index faa390cbd..255077418 100644 --- a/Projects/UOContent/Multis/Houses/HouseSign.cs +++ b/Projects/UOContent/Multis/Houses/HouseSign.cs @@ -263,7 +263,6 @@ public partial class HouseSign : Item } else { - from.CloseGump(); from.SendGump(new VendorInventoryGump(sign.Owner, from)); } } diff --git a/Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs b/Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs index a72276b71..fe803caa7 100644 --- a/Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs +++ b/Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs @@ -13,20 +13,12 @@ * along with this program. If not, see . * *************************************************************************/ -using System; using System.Buffers; -using System.Buffers.Binary; -using System.Diagnostics; -using System.IO; -using System.Runtime.InteropServices; using CommunityToolkit.HighPerformance; -using Server.Diagnostics; using Server.Engines.Help; using Server.Engines.MLQuests; using Server.Engines.Virtues; -using Server.Exceptions; using Server.Guilds; -using Server.Gumps; using Server.Items; using Server.Misc; using Server.Mobiles; @@ -52,7 +44,6 @@ public static class IncomingPlayerPackets IncomingPackets.Register(0x9B, 258, true, &HelpRequest); IncomingPackets.Register(0xA4, 149, false, &SystemInfo); IncomingPackets.Register(0xA7, 4, true, &RequestScrollWindow); - IncomingPackets.Register(0xB1, 0, true, &DisplayGumpResponse); IncomingPackets.Register(0xC2, 0, true, &UnicodePromptResponse); IncomingPackets.Register(0xC8, 2, true, &SetUpdateRange); IncomingPackets.Register(0xD0, 0, true, &ConfigurationFile); @@ -349,173 +340,6 @@ public static class IncomingPlayerPackets HelpGump.HelpRequest(state.Mobile); } - public static void DisplayGumpResponse(NetState state, SpanReader reader) - { - var serial = (Serial)reader.ReadUInt32(); - var typeId = reader.ReadInt32(); - var buttonId = reader.ReadInt32(); - - BaseGump baseGump = null; - - foreach (var g in state.Gumps) - { - if (g.Serial != serial || g.TypeID != typeId) - { - continue; - } - - baseGump = g; - break; - } - - if (baseGump != null) - { - if (baseGump is Gump gump) - { - var buttonExists = buttonId == 0; // 0 is always 'close' - - if (!buttonExists) - { - foreach (var e in gump.Entries) - { - if ((e as GumpButton)?.ButtonID == buttonId) - { - buttonExists = true; - break; - } - - if ((e as GumpImageTileButton)?.ButtonID == buttonId) - { - buttonExists = true; - break; - } - } - } - - if (!buttonExists) - { - state.LogInfo("Invalid gump response, disconnecting..."); - var exception = new InvalidGumpResponseException($"Button {buttonId} doesn't exist"); - exception.SetStackTrace(new StackTrace()); - NetState.TraceException(exception); - return; - } - } - - var switchCount = reader.ReadInt32(); - - if (switchCount < 0 || switchCount > baseGump.Switches) - { - state.LogInfo("Invalid gump response, disconnecting..."); - var exception = new InvalidGumpResponseException($"Bad switch count {switchCount}"); - exception.SetStackTrace(new StackTrace()); - NetState.TraceException(exception); - return; - } - - int switchByteCount = switchCount * 4; - - // Read all the integers - ReadOnlySpan switchBlock = - MemoryMarshal.Cast(reader.Buffer.Slice(reader.Position, switchByteCount)); - - reader.Seek(switchByteCount, SeekOrigin.Current); - - scoped ReadOnlySpan switches; - - // Swap the endianness if necessary - if (BitConverter.IsLittleEndian) - { - Span reversedSwitches = stackalloc int[switchCount]; - BinaryPrimitives.ReverseEndianness(switchBlock, reversedSwitches); - switches = reversedSwitches; - } - else - { - switches = switchBlock; - } - - var textCount = reader.ReadInt32(); - if (textCount < 0 || textCount > baseGump.TextEntries) - { - state.LogInfo("Invalid gump response, disconnecting..."); - var exception = new InvalidGumpResponseException($"Bad text entry count {textCount}"); - exception.SetStackTrace(new StackTrace()); - NetState.TraceException(exception); - return; - } - - Span textIds = stackalloc ushort[textCount]; - Span textFields = stackalloc Range[textCount]; - - var textOffset = reader.Position; - for (var i = 0; i < textCount; i++) - { - var textId = reader.ReadUInt16(); - var textLength = reader.ReadUInt16(); - - if (textLength > 239) - { - state.LogInfo("Invalid gump response, disconnecting..."); - var exception = new InvalidGumpResponseException($"Text entry {i} is too long ({textLength})"); - exception.SetStackTrace(new StackTrace()); - NetState.TraceException(exception); - return; - } - - textIds[i] = textId; - var offset = reader.Position - textOffset; - var length = textLength * 2; - textFields[i] = offset..(offset + length); - reader.Seek(length, SeekOrigin.Current); - } - - var textBlock = reader.Buffer.Slice(textOffset, reader.Position - textOffset); - - state.RemoveGump(baseGump); - - var prof = GumpProfile.Acquire(baseGump.GetType()); - - prof?.Start(); - - var relayInfo = new RelayInfo( - buttonId, - switches, - textIds, - textFields, - textBlock - ); - baseGump.OnResponse(state, relayInfo); - - prof?.Finish(); - } - - if (typeId == 461) - { - // Virtue gump - var switchCount = reader.Remaining >= 4 ? reader.ReadInt32() : 0; - - if (buttonId == 1 && switchCount > 0) - { - var beheld = World.FindEntity((Serial)reader.ReadUInt32()); - - if (beheld != null) - { - VirtueGump.RequestVirtueGump((PlayerMobile)state.Mobile, beheld); - } - } - else - { - var beheld = World.FindMobile(serial); - - if (beheld != null) - { - VirtueGump.RequestVirtueItem((PlayerMobile)state.Mobile, beheld, buttonId); - } - } - } - } - public static void SetWarMode(NetState state, SpanReader reader) { state.Mobile?.DelayChangeWarmode(reader.ReadBoolean()); diff --git a/Projects/UOContent/Regions/HouseRegion.cs b/Projects/UOContent/Regions/HouseRegion.cs index 70951f510..7c0ce914c 100644 --- a/Projects/UOContent/Regions/HouseRegion.cs +++ b/Projects/UOContent/Regions/HouseRegion.cs @@ -254,9 +254,10 @@ public class HouseRegion : BaseRegion } else if (isOwner) { - from.CloseGump(); - from.CloseGump(); - from.SendGump(new ConfirmHouseResizeGump(House)); + var gumps = from.GetGumps(); + gumps.Close(); + gumps.Close(); + gumps.Send(new ConfirmHouseResizeGump(House)); } else { diff --git a/Projects/UOContent/Skills/AnimalLore.cs b/Projects/UOContent/Skills/AnimalLore.cs index e7b77de1d..e53220844 100644 --- a/Projects/UOContent/Skills/AnimalLore.cs +++ b/Projects/UOContent/Skills/AnimalLore.cs @@ -62,7 +62,6 @@ namespace Server.SkillHandlers } else { - from.CloseGump(); from.SendGump(new AnimalLoreGump(c)); } } @@ -73,6 +72,8 @@ namespace Server.SkillHandlers { private const int LabelColor = 0x24E5; + public override bool Singleton => true; + public AnimalLoreGump(BaseCreature c) : base(250, 50) { AddPage(0); diff --git a/Projects/UOContent/Skills/Tracking/Tracking.cs b/Projects/UOContent/Skills/Tracking/Tracking.cs index aaf5d07ee..f59f3462a 100644 --- a/Projects/UOContent/Skills/Tracking/Tracking.cs +++ b/Projects/UOContent/Skills/Tracking/Tracking.cs @@ -39,9 +39,11 @@ namespace Server.SkillHandlers { m.SendLocalizedMessage(1011350); // What do you wish to track? - m.CloseGump(); - m.CloseGump(); - m.SendGump(new TrackWhatGump(pm)); + var gumps = pm.GetGumps(); + + gumps.Close(); + gumps.Close(); + gumps.Send(new TrackWhatGump(pm)); } return TimeSpan.FromSeconds(10.0); // 10 second delay before being able to re-use a skill diff --git a/Projects/UOContent/Special Systems/Items/Resurrection/ResGate.cs b/Projects/UOContent/Special Systems/Items/Resurrection/ResGate.cs index e593912ad..c6c922ac7 100644 --- a/Projects/UOContent/Special Systems/Items/Resurrection/ResGate.cs +++ b/Projects/UOContent/Special Systems/Items/Resurrection/ResGate.cs @@ -23,7 +23,6 @@ public partial class ResGate : Item m.PlaySound(0x214); m.FixedEffect(0x376A, 10, 16); - m.CloseGump(); m.SendGump(new ResurrectGump(m)); } else diff --git a/Projects/UOContent/Spells/Chivalry/NobleSacrifice.cs b/Projects/UOContent/Spells/Chivalry/NobleSacrifice.cs index b50df416e..a63a9fe38 100644 --- a/Projects/UOContent/Spells/Chivalry/NobleSacrifice.cs +++ b/Projects/UOContent/Spells/Chivalry/NobleSacrifice.cs @@ -74,7 +74,6 @@ namespace Server.Spells.Chivalry else if (resChance > Utility.RandomDouble()) { m.FixedParticles(0x375A, 1, 15, 5005, 5, 3, EffectLayer.Head); - m.CloseGump(); m.SendGump(new ResurrectGump(Caster)); sacrifice = true; } diff --git a/Projects/UOContent/Spells/Eighth/Resurrection.cs b/Projects/UOContent/Spells/Eighth/Resurrection.cs index 09e99085d..f4c6b686e 100644 --- a/Projects/UOContent/Spells/Eighth/Resurrection.cs +++ b/Projects/UOContent/Spells/Eighth/Resurrection.cs @@ -63,7 +63,6 @@ namespace Server.Spells.Eighth m.PlaySound(0x214); m.FixedEffect(0x376A, 10, 16); - m.CloseGump(); m.SendGump(new ResurrectGump(Caster)); } } diff --git a/Projects/UOContent/Spells/Necromancy/SummonFamiliar.cs b/Projects/UOContent/Spells/Necromancy/SummonFamiliar.cs index 2fba42cc2..693f2d2b2 100644 --- a/Projects/UOContent/Spells/Necromancy/SummonFamiliar.cs +++ b/Projects/UOContent/Spells/Necromancy/SummonFamiliar.cs @@ -69,7 +69,6 @@ public class SummonFamiliarSpell : NecromancerSpell { if (CheckSequence()) { - Caster.CloseGump(); Caster.SendGump(new SummonFamiliarGump(Caster, Entries, this)); } @@ -109,6 +108,8 @@ public class SummonFamiliarGump : Gump private readonly SummonFamiliarSpell _spell; + public override bool Singleton => true; + public SummonFamiliarGump(Mobile from, SummonFamiliarEntry[] entries, SummonFamiliarSpell spell) : base(200, 100) { _from = from; @@ -187,14 +188,12 @@ public class SummonFamiliarGump : Gump // That familiar requires ~1_NECROMANCY~ Necromancy and ~2_SPIRIT~ Spirit Speak. _from.SendLocalizedMessage(1061606, $"{entry.ReqNecromancy:F1}\t{entry.ReqSpiritSpeak:F1}"); - _from.CloseGump(); _from.SendGump(new SummonFamiliarGump(_from, SummonFamiliarSpell.Entries, _spell)); } else if (entry.Type == null) { _from.SendMessage("That familiar has not yet been defined."); - _from.CloseGump(); _from.SendGump(new SummonFamiliarGump(_from, SummonFamiliarSpell.Entries, _spell)); } else diff --git a/Projects/UOContent/Spells/Ninjitsu/AnimalForm.cs b/Projects/UOContent/Spells/Ninjitsu/AnimalForm.cs index f2cc23693..c4588e4d8 100644 --- a/Projects/UOContent/Spells/Ninjitsu/AnimalForm.cs +++ b/Projects/UOContent/Spells/Ninjitsu/AnimalForm.cs @@ -143,7 +143,6 @@ public class AnimalForm : NinjaSpell var lastAnimalForm = GetLastAnimalForm(Caster); if (Caster is PlayerMobile && lastAnimalForm == -1 && !_wasMoving && !CasterIsMoving()) { - Caster.CloseGump(); Caster.SendGump(new AnimalFormGump(Caster, Entries, this)); } else if (Morph(Caster, lastAnimalForm) == MorphResult.Fail) @@ -361,6 +360,8 @@ public class AnimalForm : NinjaSpell private readonly AnimalForm _spell; private readonly AnimalFormEntry[] _entries; + public override bool Singleton => true; + public AnimalFormGump(Mobile caster, AnimalFormEntry[] entries, AnimalForm spell) : base(50, 50) { _caster = caster; diff --git a/Projects/UOContent/Spells/Spellweaving/GiftOfLife.cs b/Projects/UOContent/Spells/Spellweaving/GiftOfLife.cs index e40a0b674..320fcc3fe 100644 --- a/Projects/UOContent/Spells/Spellweaving/GiftOfLife.cs +++ b/Projects/UOContent/Spells/Spellweaving/GiftOfLife.cs @@ -103,7 +103,6 @@ namespace Server.Spells.Spellweaving if (master?.NetState != null && Utility.InUpdateRange(pet.Location, master.Location)) { - master.CloseGump(); master.SendGump(new PetResurrectGump(master, pet, hitsScalar)); } else @@ -116,7 +115,6 @@ namespace Server.Spells.Spellweaving if (friend.NetState != null && Utility.InUpdateRange(pet.Location, friend.Location)) { - friend.CloseGump(); friend.SendGump(new PetResurrectGump(friend, pet)); break; } @@ -125,7 +123,6 @@ namespace Server.Spells.Spellweaving } else { - m.CloseGump(); m.SendGump(new ResurrectGump(m, hitsScalar)); } diff --git a/Projects/Server/Text/TextDefinitionExtensions.cs b/Projects/UOContent/Text/TextDefinitionExtensions.cs similarity index 100% rename from Projects/Server/Text/TextDefinitionExtensions.cs rename to Projects/UOContent/Text/TextDefinitionExtensions.cs