From 672df23010fcf8ebe54107e6621a32a2b3d588fe Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 21 Jun 2026 19:04:22 +0200 Subject: [PATCH] =?UTF-8?q?feat(net):=20D.2b-B=20B-Wire=20=E2=80=94=20Worl?= =?UTF-8?q?dSession=20dispatch=20for=200x02CD/SetStackSize/InventoryRemove?= =?UTF-8?q?Object?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add 3 new events (PlayerIntPropertyUpdated, StackSizeUpdated, InventoryObjectRemoved) and their payload record types near the existing ObjectIntPropertyUpdated event. Add 3 switch cases in the GameMessage dispatcher immediately after the PublicUpdatePropertyInt (0x02CE) branch for: - PrivateUpdatePropertyInt (0x02CD) — no-guid player-own property - SetStackSize (0x0197) — stack count + value update - InventoryRemoveObject (0x0024) — remove from inventory view No test seam on the switch; verified by build + parser tests (Tasks 3/4/5) + live run per codebase convention (see ObjectTableWiringTests comment). Co-Authored-By: Claude Opus 4.8 (1M context) --- src/AcDream.Core.Net/WorldSession.cs | 38 ++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/AcDream.Core.Net/WorldSession.cs b/src/AcDream.Core.Net/WorldSession.cs index d00edbd9..a904140c 100644 --- a/src/AcDream.Core.Net/WorldSession.cs +++ b/src/AcDream.Core.Net/WorldSession.cs @@ -195,6 +195,25 @@ public sealed class WorldSession : IDisposable /// public event Action? ObjectIntPropertyUpdated; + /// Payload for : a PropertyInt change on + /// the player's OWN object (from PrivateUpdatePropertyInt 0x02CD — no guid on the wire). + public readonly record struct PlayerIntPropertyUpdate(uint Property, int Value); + + /// Fires when the session parses a PrivateUpdatePropertyInt (0x02CD) — one + /// PropertyInt updated on the player. B-Wire routes EncumbranceVal (5) to the burden bar. + public event Action? PlayerIntPropertyUpdated; + + /// Payload for : SetStackSize (0x0197) — a stack's + /// count + value after a merge / split. + public readonly record struct StackSizeUpdate(uint Guid, int StackSize, int Value); + + /// Fires when the session parses a SetStackSize (0x0197) top-level GameMessage. + public event Action? StackSizeUpdated; + + /// Fires when the session parses an InventoryRemoveObject (0x0024) — the guid left + /// the player's inventory view. + public event Action? InventoryObjectRemoved; + /// /// Fires when the server sends a PlayerTeleport (0xF751) game message, /// signalling that the player is entering portal space. The uint payload @@ -958,6 +977,25 @@ public sealed class WorldSession : IDisposable ObjectIntPropertyUpdated?.Invoke( new ObjectIntPropertyUpdate(p.Value.Guid, p.Value.Property, p.Value.Value)); } + else if (op == PrivateUpdatePropertyInt.Opcode) + { + var p = PrivateUpdatePropertyInt.TryParse(body); + if (p is not null) + PlayerIntPropertyUpdated?.Invoke( + new PlayerIntPropertyUpdate(p.Value.Property, p.Value.Value)); + } + else if (op == SetStackSize.Opcode) + { + var p = SetStackSize.TryParse(body); + if (p is not null) + StackSizeUpdated?.Invoke( + new StackSizeUpdate(p.Value.Guid, p.Value.StackSize, p.Value.Value)); + } + else if (op == InventoryRemoveObject.Opcode) + { + var p = InventoryRemoveObject.TryParse(body); + if (p is not null) InventoryObjectRemoved?.Invoke(p.Value.Guid); + } else if (op == GameEventEnvelope.Opcode) { // Phase F.1: 0xF7B0 is the GameEvent envelope. Parse the