fix: Fix NetStateGumps and other Gumps cleanup (#1919)

This commit is contained in:
Stefano Merotta 2024-08-10 18:57:28 +02:00 committed by GitHub
parent 8282b00ca2
commit 6fe01488ef
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 73 additions and 158 deletions

View file

@ -244,7 +244,7 @@ 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}.");
foreach (var g in m_Challenger.GetAllGumps())
foreach (var g in m_Challenger.GetGumps())
{
if (g is ParticipantGump pg && pg.Participant == m_Participant)
{

View file

@ -1541,7 +1541,7 @@ namespace Server.Engines.ConPVP
p.Nullify(pl);
pm.DuelPlayer = null;
foreach (var g in init.GetAllGumps())
foreach (var g in init.GetGumps())
{
if (g is ParticipantGump pg && pg.Participant == p)
{
@ -1576,7 +1576,7 @@ namespace Server.Engines.ConPVP
var send = true;
foreach (var g in init.GetAllGumps())
foreach (var g in init.GetGumps())
{
if (g is ParticipantGump pg && pg.Participant == p)
{
@ -1620,7 +1620,7 @@ namespace Server.Engines.ConPVP
var send = true;
foreach (var g in init.GetAllGumps())
foreach (var g in init.GetGumps())
{
if (g is ParticipantGump pg && pg.Participant == p)
{

View file

@ -37,15 +37,18 @@ public static partial class GumpSystem
BaseGump baseGump = null;
foreach (var g in GetAll(state))
if (_gumps.TryGetValue(state, out var gumps))
{
if (g.Serial != serial || g.TypeID != typeId)
foreach (var g in gumps)
{
continue;
}
if (g.Serial != serial || g.TypeID != typeId)
{
continue;
}
baseGump = g;
break;
baseGump = g;
break;
}
}
if (baseGump != null)

View file

@ -13,8 +13,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
using Server.Gumps.Base;
using Server.Logging;
using Server.Network;
using System;
using System.Collections.Generic;
@ -26,11 +24,9 @@ namespace Server.Gumps;
public static partial class GumpSystem
{
private const int GumpCap = 512;
private const int InitialCapacity = 4;
public const int GumpCap = 512;
private static readonly Dictionary<NetState, List<BaseGump>> _gumps = [];
private static readonly ILogger _logger = LogFactory.GetLogger(typeof(GumpSystem));
public static unsafe void Configure()
{
@ -47,51 +43,7 @@ public static partial class GumpSystem
}
}
private static ReadOnlySpan<BaseGump> GetAll(NetState ns) =>
_gumps.TryGetValue(ns, out var gumps) ? CollectionsMarshal.AsSpan(gumps) : [];
private static T Find<T>(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<BaseGump>(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 T Find<T>(NetState ns) where T : BaseGump => ns != null ? Get(ns).Find<T>() : null;
private static void Remove(NetState ns, BaseGump gump)
{
@ -108,26 +60,6 @@ public static partial class GumpSystem
}
}
private static bool Remove<T>(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
@ -135,62 +67,16 @@ public static partial class GumpSystem
return;
}
ref List<BaseGump> 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);
Get(ns).Send(gump, singleton);
}
private static bool Close<T>(NetState ns) where T : BaseGump
{
if (Remove<T>(ns, out var gump))
{
ns.SendCloseGump(gump.TypeID, 0);
gump.OnServerClose(ns);
return true;
}
return false;
}
private static readonly List<BaseGump> _emptyList = [];
private static bool Close<T>(NetState ns) where T : BaseGump => ns != null && Get(ns).Close<T>();
private static NetStateGumps Get(NetState ns)
{
if (ns == null)
{
return new NetStateGumps(_emptyList, null);
return new NetStateGumps(null, null);
}
ref List<BaseGump> list = ref CollectionsMarshal.GetValueRefOrAddDefault(_gumps, ns, out bool exists);
@ -231,13 +117,6 @@ public static partial class GumpSystem
Send(m.NetState, g, singleton);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ReadOnlySpan<BaseGump> GetAllGumps([DisallowNull] this Mobile m)
{
ArgumentNullException.ThrowIfNull(m);
return GetAll(m.NetState);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static NetStateGumps GetGumps([DisallowNull] this Mobile m)
{
@ -253,10 +132,10 @@ public static partial class GumpSystem
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SendGump([DisallowNull] this NetState ns, BaseGump g, bool singleton = false)
public static T FindGump<T>([DisallowNull] this NetState ns) where T : BaseGump
{
ArgumentNullException.ThrowIfNull(ns);
Send(ns, g, singleton);
return Find<T>(ns);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -267,17 +146,10 @@ public static partial class GumpSystem
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ReadOnlySpan<BaseGump> GetAllGumps([DisallowNull] this NetState ns)
public static void SendGump([DisallowNull] this NetState ns, BaseGump g, bool singleton = false)
{
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);
Send(ns, g, singleton);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]

View file

@ -1,10 +1,31 @@
using Server.Network;
using System.Collections.Generic;
/*************************************************************************
* ModernUO *
* Copyright 2019-2023 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: NetStateGumps.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/>. *
*************************************************************************/
namespace Server.Gumps.Base;
using Server.Logging;
using Server.Network;
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Server.Gumps;
public readonly ref struct NetStateGumps
{
private static readonly ILogger _logger = LogFactory.GetLogger(typeof(NetStateGumps));
private readonly List<BaseGump> _gumps;
private readonly NetState _state;
@ -16,7 +37,7 @@ public readonly ref struct NetStateGumps
public bool Close<T>() where T : BaseGump
{
if (_state == null || _gumps == null)
if (_state == null)
{
return false;
}
@ -38,7 +59,7 @@ public readonly ref struct NetStateGumps
public T Find<T>() where T : BaseGump
{
if (_state == null || _gumps == null)
if (_state == null)
{
return null;
}
@ -81,7 +102,18 @@ public readonly ref struct NetStateGumps
}
}
if (_gumps.Count >= GumpSystem.GumpCap)
{
_logger.Information("Exceeded gump cap, disconnecting...");
_state.Disconnect("Exceeded gump cap.");
return;
}
_gumps.Add(gump);
gump.SendTo(_state);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ReadOnlySpan<BaseGump>.Enumerator GetEnumerator() =>
((ReadOnlySpan<BaseGump>)CollectionsMarshal.AsSpan(_gumps)).GetEnumerator();
}

View file

@ -15,7 +15,6 @@ public class PricedResurrectGump : StaticGump<PricedResurrectGump>
_healer = healer;
_price = price;
// Close this gump when
TypeID = GetTypeId(typeof(ResurrectGump));
}
@ -101,8 +100,8 @@ public class PricedResurrectGump : StaticGump<PricedResurrectGump>
if (Banker.Withdraw(from, _price))
{
// ~1_AMOUNT~ gold has been withdrawn from your bank box.
from.SendLocalizedMessage(1060398, _price.ToString());
// ~1_AMOUNT~ gold has been withdrawn from your bank to cover the price of the healing.
from.SendLocalizedMessage(1060021, _price.ToString());
// You have ~1_AMOUNT~ gold in cash remaining in your bank box.
from.SendLocalizedMessage(1060022, Banker.GetBalance(from).ToString());

View file

@ -1723,10 +1723,19 @@ namespace Server.Mobiles
public override bool Move(Direction d)
{
if (NetState != null && Alive && !NetState.CloseGump<ResurrectGump>())
if (NetState != null)
{
SendLocalizedMessage(500111); // You are frozen and cannot move.
return false;
var gumps = NetState.GetGumps();
if (Alive)
{
gumps.Close<ResurrectGump>();
}
else if (gumps.Has<ResurrectGump>())
{
SendLocalizedMessage(500111); // You are frozen and cannot move.
return false;
}
}
// var speed = ComputeMovementSpeed(d);