Roadmap: refresh the D.5.2 entry to its final shipped state (per-pixel gradient surface overload 0x004415b0; AP-43/AP-44 retired by visual verification; range 419c3ac..fb288ad). Add an explicit D.5 sub-phase ledger: D.5.4 client object/item data model (foundation, NEXT) -> D.5.3 selected-object + spell shortcuts -> window manager -> D.5.5+ core panels. Handoff doc gains a paste-ready new-session prompt. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
7.7 KiB
Handoff — the client object/item data model (next phase, post-D.5.2)
Date: 2026-06-18
From: the D.5.2 stateful-icon session (icon system SHIPPED + visually confirmed on a
live Coldeve server). This handoff frames the NEXT phase: the real item/object data model.
Status of this work: branch claude/hopeful-maxwell-214a12 (kept, not merged). D.5.2 is
complete: 52306d9..fb288ad.
0. Why this phase exists (the root cause we uncovered)
Visual-verifying D.5.2 on a live server (character Barris on Coldeve) showed 4 of 6
hotbar items render no icon. The diagnostic (icon-dump.txt, since removed) proved the
cause: those items are NOT-ENRICHED — ItemRepository.GetItem(guid) returns null
because their CreateObject was dropped.
The mechanism is acdream's scaffold item model:
EnrichItemis enrich-existing-only: it updates an item ONLY if it was already seeded as a stub (fromPlayerDescriptionat login). ACreateObjectfor an item with no pre-existing stub is silently discarded (the toolbar handoff called this out: "new-item ingestion is the inventory phase").- So only items in the login seed set get icons; everything else (most pack contents) falls on the floor. The 2 that showed (Energy Crystal, Revenant's Scythe) are wielded items the server announces up front.
This is NOT a D.5.2 bug (the icon composite is correct for every item that reaches it — confirmed: Energy Crystal's Magical gradient tint + the no-mana scroll's black edges both match retail). It is the item/object data model being a placeholder.
1. The retail model to port (the oracle)
Retail has one master object table — ClientObjMaintSystem — and CreateObject is the
canonical create/update for every object (item, creature, player). The UI never owns item
data: a hotbar slot, an inventory cell, a paperdoll slot, a vendor cell all hold a guid and
resolve it live via ClientObjMaintSystem::GetWeenieObject(guid). (Confirmed in our spine
research: "the cell never holds item data — it holds an itemID and resolves it live.")
acdream inverted this: login snapshot = source of truth, CreateObject = second-class
enrich. The fix is to flip it: CreateObject is the authoritative ingestion;
PlayerDescription / ViewContents (0x0196) / shortcuts become references + supplementary
data, not the primary seed. Every object the server tells us about is tracked; the UI
resolves by guid.
2. THE crux design question (settle this FIRST in the brainstorm)
acdream currently has two object tracks:
- the WorldEntity system (3D creatures / players / world items, fed by
CreateObject→GameWindow.OnLiveEntitySpawned→WorldEntity), and - the ItemRepository (inventory items,
src/AcDream.Core/Items/).
Retail unifies these under one ClientObjMaintSystem (every object is an ACCWeenieObject).
Decision to make: unify acdream into ONE object table (retail shape), or keep the two
tracks with a shared ingestion seam? This choice drives everything downstream (inventory,
equipment/paperdoll, vendor, trade all resolve items from whatever table wins). Think it
through up front — don't discover it halfway in.
3. Sources that feed the model (the ingestion surface to design around)
| Wire message | Role |
|---|---|
CreateObject (0xF745) |
canonical object create/update (full weenie: icon/name/type/stack/container/wielder/effects/…) |
DeleteObject (0xF747) |
remove |
PlayerDescription (0x0013) |
login snapshot: inventory + equipped + shortcuts (references; some props) |
ViewContents (0x0196) |
a container's {guid, slot} list when opened |
move events 0x0019/1A/1B, 0x0022/23, 0x019A |
re-parent (container/wield/3D) |
Public/PrivateUpdateProperty* (0x02CD–0x02DA) |
per-property live updates (D.5.2 wired 0x02CE UiEffects → icon) |
InventoryServerSaveFailed (0x00A0) |
speculative-move rollback |
4. Grounding research (already written — read before the brainstorm)
docs/research/2026-06-16-inventory-deep-dive.md— inventory panel + the wire catalogdocs/research/2026-06-16-ui-item-slot-icon-dragdrop-spine-deep-dive.md—ClientObjMaintSystem,ServerSaysMoveItem, the resolve-by-guid modeldocs/research/deepdives/r06-items-inventory.md— the item/container property modeldocs/research/2026-06-16-ui-panels-synthesis.md— core-panels build order (item-model is the prerequisite for the inventory panel)claude-memory/project_d2b_retail_ui.md— D.2b/D.5.1/D.5.2 stateclaude-memory/feedback_weenie_vs_static.md— items are server weenies, not dat-baked
5. Recommended approach
Full process (the user values it): brainstorm → spec → plan → subagent implementation. Open the brainstorm on the unify-vs-separate question (§2) first, then the ingestion lifecycle (§3), then how the UI (toolbar/inventory/paperdoll) binds by guid. This is the foundation the remaining D.5 core panels sit on — get it solid.
NOTE the user's standing constraint for this phase: "No quick fixes — needs to be
architecturally solid and thought through." Do not band-aid EnrichItem to add new items;
design the model properly.
6. New-session prompt (paste into a fresh session)
Design and build acdream's client object/item data model — the foundation under the D.5 core panels (inventory, equipment/paperdoll, vendor, trade). This is roadmap D.5.4 and it blocks D.5.5+. Read this handoff first:
docs/research/2026-06-18-item-object-model-handoff.md, thendocs/research/2026-06-16-ui-item-slot-icon-dragdrop-spine-deep-dive.mdanddocs/research/2026-06-16-inventory-deep-dive.md.The problem (confirmed live on Coldeve, character Barris): acdream's item model is enrich-existing-only —
ItemRepository.EnrichItemonly fills items pre-seeded as stubs fromPlayerDescription, and DROPSCreateObjects for anything else, so most hotbar/pack items render no icon (4 of 6 hotbar slots were blank). Port retail'sClientObjMaintSystem:CreateObjectis the canonical object create/update,PlayerDescription/ViewContents/ shortcuts become references, and the UI resolves items by guid. This is NOT a D.5.2 icon bug (the composite is correct for every item that reaches it).Do this as a proper design — the user's standing constraint is "architecturally solid, no quick fixes" (do NOT band-aid
EnrichItemto add new items). Use the full brainstorm → spec → plan → subagent-driven-development flow. Open the brainstorm by settling the crux FIRST (§2): unify acdream's two object tracks — theWorldEntity3D system (fed byGameWindow.OnLiveEntitySpawned) andItemRepository— into ONE object table like retail, or keep them separate with a shared ingestion seam? Then the ingestion lifecycle (§3 wire surface) and how the toolbar/inventory/paperdoll bind by guid. Follow the mandatory grep-named→cross-ref→pseudocode→port workflow for any AC-specific wire format; conformance tests throughout. Work continues on branchclaude/hopeful-maxwell-214a12(kept, unmerged; D.5.2 =52306d9..fb288ad).
MEMORY.md index line:
- Handoff: client object/item data model (2026-06-18) — next phase after D.5.2. Root cause of the live-Coldeve "4/6 hotbar items missing": acdream's item model is enrich-existing-only (drops CreateObjects without a pre-seeded stub). Fix = port retail's
ClientObjMaintSystem(CreateObject = canonical ingestion; UI resolves by guid). CRUX to settle first: unify the WorldEntity + ItemRepository tracks into one object table, or keep separate w/ shared ingestion? Grounding research + ingestion surface listed. User constraint: architecturally solid, no quick fixes.