From 275319461ed0dc7b9695e2e395f9acf144eff85f Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 21 Jun 2026 19:05:00 +0200 Subject: [PATCH] =?UTF-8?q?feat(net):=20D.2b-B=20B-Wire=20=E2=80=94=20Obje?= =?UTF-8?q?ctTableWiring=20applies=20all=20ints=20+=20player=20int=20+=20s?= =?UTF-8?q?tack/remove?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Wire signature gains optional 3rd param `Func? playerGuid` (existing GameWindow caller `Wire(session, Objects)` still compiles — default null). - ObjectIntPropertyUpdated gate loosened: was UiEffects-only, now applies ALL PropertyInt updates on visible objects (server is the authority on object props). - PlayerIntPropertyUpdated → UpdateIntProperty(playerGuid(), ...) so live EncumbranceVal (0x02CD) updates the player's burden bar. - StackSizeUpdated → UpdateStackSize(guid, stackSize, value). - InventoryObjectRemoved → Remove(guid). - Updated class doc-comment to list all 5 wired opcodes. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/AcDream.Core.Net/ObjectTableWiring.cs | 27 +++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/AcDream.Core.Net/ObjectTableWiring.cs b/src/AcDream.Core.Net/ObjectTableWiring.cs index 463d7d9e..c94c343d 100644 --- a/src/AcDream.Core.Net/ObjectTableWiring.cs +++ b/src/AcDream.Core.Net/ObjectTableWiring.cs @@ -5,7 +5,9 @@ namespace AcDream.Core.Net; /// /// Wires WorldSession GameMessage-level object events into the client object /// table: CreateObject (0xF745) = canonical merge-upsert, DeleteObject (0xF747) -/// = evict, PublicUpdatePropertyInt (0x02CE) UiEffects = live icon re-composite. +/// = evict, PublicUpdatePropertyInt (0x02CE) = live int apply, PrivateUpdatePropertyInt +/// (0x02CD) = player int (burden), SetStackSize (0x0197) = stack count, InventoryRemoveObject +/// (0x0024) = inventory-view removal. /// Keeps object ingestion in Core.Net (pure data, no GL) and off GameWindow. /// Retail: ACCObjectMaint::CreateObject / DeleteObject (the weenie_object_table side). /// @@ -16,18 +18,35 @@ public static class ObjectTableWiring /// on . Call this BEFORE the render handler subscribes /// to EntitySpawned so the table is populated before the render path runs. /// - public static void Wire(WorldSession session, ClientObjectTable table) + public static void Wire(WorldSession session, ClientObjectTable table, Func? playerGuid = null) { ArgumentNullException.ThrowIfNull(session); ArgumentNullException.ThrowIfNull(table); session.EntitySpawned += s => table.Ingest(ToWeenieData(s)); session.EntityDeleted += d => table.Remove(d.Guid); + + // B-Wire: apply EVERY PropertyInt update on a visible object (0x02CE), not just + // UiEffects — the server is the authority on object properties. UpdateIntProperty + // stores it in the bundle and still mirrors UiEffects → the typed Effects field. session.ObjectIntPropertyUpdated += u => + table.UpdateIntProperty(u.Guid, u.Property, u.Value); + + // B-Wire: PrivateUpdatePropertyInt (0x02CD) carries no guid — it targets the + // local player. Route it to the player object so live EncumbranceVal updates the + // burden bar. (No-op if the player guid isn't wired yet.) + session.PlayerIntPropertyUpdated += u => { - if (u.Property == ClientObjectTable.UiEffectsPropertyId) - table.UpdateIntProperty(u.Guid, u.Property, u.Value); + if (playerGuid is not null) + table.UpdateIntProperty(playerGuid(), u.Property, u.Value); }; + + // B-Wire: SetStackSize (0x0197) — update the object's stack count + value. + session.StackSizeUpdated += u => table.UpdateStackSize(u.Guid, u.StackSize, u.Value); + + // B-Wire: InventoryRemoveObject (0x0024) — the object left the player's inventory + // view; drop it from the table (retail ClientUISystem removes it from maintenance). + session.InventoryObjectRemoved += guid => table.Remove(guid); } /// Translate the wire spawn into the table's merge patch.