From c5e35c9b6954e168e6bbfef040871448c8ef515a Mon Sep 17 00:00:00 2001
From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com>
Date: Sun, 12 Sep 2021 22:23:15 -0700
Subject: [PATCH] fix: Uses client bug to make addon containers work (#776)
* Fixes tooltip for container furniture so it works. This doesn't work on ClassicUO.
* Fixes double click opening container furniture by double clicking the addon component.
* Fixes the context menu not showing up sometimes on the addon piece.
Note: You cannot drop anything into the addon component since it might be far away and it is not a real container. There is no easy fix for this without building an entire custom container class for addons or changing how items drag/drop entirely. Requires closing/opening container gumps as it switches from one component to another that shares the same content. Also requires sharing tooltips, invalidated properties, process delta changes, etc.
Not worth the effort.
---
Projects/Server/Items/Container.cs | 2 +-
Projects/Server/Items/Item.cs | 50 +++++++++----------
Projects/UOContent/Gumps/AdminGump.cs | 44 ++++++++--------
.../UOContent/Items/Addons/AddonComponent.cs | 12 +++--
.../Items/Addons/AddonContainerComponent.cs | 26 ++++++++--
.../Items/Addons/ArcaneBookshelfEastAddon.cs | 16 +++---
.../Items/Addons/BaseAddonContainer.cs | 17 +++++++
.../UOContent/Items/Containers/Container.cs | 23 +--------
8 files changed, 104 insertions(+), 86 deletions(-)
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)
{