fix: Moves ContextMenu out of core, streamlines code, fixes bugs (#1873)

## Summary
- Removes allocation of a `List<ContextMenuEntry>` every time a context menu is created.
- Moves packet/context menu creation logic out of the core
- Fixes tame entry

## BREAKING CHANGE
> [!Important]
> **Developer Note**
> ```cs
> public virtual void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
> ```
> and similar functions changed to
> ```cs
> public virtual void GetContextMenuEntries(Mobile from, ref PooledRefList<ContextMenuEntry> list)
> ```
This commit is contained in:
Kamron Batman 2024-07-20 21:33:23 -07:00 • committed by GitHub
parent bb24b330e1
commit f58117a877
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
88 changed files with 1206 additions and 1483 deletions

View file

@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using ModernUO.Serialization;
using Server.Collections;
using Server.ContextMenus;
using Server.Gumps;
using Server.Multis;
@ -191,11 +192,11 @@ public partial class DawnsMusicBox : Item, ISecurable
}
}
public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
public override void GetContextMenuEntries(Mobile from, ref PooledRefList<ContextMenuEntry> list)
{
base.GetContextMenuEntries(from, list);
base.GetContextMenuEntries(from, ref list);
SetSecureLevelEntry.AddTo(from, this, list); // Set secure level
SetSecureLevelEntry.AddTo(from, this, ref list); // Set secure level
}
public override void OnDoubleClick(Mobile from)

View file

@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
using ModernUO.Serialization;
using Server.Collections;
using Server.ContextMenus;
using Server.Gumps;
using Server.Multis;
@ -77,11 +77,11 @@ public partial class RoseOfTrinsic : Item, ISecurable
list.Add(1062925, Petals); // Petals: ~1_COUNT~
}
public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
public override void GetContextMenuEntries(Mobile from, ref PooledRefList<ContextMenuEntry> list)
{
base.GetContextMenuEntries(from, list);
base.GetContextMenuEntries(from, ref list);
SetSecureLevelEntry.AddTo(from, this, list);
SetSecureLevelEntry.AddTo(from, this, ref list);
}
private void StartSpawnTimer(TimeSpan delay)

View file

@ -1,5 +1,5 @@
using System.Collections.Generic;
using ModernUO.Serialization;
using Server.Collections;
using Server.ContextMenus;
using Server.Gumps;
using Server.Multis;
@ -24,11 +24,11 @@ public partial class TapestryOfSosaria : Item, ISecurable
public override int LabelNumber => 1062917; // The Tapestry of Sosaria
public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
public override void GetContextMenuEntries(Mobile from, ref PooledRefList<ContextMenuEntry> list)
{
base.GetContextMenuEntries(from, list);
base.GetContextMenuEntries(from, ref list);
SetSecureLevelEntry.AddTo(from, this, list);
SetSecureLevelEntry.AddTo(from, this, ref list);
}
public override void OnDoubleClick(Mobile from)

View file

