Docs: DR-026 inventory/equipment/progression foundation + session log
DR-026 records the architecture (data-driven catalog + replicated buffers + reuse of the StatModifier/RPC machinery), the Phase 0-4 roadmap, the 7 validated decisions, and the deliberate gameplay choices (personal-harvest pivot, automation asymmetry, session-only inventory). Adds the Build-section inventory pointer to CLAUDE.md net-zero (39923 bytes, >1KB headroom) by condensing the persistence/world/HUD bullets; trimmed wording archived to the gotchas archive. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
---
|
||||
date: 2026-06-08
|
||||
type: session
|
||||
tags:
|
||||
- session
|
||||
- inventory
|
||||
- equipment
|
||||
- progression
|
||||
- items
|
||||
- netcode
|
||||
- ghostfield
|
||||
- harvesting
|
||||
- ultracode
|
||||
permalink: gamevault/07-sessions/2026/2026-06-08-inventory-equipment-progression-phase0
|
||||
---
|
||||
|
||||
# Session 2026-06-08 — Inventory · Equipment · Progression (Phase 0 backbone)
|
||||
|
||||
> Driven by `/dots-dev` in **ultracode** mode. Operator: *"Expand combat and harvesting for resources… first the
|
||||
> concept of an inventory and equipment (granting spells/affects); harvesting should require axes/pickaxes/tools;
|
||||
> this may require a progression system to be scalable — think carefully, handle scale + flexibility."*
|
||||
|
||||
## Decision & design
|
||||
|
||||
Architecture, phased roadmap, and the 7 Phase-0 decisions live in [[DR-026_Inventory_Equipment_Progression_Foundation]].
|
||||
Intake forks (one `AskUserQuestion`): **fully per-player inventory · gear-tier + crafting progression ·
|
||||
weapon-granted swappable abilities · plan + build the Phase 0 backbone**.
|
||||
|
||||
Before any code, a **5-lens adversarial design-review Workflow** (netcode/relevancy · determinism-Burst ·
|
||||
architecture-scale · economy-regression · test-strategy → synthesis) audited the design against the real code.
|
||||
Verdict **GO_WITH_CHANGES**. Key catches that changed the implementation:
|
||||
|
||||
- **Blocker (4/5 lenses):** the planned "add `RefRO<GhostOwner>` to the projectile query" would make GhostOwner a
|
||||
*required* component → the 8 existing harvest tests seed owner-less projectiles → they'd never match and **fail**,
|
||||
and the ledger-fallback never runs. **Fix:** optional cached `ComponentLookup<GhostOwner>`, query unchanged.
|
||||
- **Reachable deposit trigger required** — harvest→bag severs the build economy until deposit; the dev `#if` hook is
|
||||
not enough → added a real `G` key.
|
||||
- **Hoist** the catalog/owner-map/buffer lookups out of the per-hit sweep (stays `[BurstCompile]`).
|
||||
- **Mandatory player re-bake** (new `[GhostField]` buffer changes the ghost hash) + a **headless Play gate** (EditMode
|
||||
can't test replication; `NetCodeTestWorld` is internal).
|
||||
- **Scalability add-now:** bake `byte Tier` into `ItemDefBlob` (free re-bake later, but content-only Phase 1/2 now).
|
||||
|
||||
## What was built (code-complete, clean compile, 228/228 EditMode green)
|
||||
|
||||
**Simulation (`_Project/Scripts/Simulation/Items/`):** `ItemCategory` (byte consts), `ItemDefBlob`/`ItemDatabaseBlob`
|
||||
(ID-keyed), `ItemDatabase` (blob singleton), `InventorySlot` (`[GhostField]` `OwnerSendType.All` buffer, twin of
|
||||
`StatModifier`), `InventoryMath` (pure stack/cap/withdraw), `InventoryDepositRequest` (`IRpcCommand`). +
|
||||
`Tuning.InventoryMaxSlots=24` / `DefaultStackMax=999`.
|
||||
|
||||
**Authoring:** `ItemDefinition` SO (byte `Category`/`Tier` to dodge the MCP enum-drop + Burst-enum hazards) +
|
||||
`ItemDatabaseAuthoring` baker (mirrors `AbilityDatabaseAuthoring`). `PlayerAuthoring` now `AddBuffer<InventorySlot>`.
|
||||
|
||||
**Server:** `InventoryDepositSystem` (RPC → withdraw from bag, deposit to `ResourceLedger`, owner-map idiom,
|
||||
`ItemId==0` = deposit-all). `ResourceHarvestSystem` rerouted: owner read via optional `ComponentLookup<GhostOwner>`,
|
||||
deposit into the harvesting player's `InventorySlot` (stackMax from `ItemDatabase` if present), remainder/unresolvable
|
||||
→ ledger.
|
||||
|
||||
**Client:** `InventoryDepositSendSystem` (`G` = deposit all + `#if UNITY_EDITOR` static hook, mirrors
|
||||
`StorageOpSendSystem`). `HudSystem` folds in a read-only inventory panel (bottom-right, toggle `I`, names from the
|
||||
catalog, `G` hint) — null-safe, observe-only.
|
||||
|
||||
**Tests (`_Project/Tests/EditMode/`):** `InventoryMathTests`, `InventoryHarvestTests` (owned→bag / full-bag→ledger /
|
||||
no-matching-player→ledger), `InventoryDepositSystemTests` (specific / deposit-all / unresolvable). The 8
|
||||
`ResourceHarvestSystemTests` stay green via the genuine no-owner fallback.
|
||||
|
||||
## Play validation (done — task #9 closed)
|
||||
|
||||
Focused-editor finish completed this session:
|
||||
1. Authored 4 `ItemDefinition` assets (Aether/Ore/Biomass + Stone Pickaxe tool, id 10) under `Assets/_Project/Items/`
|
||||
and wired `ItemDatabaseAuthoring` (Items list assigned via `execute_code` to dodge the MCP ref-drop) into the
|
||||
`Gameplay` subscene; `refresh_unity scope=all force` re-baked.
|
||||
2. Headless `execute_code` Play gate (host+client), all green:
|
||||
- `ItemDatabase` baked into BOTH worlds (4 items); player ghost carries `InventorySlot` in both → **re-bake +
|
||||
handshake clean** (no ghost-hash desync).
|
||||
- Server write to the player bag (`InventoryMath.Deposit` Ore x7 + Aether x3) **replicated to the `ClientWorld`
|
||||
owner** — the proof EditMode can't make.
|
||||
- `InventoryDepositSendSystem.Deposit(0,0)` (the `G` path) **round-tripped**: server ledger ← bag, both
|
||||
inventories emptied, empty state replicated back.
|
||||
- HUD panel (`_invOpen` forced) rendered 4 rows with **catalog names** incl. `Stone Pickaxe x1` (non-resource
|
||||
lookup works).
|
||||
|
||||
## Deliberate decisions to remember (so a later session doesn't "fix" them)
|
||||
|
||||
- Manual harvest is personal-then-deposit; **automation stays base-direct** (asymmetry is intentional).
|
||||
- Inventory is **session-only** — undeposited haul is lost on Continue (Phase 3 adds `SaveData` v3).
|
||||
- Don't unify `ResourceLedger` / `SharedStorageContainer` / `InventorySlot` (separate decision); don't touch
|
||||
`SharedStorageContainer`.
|
||||
|
||||
## Next-session intent
|
||||
|
||||
Finish the focused-editor Play gate above, then **Phase 1 — Equipment slots + `EquipmentEffectSystem`** (weapon →
|
||||
`AbilityRef.Id`, gear → `StatModifier` bundle by slot `SourceId`), then **Phase 2 — tool-gated harvesting**.
|
||||
Reference in New Issue
Block a user