From 84b7d2d7cd5665f27e308e0f7d91f9e4df086960 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 13 Jul 2026 20:43:48 +0200 Subject: [PATCH] fix(ui): port live experience quality updates (#217) Parse retail PrivateUpdatePropertyInt64 and route authoritative Total/Available Experience through both local-player projections so Attributes, the level meter, and Skills refresh together. Preserve the existing retail XP curve and right-align the Total XP value. Close the user-confirmed item-give gate for #216 and record the named-retail/ACE/holtburger conformance evidence. Co-Authored-By: Codex --- docs/ISSUES.md | 62 ++++++++------ docs/plans/2026-04-11-roadmap.md | 1 + ...-13-retail-experience-update-pseudocode.md | 81 +++++++++++++++++++ src/AcDream.App/Rendering/GameWindow.cs | 3 +- .../UI/Layout/CharacterStatController.cs | 24 +++++- .../Messages/PrivateUpdatePropertyInt64.cs | 35 ++++++++ src/AcDream.Core.Net/ObjectTableWiring.cs | 32 +++++++- src/AcDream.Core.Net/WorldSession.cs | 18 +++++ src/AcDream.Core/Player/LocalPlayerState.cs | 12 +++ .../UI/Layout/CharacterSheetProviderTests.cs | 17 ++++ .../UI/Layout/CharacterStatControllerTests.cs | 13 +++ .../PrivateUpdatePropertyInt64Tests.cs | 49 +++++++++++ .../ObjectTableWiringTests.cs | 32 ++++++++ .../PlayerDescriptionParserTests.cs | 25 ++++++ .../Player/LocalPlayerStateTests.cs | 16 ++++ 15 files changed, 391 insertions(+), 29 deletions(-) create mode 100644 docs/research/2026-07-13-retail-experience-update-pseudocode.md create mode 100644 src/AcDream.Core.Net/Messages/PrivateUpdatePropertyInt64.cs create mode 100644 tests/AcDream.Core.Net.Tests/Messages/PrivateUpdatePropertyInt64Tests.cs diff --git a/docs/ISSUES.md b/docs/ISSUES.md index fb84eeb9..6738653d 100644 --- a/docs/ISSUES.md +++ b/docs/ISSUES.md @@ -44,38 +44,40 @@ Copy this block when adding a new issue: --- -## #216 — Inventory drags into the 3-D world could only drop items +## #217 — Character windows did not receive live 64-bit experience updates -**Status:** IN-PROGRESS +**Status:** IN-PROGRESS — implementation complete; connected visual gate pending **Severity:** HIGH **Filed:** 2026-07-13 -**Component:** retained UI / inventory / interaction / net +**Component:** retained UI / character sheet / net / player state -**Description:** Releasing a physical inventory item over an NPC always sent -the ground-drop path. A starter-dungeon character therefore could not hand the -exit token to the exit NPC and could not complete the dungeon. +**Description:** The Attributes window always displayed Total Experience as 0 +and an empty level-progress meter after the player earned XP. The Skills footer +also displayed Unassigned Experience as 0, preventing an accurate raise-cost +decision. The Total Experience number was centered instead of right-aligned. -**Root cause / status:** Implementation complete; connected live gate pending. -The exact `AttemptPlaceIn3D` policy and the `0x00CD` -packet builder already existed, but `GameWindow.OnUiDragReleasedOutside` -discarded the release coordinates and always called `DropToWorld`, hard-coding -`TargetId=0`. The release path now world-picks at the actual release point, -the controller executes its existing `GiveToTarget` action without optimistic -mutation, `WorldSession` sends the exact request, and PlayerDescription drives -the retail player secure-trade preference. +**Root cause / status:** acdream parsed the neighboring private/public Int32 +quality messages (`0x02CD`/`0x02CE`) but omitted retail +`PrivateUpdatePropertyInt64 (0x02CF)`. Both TotalExperience (quality 1) and +AvailableExperience (quality 2) use that message. The exact parser/event/state +path is now ported, both local-player projections are synchronized in one +wiring owner, the existing retail XP-band formula receives live data, and only +the value element `0x10000235` is explicitly right-aligned. -**Files:** `src/AcDream.App/UI/ItemInteractionController.cs`; -`src/AcDream.App/Rendering/GameWindow.cs`; -`src/AcDream.Core.Net/WorldSession.cs`. +**Files:** `src/AcDream.Core.Net/Messages/PrivateUpdatePropertyInt64.cs`; +`src/AcDream.Core.Net/WorldSession.cs`; +`src/AcDream.Core.Net/ObjectTableWiring.cs`; +`src/AcDream.Core/Player/LocalPlayerState.cs`; +`src/AcDream.App/UI/Layout/CharacterStatController.cs`. -**Research:** `docs/research/2026-07-13-retail-give-item-pseudocode.md`; -`ItemHolder::AttemptPlaceIn3D @ 0x00588600`; -`ACCWeenieObject::UIAttemptGive @ 0x0058D620`; -`CM_Inventory::Event_GiveObjectRequest @ 0x006ABB00`. +**Research:** `docs/research/2026-07-13-retail-experience-update-pseudocode.md`; +`CM_Qualities::DispatchUI_PrivateUpdateInt64 @ 0x006AEAD0`; +`ClientObjMaintSystem::Handle_Qualities__PrivateUpdateInt64 @ 0x00559000`; +`gmStatManagementUI::UpdateExperience @ 0x004F0A70`. -**Acceptance:** Drag the starter-dungeon exit token from the backpack onto the -exit NPC. ACE accepts the token, the inventory removes/decrements it only from -the authoritative server response, and the quest teleport exits the dungeon. +**Acceptance:** Earn XP while logged in. Attributes immediately shows the new +right-aligned total and red progress fill; Skills immediately shows the same +server-authoritative unassigned XP available for raises. --- @@ -8225,6 +8227,18 @@ Fixed by the A7 lighting rework, specifically A7 Fix D (`0980bea4`, `cf627933`, **Status:** DONE (2026-07-09, investigated this session). The described mechanism (live entities collapsing to one root-centered cylinder) no longer exists. `RegisterLiveEntityCollision` (`GameWindow.cs:4244`) now builds a multi-shape list via `ShadowShapeBuilder.FromSetup` — one shape per CylSphere, Sphere, and BSP-bearing Part — and registers via `RegisterMultiPart` (A6.P4 Task 7, `ca9341c2`). The retail `CSphere` and `CCylSphere` collision families were ported verbatim in `78e57581` (sphere primitive), `6ab26989` (fix #172, CCylSphere family), and `96ae2740` (fix #182, CSphere family, retires TS-45). The remaining `setup.Radius` single-cylinder path is now a deliberately-audited fallback used only when no other shape data exists. `tests/AcDream.Core.Tests/Physics/ShadowShapeBuilderShapeSourceTests.cs` covers both a multi-shape object and a live-creature case. +--- + +## #216 — Inventory drags into the 3-D world could only drop items + +**Status:** DONE (2026-07-13, `30d29450`, user-confirmed connected gate). +Dragging the starter-dungeon exit token onto its NPC now world-picks at the +actual release point, executes the retail `GiveToTarget` path without optimistic +inventory mutation, receives ACE's authoritative removal, and completes the +quest teleport out of the dungeon. + +--- +