@ -4,10 +4,10 @@ using System.Net;
using System.Runtime.CompilerServices;
using ModernUO.Serialization;
using Server.Accounting;
using Server.Collections;
using Server.ContextMenus;
using Server.Gumps;
using Server.Mobiles;
using Server.Network;
using Server.Regions;
using Server.Text;
@ -394,21 +394,21 @@ public partial class HouseRaffleStone : Item
}
}
public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
public override void GetContextMenuEntries(Mobile from, ref PooledRefList<ContextMenuEntry> list)
{
base.GetContextMenuEntries(from, list);
base.GetContextMenuEntries(from, ref list);
if (from.AccessLevel >= AccessLevel.Seer)
{
list.Add(new EditEntry(from, this));
list.Add(new EditEntry());
if (_currentState == HouseRaffleState.Inactive)
{
list.Add(new ActivateEntry(from, this));
list.Add(new ActivateEntry(ValidLocation(_plotBounds, _plotFacet)));
}
else
{
list.Add(new ManagementEntry(from, this));
list.Add(new ManagementEntry());
}
}
}
@ -597,70 +597,49 @@ public partial class HouseRaffleStone : Item
}
}
private class RaffleContextMenuEntry : ContextMenuEntry
private class EditEntry : ContextMenuEntry
{
protected readonly Mobile _from;
protected readonly HouseRaffleStone _stone;
public RaffleContextMenuEntry(Mobile from, HouseRaffleStone stone, int label) : base(label)
{
_from = from;
_stone = stone;
}
}
private class EditEntry : RaffleContextMenuEntry
{
public EditEntry(Mobile from, HouseRaffleStone stone) : base(from, stone, 5101) // Edit
public EditEntry() : base(5101)
{
}
public override void OnClick()
public override void OnClick(Mobile from, IEntity target)
{
if (_stone.Deleted || _from.AccessLevel < AccessLevel.Seer)
if (from.AccessLevel < AccessLevel.Seer || target is not HouseRaffleStone stone || stone.Deleted)
{
return;
}
_from.SendGump(new PropertiesGump(_from, _stone));
from.SendGump(new PropertiesGump(from, stone));
}
}
private class ActivateEntry : RaffleContextMenuEntry
private class ActivateEntry : ContextMenuEntry
{
public ActivateEntry(Mobile from, HouseRaffleStone stone) : base(from, stone, 5113) // Start
{
if (!ValidLocation(stone._plotBounds, stone._plotFacet))
{
Flags |= CMEFlags.Disabled;
}
}
public ActivateEntry(bool enabled) : base(5113) => Enabled = enabled;
public override void OnClick()
public override void OnClick(Mobile from, IEntity target)
{
if (_stone.Deleted || _from.AccessLevel < AccessLevel.Seer || !ValidLocation(_stone._plotBounds, _stone._plotFacet))
if (from.AccessLevel >= AccessLevel.Seer && target is HouseRaffleStone { Deleted: false } stone &&
ValidLocation(stone._plotBounds, stone._plotFacet))
{
return;
stone.CurrentState = HouseRaffleState.Active;
}
_stone.CurrentState = HouseRaffleState.Active;
}
}
private class ManagementEntry : RaffleContextMenuEntry
private class ManagementEntry : ContextMenuEntry
{
public ManagementEntry(Mobile from, HouseRaffleStone stone) : base(from, stone, 5032) // Game Monitor
public ManagementEntry() : base(5032)
{
}
public override void OnClick()
public override void OnClick(Mobile from, IEntity target)
{
if (_stone.Deleted || _from.AccessLevel < AccessLevel.Seer)
if (from.AccessLevel >= AccessLevel.Seer && target is HouseRaffleStone { Deleted: false } stone)
{
return;
from.SendGump(new HouseRaffleManagementGump(stone));
}
_from.SendGump(new HouseRaffleManagementGump(_stone));
}
}

View file

@ -1,9 +1,8 @@
using System;
using System.Collections.Generic;
using ModernUO.Serialization;
using Server.Collections;
using Server.ContextMenus;
using Server.Engines.Quests;
using Server.Network;
using Server.Regions;
using Server.Spells;
using Server.Targeting;
@ -116,13 +115,13 @@ public partial class BagOfSending : Item, TranslocationItem
LabelTo(from, 1060741, _charges.ToString()); // charges: ~1_val~
}
public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
public override void GetContextMenuEntries(Mobile from, ref PooledRefList<ContextMenuEntry> list)
{
base.GetContextMenuEntries(from, list);
base.GetContextMenuEntries(from, ref list);
if (from.Alive)
{
list.Add(new UseBagEntry(this, Charges > 0 && IsChildOf(from.Backpack)));
list.Add(new UseBagEntry(Charges > 0 && IsChildOf(from.Backpack)));
}
}
@ -156,30 +155,13 @@ public partial class BagOfSending : Item, TranslocationItem
private class UseBagEntry : ContextMenuEntry
{
private readonly BagOfSending _bag;
public UseBagEntry(bool enabled) : base(6189) => Enabled = enabled;
public UseBagEntry(BagOfSending bag, bool enabled) : base(6189)
public override void OnClick(Mobile from, IEntity target)
{
_bag = bag;
if (!enabled)
if (from.CheckAlive() && target is BagOfSending bag && !bag.Deleted)
{
Flags |= CMEFlags.Disabled;
}
}
public override void OnClick()
{
if (_bag.Deleted)
{
return;
}
var from = Owner.From;
if (from.CheckAlive())
{
_bag.OnDoubleClick(from);
bag.OnDoubleClick(from);
}
}
}

View file

@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
using ModernUO.Serialization;
using Server.Collections;
using Server.ContextMenus;
using Server.Engines.ConPVP;
using Server.Mobiles;
@ -97,9 +97,9 @@ public partial class BallOfSummoning : Item, TranslocationItem
LabelTo(from, 1054131, $"{_charges}\t{_petName.DefaultIfNullOrEmpty(" ")}");
}
public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
public override void GetContextMenuEntries(Mobile from, ref PooledRefList<ContextMenuEntry> list)
{
base.GetContextMenuEntries(from, list);
base.GetContextMenuEntries(from, ref list);
if (!from.Alive || RootParent != from)
{
@ -299,10 +299,8 @@ public partial class BallOfSummoning : Item, TranslocationItem
public BallEntry(BallCallback callback, int number) : base(number, 2) => _callback = callback;
public override void OnClick()
public override void OnClick(Mobile from, IEntity target)
{
var from = Owner.From;
if (from.CheckAlive())
{
_callback(from);

View file

@ -1,11 +1,10 @@
using System;
using System.Collections.Generic;
using ModernUO.Serialization;
using Server.Collections;
using Server.ContextMenus;
using Server.Factions;
using Server.Misc;
using Server.Mobiles;
using Server.Network;
using Server.Prompts;
using Server.Regions;
using Server.Spells;
@ -93,9 +92,9 @@ public partial class BraceletOfBinding : BaseBracelet, TranslocationItem
LabelTo(from, 1054000, $"{_charges}\t{_inscription.DefaultIfNullOrEmpty(" ")}");
}
public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
public override void GetContextMenuEntries(Mobile from, ref PooledRefList<ContextMenuEntry> list)
{
base.GetContextMenuEntries(from, list);
base.GetContextMenuEntries(from, ref list);
if (from.Alive && IsChildOf(from))
{
@ -326,17 +325,11 @@ public partial class BraceletOfBinding : BaseBracelet, TranslocationItem
public BraceletEntry(BraceletCallback callback, int number, bool enabled) : base(number)
{
_callback = callback;
if (!enabled)
{
Flags |= CMEFlags.Disabled;
}
Enabled = enabled;
}
public override void OnClick()
public override void OnClick(Mobile from, IEntity target)
{
var from = Owner.From;
if (from.CheckAlive())
{
_callback(from);

View file

@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
using ModernUO.Serialization;
using Server.Collections;
using Server.ContextMenus;
using Server.Engines.VeteranRewards;
using Server.Gumps;
@ -19,16 +19,16 @@ public partial class AnkhOfSacrificeComponent : AddonComponent
public override bool ForceShowProperties => ObjectPropertyList.Enabled;
public override int LabelNumber => 1027772; // Ankh of Sacrifice
public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
public override void GetContextMenuEntries(Mobile from, ref PooledRefList<ContextMenuEntry> list)
{
base.GetContextMenuEntries(from, list);
base.GetContextMenuEntries(from, ref list);
if (from is PlayerMobile mobile)
{
list.Add(new LockKarmaEntry(mobile, Addon as AnkhOfSacrificeAddon));
list.Add(new Ankhs.LockKarmaEntry(mobile.KarmaLocked));
}
list.Add(new ResurrectEntry(from, Addon as AnkhOfSacrificeAddon));
list.Add(new ResurrectEntry());
}
public static void Resurrect(PlayerMobile m, AnkhOfSacrificeAddon ankh)
@ -68,57 +68,15 @@ public partial class AnkhOfSacrificeComponent : AddonComponent
private class ResurrectEntry : ContextMenuEntry
{
private readonly AnkhOfSacrificeAddon _ankh;
private readonly Mobile _mobile;
public ResurrectEntry(Mobile mobile, AnkhOfSacrificeAddon ankh) : base(6195, 2)
public ResurrectEntry() : base(6195, 2)
{
_mobile = mobile;
_ankh = ankh;
}
public override void OnClick()
public override void OnClick(Mobile from, IEntity target)
{
if (_ankh?.Deleted != false)
if (target is AnkhOfSacrificeAddon { Deleted: false } ankh)
{
return;
}
Resurrect(_mobile as PlayerMobile, _ankh);
}
}
private class LockKarmaEntry : ContextMenuEntry
{
private readonly AnkhOfSacrificeAddon _ankh;
private readonly PlayerMobile _mobile;
public LockKarmaEntry(PlayerMobile mobile, AnkhOfSacrificeAddon ankh) : base(mobile.KarmaLocked ? 6197 : 6196, 2)
{
_mobile = mobile;
_ankh = ankh;
}
public override void OnClick()
{
if (!_mobile.InRange(_ankh.GetWorldLocation(), 2))
{
_mobile.SendLocalizedMessage(500446); // That is too far away.
}
else
{
_mobile.KarmaLocked = !_mobile.KarmaLocked;
if (_mobile.KarmaLocked)
{
// Your karma has been locked. Your karma can no longer be raised.
_mobile.SendLocalizedMessage(1060192);
}
else
{
// Your karma has been unlocked. Your karma can be raised again.
_mobile.SendLocalizedMessage(1060191);
}
Resurrect(from as PlayerMobile, ankh);
}
}
}