acdream/docs/research/2026-06-18-item-object-model-handoff.md
Erik 5b568d000a docs(D.5): sub-phase ledger + item-model cold-start prompt
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>
2026-06-18 10:41:08 +02:00

120 lines
7.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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**:
- `EnrichItem` is **enrich-existing-only**: it updates an item ONLY if it was already seeded
as a stub (from `PlayerDescription` at login). A `CreateObject` for 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* (0x02CD0x02DA)` | 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 catalog
- `docs/research/2026-06-16-ui-item-slot-icon-dragdrop-spine-deep-dive.md``ClientObjMaintSystem`,
`ServerSaysMoveItem`, the resolve-by-guid model
- `docs/research/deepdives/r06-items-inventory.md` — the item/container property model
- `docs/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 state
- `claude-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`**,
> then `docs/research/2026-06-16-ui-item-slot-icon-dragdrop-spine-deep-dive.md` and
> `docs/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.EnrichItem` only fills items pre-seeded as stubs
> from `PlayerDescription`, and DROPS `CreateObject`s for anything else, so most hotbar/pack
> items render no icon (4 of 6 hotbar slots were blank). Port retail's `ClientObjMaintSystem`:
> **`CreateObject` is 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 `EnrichItem` to 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 — the `WorldEntity` 3D system (fed by
> `GameWindow.OnLiveEntitySpawned`) and `ItemRepository` — 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 branch `claude/hopeful-maxwell-214a12` (kept, unmerged;
> D.5.2 = `52306d9..fb288ad`).
**MEMORY.md index line:**
- [Handoff: client object/item data model (2026-06-18)](research/2026-06-18-item-object-model-handoff.md) — 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.