diff --git a/Projects/Server/Items/Container.cs b/Projects/Server/Items/Container.cs index f0dd8e630..43a2ba939 100644 --- a/Projects/Server/Items/Container.cs +++ b/Projects/Server/Items/Container.cs @@ -763,7 +763,7 @@ namespace Server.Items { if (Core.ML) { - if (ParentsContain()) // Root Parent is the Mobile. Parent could be another containter. + if (ParentsContain()) // Root Parent is the Mobile. Parent could be another container. { list.Add( 1073841, // Contents: ~1_COUNT~/~2_MAXCOUNT~ items, ~3_WEIGHT~ stones diff --git a/Projects/Server/Items/Item.cs b/Projects/Server/Items/Item.cs index cfb7e14b8..7d507b93a 100644 --- a/Projects/Server/Items/Item.cs +++ b/Projects/Server/Items/Item.cs @@ -1332,39 +1332,36 @@ namespace Server if (openers != null) { - lock (openers) + for (var i = 0; i < openers.Count; ++i) { - for (var i = 0; i < openers.Count; ++i) + var mob = openers[i]; + + var range = GetUpdateRange(mob); + + if (mob.Map != map || !mob.InRange(worldLoc, range)) { - var mob = openers[i]; - - var range = GetUpdateRange(mob); - - if (mob.Map != map || !mob.InRange(worldLoc, range)) + openers.RemoveAt(i--); + } + else + { + if (mob == rootParent || mob == tradeRecip) { - openers.RemoveAt(i--); + continue; } - else + + var ns = mob.NetState; + + if (ns != null && mob.CanSee(this)) { - if (mob == rootParent || mob == tradeRecip) - { - continue; - } - - var ns = mob.NetState; - - if (ns != null && mob.CanSee(this)) - { - ns.SendContainerContentUpdate(this); - SendOPLPacketTo(ns); - } + ns.SendContainerContentUpdate(this); + SendOPLPacketTo(ns); } } + } - if (openers.Count == 0) - { - contParent.Openers = null; - } + if (openers.Count == 0) + { + contParent.Openers = null; } } @@ -1719,6 +1716,7 @@ namespace Server } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] private bool GetFlag(ImplFlag flag) => (m_Flags & flag) != 0; public BounceInfo GetBounce() => LookupCompactInfo()?.m_Bounce; @@ -2408,7 +2406,7 @@ namespace Server } #nullable enable - public void InvalidateProperties() + public virtual void InvalidateProperties() { if (!ObjectPropertyList.Enabled) { diff --git a/Projects/UOContent/Gumps/AdminGump.cs b/Projects/UOContent/Gumps/AdminGump.cs index add8aa9ec..25777e491 100644 --- a/Projects/UOContent/Gumps/AdminGump.cs +++ b/Projects/UOContent/Gumps/AdminGump.cs @@ -2696,9 +2696,9 @@ namespace Server.Gumps { case 0: { - @from.SendGump( + from.SendGump( new AdminGump( - @from, + from, AdminGumpPage.AccountDetails_Information, 0, null, @@ -2710,9 +2710,9 @@ namespace Server.Gumps } case 1: { - @from.SendGump( + from.SendGump( new AdminGump( - @from, + from, AdminGumpPage.AccountDetails_Characters, 0, null, @@ -2724,9 +2724,9 @@ namespace Server.Gumps } case 2: { - @from.SendGump( + from.SendGump( new AdminGump( - @from, + from, AdminGumpPage.AccountDetails_Comments, 0, null, @@ -2738,23 +2738,23 @@ namespace Server.Gumps } case 3: { - @from.SendGump( - new AdminGump(@from, AdminGumpPage.AccountDetails_Tags, 0, null, null, m_State) + from.SendGump( + new AdminGump(from, AdminGumpPage.AccountDetails_Tags, 0, null, null, m_State) ); break; } case 13: { - @from.SendGump( - new AdminGump(@from, AdminGumpPage.AccountDetails_Access, 0, null, null, m_State) + from.SendGump( + new AdminGump(from, AdminGumpPage.AccountDetails_Access, 0, null, null, m_State) ); break; } case 14: { - @from.SendGump( + from.SendGump( new AdminGump( - @from, + from, AdminGumpPage.AccountDetails_Access_ClientIPs, 0, null, @@ -2766,9 +2766,9 @@ namespace Server.Gumps } case 15: { - @from.SendGump( + from.SendGump( new AdminGump( - @from, + from, AdminGumpPage.AccountDetails_Access_Restrictions, 0, null, @@ -2780,14 +2780,14 @@ namespace Server.Gumps } case 4: { - @from.Prompt = new AddCommentPrompt(m_State as Account); - @from.SendMessage("Enter the new account comment."); + from.Prompt = new AddCommentPrompt(m_State as Account); + from.SendMessage("Enter the new account comment."); break; } case 5: { - @from.Prompt = new AddTagNamePrompt(m_State as Account); - @from.SendMessage("Enter the new tag name."); + from.Prompt = new AddTagNamePrompt(m_State as Account); + from.SendMessage("Enter the new tag name."); break; } case 6: @@ -2897,9 +2897,9 @@ namespace Server.Gumps } case 8: { - @from.SendGump( + from.SendGump( new AdminGump( - @from, + from, AdminGumpPage.AccountDetails_ChangePassword, 0, null, @@ -2911,9 +2911,9 @@ namespace Server.Gumps } case 9: { - @from.SendGump( + from.SendGump( new AdminGump( - @from, + from, AdminGumpPage.AccountDetails_ChangeAccess, 0, null, diff --git a/Projects/UOContent/Items/Addons/AddonComponent.cs b/Projects/UOContent/Items/Addons/AddonComponent.cs index e7b58f8d6..6e3d64908 100644 --- a/Projects/UOContent/Items/Addons/AddonComponent.cs +++ b/Projects/UOContent/Items/Addons/AddonComponent.cs @@ -1,3 +1,5 @@ +using System.Collections.Generic; +using Server.ContextMenus; using Server.Engines.Craft; namespace Server.Items @@ -141,10 +143,7 @@ namespace Server.Items } } - public override void OnDoubleClick(Mobile from) - { - _addon?.OnComponentUsed(this, from); - } + public override void OnDoubleClick(Mobile from) => _addon?.OnComponentUsed(this, from); public override void OnLocationChange(Point3D old) { @@ -162,6 +161,11 @@ namespace Server.Items } } + public override void GetProperties(ObjectPropertyList list) => _addon?.GetProperties(list); + + public override void GetContextMenuEntries(Mobile from, List list) => + _addon?.GetContextMenuEntries(from, list); + public override void OnAfterDelete() { base.OnAfterDelete(); diff --git a/Projects/UOContent/Items/Addons/AddonContainerComponent.cs b/Projects/UOContent/Items/Addons/AddonContainerComponent.cs index 7baf0bb64..509d430ea 100644 --- a/Projects/UOContent/Items/Addons/AddonContainerComponent.cs +++ b/Projects/UOContent/Items/Addons/AddonContainerComponent.cs @@ -1,5 +1,8 @@ +using System; +using System.Buffers.Binary; using System.Collections.Generic; using Server.ContextMenus; +using Server.Network; namespace Server.Items { @@ -19,11 +22,11 @@ namespace Server.Items [SerializableField(0)] [SerializableFieldAttr("[CommandProperty(AccessLevel.GameMaster)]")] - public BaseAddonContainer _addon; + private BaseAddonContainer _addon; [SerializableField(1)] [SerializableFieldAttr("[CommandProperty(AccessLevel.GameMaster)]")] - public Point3D _offset; + private Point3D _offset; [Hue] [CommandProperty(AccessLevel.GameMaster)] @@ -65,9 +68,6 @@ namespace Server.Items } } - public override void GetContextMenuEntries(Mobile from, List list) => - _addon?.GetContextMenuEntries(from, list); - public override void OnMapChange() { if (_addon != null) @@ -76,6 +76,11 @@ namespace Server.Items } } + public override void GetProperties(ObjectPropertyList list) => _addon?.GetProperties(list); + + public override void GetContextMenuEntries(Mobile from, List list) => + _addon?.GetContextMenuEntries(from, list); + public override void OnAfterDelete() { base.OnAfterDelete(); @@ -83,6 +88,17 @@ namespace Server.Items _addon?.Delete(); } + public override void SendWorldPacketTo(NetState ns, ReadOnlySpan world = default) + { + Span buffer = stackalloc byte[OutgoingEntityPackets.MaxWorldEntityPacketLength].InitializePacket(); + var length = OutgoingItemPackets.CreateWorldItem(buffer, this); + // Use an itemid of a real container + BinaryPrimitives.WriteUInt16BigEndian(buffer[7..9], (ushort)(_addon?.ItemID ?? 0x9AB)); + ns.Send(buffer[..length]); + + base.SendWorldPacketTo(ns, world); + } + [AfterDeserialization] private void AfterDeserialization() { diff --git a/Projects/UOContent/Items/Addons/ArcaneBookshelfEastAddon.cs b/Projects/UOContent/Items/Addons/ArcaneBookshelfEastAddon.cs index 02e1c448b..ba197ed84 100644 --- a/Projects/UOContent/Items/Addons/ArcaneBookshelfEastAddon.cs +++ b/Projects/UOContent/Items/Addons/ArcaneBookshelfEastAddon.cs @@ -1,27 +1,29 @@ namespace Server.Items { [Serializable(0)] - public partial class ArcaneBookshelfEastAddon : BaseAddon + public partial class ArcaneBookshelfEastAddon : BaseAddonContainer { [Constructible] - public ArcaneBookshelfEastAddon() + public ArcaneBookshelfEastAddon() : base(0x3084) { - AddComponent(new AddonComponent(0x3084), 0, 0, 0); - AddComponent(new AddonComponent(0x3085), -1, 0, 0); + AddComponent(new AddonContainerComponent(0x3085), -1, 0, 0); } - public override BaseAddonDeed Deed => new ArcaneBookshelfEastDeed(); + public override BaseAddonContainerDeed Deed => new ArcaneBookshelfEastDeed(); + public override bool RetainDeedHue => true; + public override int DefaultGumpID => 0x107; + public override int DefaultDropSound => 0x42; } [Serializable(0)] - public partial class ArcaneBookshelfEastDeed : BaseAddonDeed + public partial class ArcaneBookshelfEastDeed : BaseAddonContainerDeed { [Constructible] public ArcaneBookshelfEastDeed() { } - public override BaseAddon Addon => new ArcaneBookshelfEastAddon(); + public override BaseAddonContainer Addon => new ArcaneBookshelfEastAddon(); public override int LabelNumber => 1073371; // arcane bookshelf (east) } } diff --git a/Projects/UOContent/Items/Addons/BaseAddonContainer.cs b/Projects/UOContent/Items/Addons/BaseAddonContainer.cs index c812ac3c5..cc94b8265 100644 --- a/Projects/UOContent/Items/Addons/BaseAddonContainer.cs +++ b/Projects/UOContent/Items/Addons/BaseAddonContainer.cs @@ -187,6 +187,19 @@ namespace Server.Items } } + public override void InvalidateProperties() + { + base.InvalidateProperties(); + + if (_components != null) + { + foreach (var component in _components) + { + component.InvalidateProperties(); + } + } + } + // Handles v0 with old Enum -> Int casting private void Deserialize(IGenericReader reader, int version) { @@ -332,6 +345,10 @@ namespace Server.Items public virtual void OnComponentUsed(AddonContainerComponent c, Mobile from) { + if (!Deleted) + { + OnDoubleClick(from); + } } } } diff --git a/Projects/UOContent/Items/Containers/Container.cs b/Projects/UOContent/Items/Containers/Container.cs index d2d57ef38..872bc6d77 100644 --- a/Projects/UOContent/Items/Containers/Container.cs +++ b/Projects/UOContent/Items/Containers/Container.cs @@ -16,28 +16,9 @@ namespace Server.Items { } - public override int DefaultMaxWeight - { - get - { - if (IsSecure) - { - return 0; - } + public override int DefaultMaxWeight => IsSecure ? 0 : base.DefaultMaxWeight; - return base.DefaultMaxWeight; - } - } - - public override bool IsAccessibleTo(Mobile m) - { - if (!BaseHouse.CheckAccessible(m, this)) - { - return false; - } - - return base.IsAccessibleTo(m); - } + public override bool IsAccessibleTo(Mobile m) => BaseHouse.CheckAccessible(m, this) && base.IsAccessibleTo(m); public override bool CheckHold(Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight) {