feat: Moves gumps out of the core (#1916)
> [!Important] > **Developer Note** > This code change will **completely move gumps out of the core** ### Summary - Adds `GetGumps()` convenience which exposes methods to Find/Close/Send multiple gumps. This helper is a performance improvement by eliminating the Dictionary<Player, List> lookup for gumps.
This commit is contained in:
parent
40d99f6d1c
commit
8282b00ca2
246 changed files with 1722 additions and 1383 deletions
198
Projects/UOContent/Gumps/Base/GumpSystem.IncomingPackets.cs
Normal file
198
Projects/UOContent/Gumps/Base/GumpSystem.IncomingPackets.cs
Normal file
|
|
@ -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 <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
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<int> switchBlock =
|
||||
MemoryMarshal.Cast<byte, int>(reader.Buffer.Slice(reader.Position, switchByteCount));
|
||||
|
||||
reader.Seek(switchByteCount, SeekOrigin.Current);
|
||||
|
||||
scoped ReadOnlySpan<int> switches;
|
||||
|
||||
// Swap the endianness if necessary
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
Span<int> 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<ushort> textIds = stackalloc ushort[textCount];
|
||||
Span<Range> 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<PlayerMobile>((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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue