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

@ -4296,13 +4296,8 @@ namespace Server.Multis
public class SetSecureLevelEntry : ContextMenuEntry
{
private readonly Item m_Item;
private ISecurable m_Securable;
public SetSecureLevelEntry(Item item, ISecurable securable) : base(6203, 6)
public SetSecureLevelEntry() : base(6203, 6)
{
m_Item = item;
m_Securable = securable;
}
public static ISecurable GetSecurable(Mobile from, Item item)
@ -4314,8 +4309,6 @@ namespace Server.Multis
return null;
}
ISecurable sec = null;
if (item is ISecurable securable)
{
var isOwned = item is BaseDoor door && house.Doors.Contains(door);
@ -4332,45 +4325,50 @@ namespace Server.Multis
if (isOwned)
{
sec = securable;
return securable;
}
}
else
{
var list = house.Secures;
for (var i = 0; sec == null && i < list?.Count; ++i)
for (var i = 0; i < list?.Count; ++i)
{
var si = list[i];
if (si.Item == item)
{
sec = si;
return si;
}
}
}
return sec;
return null;
}
public static void AddTo(Mobile from, Item item, List<ContextMenuEntry> list)
public static void AddTo(Mobile from, Item item, ref PooledRefList<ContextMenuEntry> list)
{
var sec = GetSecurable(from, item);
if (sec != null)
{
list.Add(new SetSecureLevelEntry(item, sec));
list.Add(new SetSecureLevelEntry());
}
}
public override void OnClick()
public override void OnClick(Mobile from, IEntity target)
{
var sec = GetSecurable(Owner.From, m_Item);
if (target is not Item item)
{
return;
}
var sec = GetSecurable(from, item);
if (sec != null)
{
Owner.From.CloseGump<SetSecureLevelGump>();
Owner.From.SendGump(new SetSecureLevelGump(Owner.From, sec, BaseHouse.FindHouseAt(m_Item)));
from.CloseGump<SetSecureLevelGump>();
from.SendGump(new SetSecureLevelGump(from, sec, BaseHouse.FindHouseAt(item)));
}
}
}

View file

@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
using ModernUO.Serialization;
using Server.Collections;
using Server.ContextMenus;
using Server.Gumps;
@ -197,9 +197,9 @@ public partial class HouseSign : 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 (!BaseHouse.NewVendorSystem || !from.Alive || Owner?.IsAosRules != true)
{
@ -208,59 +208,55 @@ public partial class HouseSign : Item
if (Owner.AreThereAvailableVendorsFor(from))
{
list.Add(new VendorsEntry(this));
list.Add(new VendorsEntry());
}
if (Owner.VendorInventories.Count > 0)
{
list.Add(new ReclaimVendorInventoryEntry(this));
list.Add(new ReclaimVendorInventoryEntry());
}
}
private class VendorsEntry : ContextMenuEntry
{
private readonly HouseSign m_Sign;
public VendorsEntry(HouseSign sign) : base(6211) => m_Sign = sign;
public override void OnClick()
public VendorsEntry() : base(6211, 5)
{
var from = Owner.From;
}
if (!from.CheckAlive() || m_Sign.Deleted || m_Sign.Owner?.AreThereAvailableVendorsFor(from) != true)
public override void OnClick(Mobile from, IEntity target)
{
if (!from.CheckAlive() || target is not HouseSign sign || sign.Deleted || sign.Owner?.AreThereAvailableVendorsFor(from) != true)
{
return;
}
if (from.Map != m_Sign.Map || !from.InRange(m_Sign, 5))
if (from.Map != sign.Map)
{
// You must be within five paces of the house sign to use this option.
from.SendLocalizedMessage(1062429);
}
else
{
from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Vendors, from, m_Sign.Owner));
from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Vendors, from, sign.Owner));
}
}
}
private class ReclaimVendorInventoryEntry : ContextMenuEntry
{
private readonly HouseSign m_Sign;
public ReclaimVendorInventoryEntry(HouseSign sign) : base(6213) => m_Sign = sign;
public override void OnClick()
public ReclaimVendorInventoryEntry() : base(6213, 5)
{
var from = Owner.From;
}
if (m_Sign.Deleted || m_Sign.Owner == null || m_Sign.Owner.VendorInventories.Count == 0 ||
!from.CheckAlive())
public override void OnClick(Mobile from, IEntity target)
{
if (!from.CheckAlive() || target is not HouseSign sign || sign.Deleted || sign.Owner == null ||
sign.Owner.VendorInventories.Count == 0)
{
return;
}
if (from.Map != m_Sign.Map || !from.InRange(m_Sign, 5))
if (from.Map != sign.Map)
{
// You must be within five paces of the house sign to use this option.
from.SendLocalizedMessage(1062429);
@ -268,7 +264,7 @@ public partial class HouseSign : Item
else
{
from.CloseGump<VendorInventoryGump>();
from.SendGump(new VendorInventoryGump(m_Sign.Owner, from));
from.SendGump(new VendorInventoryGump(sign.Owner, 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.Mobiles;
@ -57,10 +57,10 @@ public partial class HouseTeleporter : Item, ISecurable
return true;
}
public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
public override void GetContextMenuEntries(Mobile from, ref PooledRefList<ContextMenuEntry> list)
{
base.GetContextMenuEntries(from, list);
SetSecureLevelEntry.AddTo(from, this, list);
base.GetContextMenuEntries(from, ref list);
SetSecureLevelEntry.AddTo(from, this, ref list);
}
private void Deserialize(IGenericReader reader, int version)