Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PoC] Add WebRender #807

Draft
wants to merge 16 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions Projects/Server/Gumps/Gump.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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 }");
Expand Down Expand Up @@ -53,6 +56,8 @@ public Gump(int x, int y)

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)
Expand All @@ -70,6 +75,22 @@ public void AddBackground(int x, int y, int width, int height, int gumpID)
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
Expand Down
14 changes: 14 additions & 0 deletions Projects/Server/Gumps/GumpBody.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Server.Collections;
using System.Buffers;

namespace Server.Gumps;

public class GumpBody : GumpEntry
{
public GumpBody(string body) => Body = body;
public string Body { get; }
public override void AppendTo(ref SpanWriter writer, OrderedHashSet<string> strings, ref int entries, ref int switches)
{
writer.WriteAscii($"{{ body {Body} }}");
}
}
19 changes: 19 additions & 0 deletions Projects/Server/Gumps/GumpBodyUpdate.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Server.Collections;
using System.Buffers;

namespace Server.Gumps;

public class GumpBodyUpdate : GumpEntry
{
public GumpBodyUpdate(string responseButtonId, string body)
{
Body = body;
ResponseButtonId = responseButtonId;
}
public string Body { get; }
public string ResponseButtonId { get; }
public override void AppendTo(ref SpanWriter writer, OrderedHashSet<string> strings, ref int entries, ref int switches)
{
writer.WriteAscii($"{{ bodyUpdate {ResponseButtonId} {Body} }}");
}
}
12 changes: 8 additions & 4 deletions Projects/Server/Network/Packets/IncomingPlayerPackets.cs
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,7 @@ public static void DisplayGumpResponse(NetState state, CircularBufferReader read
continue;
}

var isWebResponse = gump.UseWebRender;
var buttonExists = buttonID == 0; // 0 is always 'close'

if (!buttonExists)
Expand All @@ -370,7 +371,7 @@ public static void DisplayGumpResponse(NetState state, CircularBufferReader read
}
}

if (!buttonExists)
if (!isWebResponse && !buttonExists)
{
state.LogInfo("Invalid gump response, disconnecting...");
var exception = new InvalidGumpResponseException($"Button {buttonID} doesn't exist");
Expand All @@ -384,7 +385,7 @@ public static void DisplayGumpResponse(NetState state, CircularBufferReader read

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}");
Expand All @@ -405,7 +406,7 @@ public static void DisplayGumpResponse(NetState state, CircularBufferReader read

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}");
Expand Down Expand Up @@ -440,7 +441,10 @@ public static void DisplayGumpResponse(NetState state, CircularBufferReader read
textEntries[i] = new TextRelay(entryID, text);
}

state.RemoveGump(gump);
if (!isWebResponse)
{
state.RemoveGump(gump);
}

var prof = GumpProfile.Acquire(gump.GetType());

Expand Down
5 changes: 5 additions & 0 deletions Projects/Server/Network/Packets/OutgoingGumpPackets.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,11 @@ public static void SendDisplayGump(this NetState ns, Gump gump, out int switches

var layoutWriter = new SpanWriter(_layoutBuffer);

if (gump.UseWebRender)
{
layoutWriter.Write(Gump.WebRender);
}

if (!gump.Draggable)
{
layoutWriter.Write(Gump.NoMove);
Expand Down
8 changes: 6 additions & 2 deletions Projects/UOContent/Commands/Object Creation/AddGump.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,14 @@ public AddGump(Mobile from, string searchString, int page, Type[] searchResults,
(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]")]
Expand Down
176 changes: 176 additions & 0 deletions Projects/UOContent/Gumps/SciterTestGump.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
using System;
using Server.Network;

namespace Server.Gumps;

public class SciterTestGump : Gump
{
public record Item(string Name, int Count);

public class Shop
{
public Item[] ShopItems { get; } = {
new("Arrow", 10),
new("Bolt", 10),
new("Gold", 20000),
};
}
private Shop _shop = new();

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, Utility.ToInt32(info.TextEntries[0].Text));
break;
}
}

}

private const string Body = @"<html>
<head>
<style>
html { background-color: black; }
h1 { color: white; }
p { color: white; }
.btn1 {
background-color: yellow;
color: black;
text-align: center;
font-size: 13px;
}

#close {
position: relative;
float: right;
}

.center {
position: relative;
float: center;
}

.close-btn {
font-size: 60px;
font-weight: bold;
color: #000;
}

.tsize
{
color: red;
font-size: 18px;
}

.myButton {
box-shadow: inset 0px 34px 0px -15px #b54b3a;
background: linear-gradient(to bottom, #a73f2d 5%, #b34332 100%);
background-color: #a73f2d;
border: 1px solid #241d13;
display: inline-block;
cursor: pointer;
color: #ffffff;
font-family: Arial;
font-size: 15px;
font-weight: bold;
padding: 9px 23px;
text-decoration: none;
text-shadow: 0px -1px 0px #7a2a1d;
}
.myButton:hover {
background: linear-gradient(to bottom, #b34332 5%, #a73f2d 100%);
background-color: #b34332;
}
.myButton:active {
position: relative;
top: 1px;
}
</style>
<script type=""module"">

document.ready = function () {}
document.onmouseleave = function(){
Window.this.xcall('GameFocus');
}
</script>
</head>
<body>
<div id=""app"" >
<a id=""close"" v-on:click=""Close()"" class=""tsize"">&#x2715;</a>
<h1 class=""center""> MUO + VueJs Demo</h1>
<ul>
<li v-for=""(item, index) in shopItems"">
<p>{{ item.Name }} amount: {{ item.Count }}
<a href=""#"" class=""myButton"" v-on:click=""Get(index)"">OK</a>
</p>
</li>
</ul>
</div>
<script src=""https://unpkg.com/vue""></script>
<script>
var app = new Vue({
el: '#app',
data: { shopItems: [] },
beforeMount: function () {
//set size
Window.this.move(100, 100, 500, 500, false);
this.getItems();
},
methods: {
getItems: function () {
Window.this.xcall('SEND', 1, function (value) {
//you can't use this now it's func
app.shopItems = value.ShopItems;
});
},
Get: function (index) {
Window.this.xcall('SEND', 2, index);
},
Close: function () {
document.body.innerHTML = """";
Window.this.state = Window.WINDOW_HIDDEN;
},
}
});
</script>
</body>
</html>";
}