diff --git a/Projects/Server/Gumps/Gump.cs b/Projects/Server/Gumps/Gump.cs index 163faada3..e366c34ef 100644 --- a/Projects/Server/Gumps/Gump.cs +++ b/Projects/Server/Gumps/Gump.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.Text; +using System.Text.Json; using Server.Network; using Server.Text; using Server.Utilities; @@ -10,6 +12,7 @@ public partial class Gump { private static Serial _nextSerial = (Serial)1; + public static readonly byte[] WebRender = StringToBuffer("{ webrender }"); public static readonly byte[] NoMove = StringToBuffer("{ nomove }"); public static readonly byte[] NoClose = StringToBuffer("{ noclose }"); public static readonly byte[] NoDispose = StringToBuffer("{ nodispose }"); @@ -53,6 +56,8 @@ public partial class Gump public bool Closable { get; set; } = true; + public bool UseWebRender { get; set; } = false; + public static int GetTypeID(Type type) => type?.FullName?.GetHashCode(StringComparison.Ordinal) ?? -1; public void AddPage(int page) @@ -70,6 +75,22 @@ public partial class Gump Add(new GumpBackground(x, y, width, height, gumpID)); } + public void SendData(Mobile m, string responseMethod, object value) + { + Entries.Clear(); + + var jtext = JsonSerializer.Serialize(value, new JsonSerializerOptions() { WriteIndented = true }); + Add(new GumpBodyUpdate(responseMethod, + Convert.ToBase64String(Encoding.UTF8.GetBytes(jtext)))); + + m.SendGump(this); + } + + public void AddBody(string body) + { + Add(new GumpBody(Convert.ToBase64String(Encoding.UTF8.GetBytes(body)))); + } + public void AddButton( int x, int y, int normalID, int pressedID, int buttonID, GumpButtonType type = GumpButtonType.Reply, int param = 0 diff --git a/Projects/Server/Gumps/GumpBody.cs b/Projects/Server/Gumps/GumpBody.cs new file mode 100644 index 000000000..6e8340946 --- /dev/null +++ b/Projects/Server/Gumps/GumpBody.cs @@ -0,0 +1,27 @@ +using Server.Collections; +using System; +using System.Buffers; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Server.Gumps +{ + public class GumpBody : GumpEntry + { + public static readonly byte[] LayoutName = Gump.StringToBuffer("body"); + + public override string Compile(OrderedHashSet strings) => $"{{ body {_body} }}"; + public GumpBody(string body) =>_body = body; + public string _body { get; set; } + public override void AppendTo(ref SpanWriter writer, OrderedHashSet strings, ref int entries, ref int switches) + { + writer.Write((ushort)0x7B20); // "{ " + writer.Write(LayoutName); + writer.WriteAscii(' '); + writer.WriteAscii(_body.ToString()); + writer.Write((ushort)0x207D); // " }" + } + } +} diff --git a/Projects/Server/Gumps/GumpBodyUpdate.cs b/Projects/Server/Gumps/GumpBodyUpdate.cs new file mode 100644 index 000000000..6a46e7cc0 --- /dev/null +++ b/Projects/Server/Gumps/GumpBodyUpdate.cs @@ -0,0 +1,34 @@ +using Server.Collections; +using System; +using System.Buffers; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Server.Gumps +{ + public class GumpBodyUpdate : GumpEntry + { + public static readonly byte[] LayoutName = Gump.StringToBuffer("bodyUpdate"); + + public override string Compile(OrderedHashSet strings) => $"{{ bodyUpdate {_responseButtonId} {_body} }}"; + public GumpBodyUpdate(string responseButtonId, string body) + { + _body = body; + _responseButtonId = responseButtonId; + } + public string _body { get; set; } + public string _responseButtonId { get; set; } + public override void AppendTo(ref SpanWriter writer, OrderedHashSet strings, ref int entries, ref int switches) + { + writer.Write((ushort)0x7B20); // "{ " + writer.Write(LayoutName); + writer.WriteAscii(' '); + writer.WriteAscii(_responseButtonId); + writer.WriteAscii(' '); + writer.WriteAscii(_body); + writer.Write((ushort)0x207D); // " }" + } + } +} diff --git a/Projects/Server/Network/Packets/IncomingPlayerPackets.cs b/Projects/Server/Network/Packets/IncomingPlayerPackets.cs index d49b3107c..50c87bce4 100644 --- a/Projects/Server/Network/Packets/IncomingPlayerPackets.cs +++ b/Projects/Server/Network/Packets/IncomingPlayerPackets.cs @@ -350,6 +350,7 @@ public static class IncomingPlayerPackets continue; } + var isWebResponse = gump.UseWebRender; var buttonExists = buttonID == 0; // 0 is always 'close' if (!buttonExists) @@ -370,7 +371,7 @@ public static class IncomingPlayerPackets } } - if (!buttonExists) + if (!isWebResponse && !buttonExists) { state.LogInfo("Invalid gump response, disconnecting..."); var exception = new InvalidGumpResponseException($"Button {buttonID} doesn't exist"); @@ -384,7 +385,7 @@ public static class IncomingPlayerPackets var switchCount = reader.ReadInt32(); - if (switchCount < 0 || switchCount > gump.m_Switches) + if (!isWebResponse && (switchCount < 0 || switchCount > gump.m_Switches)) { state.LogInfo("Invalid gump response, disconnecting..."); var exception = new InvalidGumpResponseException($"Bad switch count {switchCount}"); @@ -405,7 +406,7 @@ public static class IncomingPlayerPackets var textCount = reader.ReadInt32(); - if (textCount < 0 || textCount > gump.m_TextEntries) + if (!isWebResponse && (textCount < 0 || textCount > gump.m_TextEntries)) { state.LogInfo("Invalid gump response, disconnecting..."); var exception = new InvalidGumpResponseException($"Bad text entry count {textCount}"); @@ -440,7 +441,10 @@ public static class IncomingPlayerPackets textEntries[i] = new TextRelay(entryID, text); } - state.RemoveGump(gump); + if (!isWebResponse) + { + state.RemoveGump(gump); + } var prof = GumpProfile.Acquire(gump.GetType()); diff --git a/Projects/Server/Network/Packets/OutgoingGumpPackets.cs b/Projects/Server/Network/Packets/OutgoingGumpPackets.cs index f1eb61fa0..885ca7f1a 100644 --- a/Projects/Server/Network/Packets/OutgoingGumpPackets.cs +++ b/Projects/Server/Network/Packets/OutgoingGumpPackets.cs @@ -109,6 +109,11 @@ public static class OutgoingGumpPackets var layoutWriter = new SpanWriter(_layoutBuffer); + if (gump.UseWebRender) + { + layoutWriter.Write(Gump.WebRender); + } + if (!gump.Draggable) { layoutWriter.Write(Gump.NoMove); diff --git a/Projects/UOContent/Commands/Object Creation/AddGump.cs b/Projects/UOContent/Commands/Object Creation/AddGump.cs index 2c093052f..07446d1be 100644 --- a/Projects/UOContent/Commands/Object Creation/AddGump.cs +++ b/Projects/UOContent/Commands/Object Creation/AddGump.cs @@ -86,10 +86,14 @@ namespace Server.Gumps (m_Page + 1) * 10 < searchResults.Length ? 0x7FFF : 0x5EF7 ); } - - public static void Initialize() + private static void Sciter_OnCommand(CommandEventArgs e) + { + e.Mobile.SendGump(new SciterTestGump(e.Mobile)); + } + public static void Initialize() { CommandSystem.Register("AddMenu", AccessLevel.GameMaster, AddMenu_OnCommand); + CommandSystem.Register("t", AccessLevel.GameMaster, Sciter_OnCommand); } [Usage("AddMenu [searchString]")] diff --git a/Projects/UOContent/Gumps/SciterTestGump.cs b/Projects/UOContent/Gumps/SciterTestGump.cs new file mode 100644 index 000000000..4147c24c8 --- /dev/null +++ b/Projects/UOContent/Gumps/SciterTestGump.cs @@ -0,0 +1,287 @@ +using Server.Gumps; +using Server.Items; +using Server.Network; +using System; +using System.IO; +using System.Text; + +namespace Server.Gumps +{ + public class SciterTestGump : Gump + { + public class Item + { + public string Name { get; set; } + public int Count { get; set; } + } + public class Shop + { + public Item[] ShopItems { get; set; } = new Item[] + { + new Item(){Name="Arrow",Count = 10 }, + new Item(){Name="Bolt",Count = 10 }, + new Item(){Name="Gold",Count = 20000 }, + }; + } + public Shop _shop = new Shop(); + public SciterTestGump(Mobile user) : base( + 0, + 0 + ) + { + UseWebRender = true; + AddBody(body()); + } + + + public void TryToAddItem(Mobile m, int index) + { + if (_shop.ShopItems.Length < index) + return; + + var itemName = _shop.ShopItems[index].Name; + var itemCount = Convert.ToInt32(_shop.ShopItems[index].Count); + + var type = AssemblyHandler.FindTypeByName(itemName); + + var item = Activator.CreateInstance(type, args: new object[] { itemCount }); + if (item is Server.Item _item) + { + m.AddToBackpack(_item); + } + + } + public override void OnResponse(NetState sender, RelayInfo info) + { + var from = sender.Mobile; + switch (info.ButtonID) + { + case 0: // close + sender.RemoveGump(this); + break; + case 1: + SendData(from, "1", _shop); + break; + case 2: + TryToAddItem(from, Convert.ToInt32(info.TextEntries[0].Text)); + break; + + default: + break; + } + + } + public string body() + { + return "\r\n" + + " \r\n" + + " \r\n" + + " \r\n\r\n" + + "\t\r\n" + + " \r\n" + + "\r\n" + + " \r\n" + + "
\r\n" + + " \r\n" + + "

MUO + VueJ" + + "s Demo

\r\n" + + "
    \r\n" + + "
  • \r\n" + + "

    {{ item" + + ".Name }} amount: {{ " + + "item.Count }} \r\n" + + " OK\r" + + "\n" + + "

    \r\n" + + "
  • \r\n" + + "
\r\n" + + "
\r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + ""; + } + + } +}