Init Homebase
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
---
|
||||
date: 2026-06-02
|
||||
type: session
|
||||
tags: [session, dots, netcode, home-base, rpc, ghost, m5, m4]
|
||||
permalink: gamevault/07-sessions/2026/2026-06-02-m5-homebase-baselayer
|
||||
---
|
||||
|
||||
# Session 2026-06-02 — M5: home-base base-layer + shared storage
|
||||
|
||||
## Goal
|
||||
|
||||
Close out M4 and take the next milestone via `/dots-dev`. Operator closed **M4** (multi-client co-op validated via Unity **Multiplayer Play Mode** — two controllable characters in-scene; full handshake not exercised end-to-end, Relay still deferred). For **M5**, clarified what "home base" means for this game and built the operator-chosen **Option B**: a fixed Base Anchor + planar build-grid coordinate space + spawn re-root, **plus** one shared storage container ghost (deposit/withdraw via RPC). Locked in [[DR-008_M5_HomeBase_BaseLayer_Storage]].
|
||||
|
||||
## Process
|
||||
|
||||
- **Scoping research workflow** (4 parallel readers → synthesis): design/genre meaning, DOTS/Netcode subscene+streaming feasibility, codebase scene state, persistence/world-arch → a grounded "home base" definition + 3 scoped options (A/B/C). Operator picked **B**; grid **1.0u × 32²** planar; storage = **(itemId, count)**; persistence = in-session only (no disk); one shared base; manifest reconcile folded in.
|
||||
- **Design/verify workflow** (3 parallel → I synthesized the plan): extracted exact in-repo templates (RPC `GoInGameRequest`, `StatModifier` ghost buffer, `UpgradePickup` server-spawned interpolated ghost, ring spawn, baked-singleton bakers); **context7 was unreachable** so Netcode 1.13.2 shapes were verified by reflection on the installed assemblies + the project's own proven usages; locked the deterministic grid math.
|
||||
- **Implementation** (sequential via MCP `create_script`/`apply_text_edits` — single editor, domain-reload-ordered; NOT a parallel swarm): components+math → tests → server systems+spawn re-root → client send → authoring → prefab/subscene wiring → runtime validation.
|
||||
|
||||
## Done
|
||||
|
||||
- **New (`ProjectM.Simulation/HomeBase`):** `BaseAnchor`; `BaseGridMath` (WorldToCell/CellToWorld/IsCellInPlot/IsPointInPlot/ClampCell/PlotCenter — corner-origin, center-returning, half-open, floor); `StorageEntry` (`[GhostField]` buffer, ownerless); `SharedStorageContainer` tag; `StorageSpawner`; `StorageOpRequest` + `StorageOp` byte consts; `StorageMath` (deposit-merge / withdraw-clamp-drop).
|
||||
- **New (`ProjectM.Server/HomeBase`):** `SharedStorageSpawnSystem` (one-shot, spawns the container ghost at `CellToWorld(cell)`); `StorageOpReceiveSystem` (server RPC apply via `StorageMath`, singleton container, outside the predicted loop).
|
||||
- **New (`ProjectM.Client/HomeBase`):** `StorageOpSendSystem` (managed `SystemBase`; E/Q keyboard edge + editor-only `Deposit`/`Withdraw` statics → `StorageOpRequest` RPC to the server connection).
|
||||
- **New (`ProjectM.Authoring/HomeBase`):** `BaseAnchorAuthoring` (bakes `BaseAnchor` from the GameObject position + plot gizmo); `SharedStorageContainerAuthoring`; `StorageSpawnerAuthoring`.
|
||||
- **Modified:** `GoInGameServerSystem` — spawn ring re-rooted on `BaseGridMath.PlotCenter(BaseAnchor)` with a `TryGetSingleton` fallback. `Packages/manifest.json` — stale 6.6-era pins reconciled to the resolved 6.4.7 lock.
|
||||
- **Assets:** `Storage.prefab` (duplicated from `UpgradePickup.prefab` → swapped to `SharedStorageContainerAuthoring`, kept the ownerless-interpolated `GhostAuthoringComponent`). `Gameplay.unity` subscene — added `BaseAnchor` (at (0,1,0)) + `StorageSpawner` (→ Storage.prefab, cell (19,19)) authoring GameObjects.
|
||||
- **Tests:** `BaseGridMathTests` (7) + `StorageMathTests` (8). **EditMode 62/62.**
|
||||
|
||||
## Validation
|
||||
|
||||
- **EditMode 62/62 green** (+15 vs M5b's 47).
|
||||
- **Runtime (single in-editor client, 6.4.7):** `BaseAnchor` baked **identically into both worlds**; player **spawn re-rooted** onto the anchor (spawned at (2.5,1,0)); storage ghost **server-spawned + replicated** to the client at (3.5,1,3.5) = `CellToWorld(19,19)`; **deposit (1×5, 2×3)** then **withdraw (decrement + clamp + drop-empty)** → **server == client buffer** every time, driven through the real RPC→server→replication path; RPCs survived the tick-batching artifact. Console clean of code/Burst/ghost/RPC errors — only the known unfocused-editor tick-batching warning.
|
||||
|
||||
## Decisions
|
||||
- [[DR-008_M5_HomeBase_BaseLayer_Storage]] — home base = baked ghost-free `BaseAnchor` + locked deterministic `BaseGridMath` grid (M6 builds on it) + spawn re-root + one ownerless-interpolated shared-storage ghost mutated by a server-authoritative RPC (singleton-resolved, byte op, outside the predicted loop). Streaming + disk persistence deferred.
|
||||
|
||||
## Diagnosis notes (for future me)
|
||||
- **`execute_code` runs as a method body** — no `using` directives allowed (they parse as statements → "Identifier expected"); **fully-qualify** all types (`Unity.Entities.World`, `ProjectM.Simulation.BaseAnchor`, …).
|
||||
- **Ownerless interpolated ghost ≠ owner-predicted ghost for buffer replication:** a server-spawned ownerless chest needs **no `OwnerSendType`/`GhostOwner`** — `[GhostField]` alone replicates server mutations to all. `OwnerSendType.All` (per `StatModifier`) is only for the predicting *owner* to recompute.
|
||||
- **RPC > predicted InputEvent for one-off shared-state actions:** reliable delivery meant deposit/withdraw landed even while the editor tick-batched (the M2 one-shot `Fire` InputEvent drops under batching).
|
||||
- **The editor hung mid-session** (unresponsive bridge: queued commands accepted, pings unanswered) while unfocused — Edit-mode throttles to near-idle when the window lacks OS focus (`Application.runInBackground` only helps in Play mode). Operator **restarted the editor**; it recovered clean. Avoid piling `refresh_unity` calls onto a blocked main thread; wait or ask to focus/restart.
|
||||
- **`scope=all force` refresh is heavy** — fine on a fresh editor, but it (plus an unfocused throttle) likely contributed to the hang. Prefer `scope=scripts` for code-only changes.
|
||||
|
||||
## Open / deferred
|
||||
- **Option C** (base/expedition subscene split + async `SceneSystem` streaming) — own world-architecture milestone; M6/M7 don't need it.
|
||||
- **Disk persistence** — nothing to save until M6 produces structures; thin host-only slice afterward.
|
||||
- **Storage polish** — proximity gate (container has `HitRadius`), real item/UI model, multi-writer ordering beyond first-come.
|
||||
- **Multi-client storage** — validate two clients see identical shared state (pairs with the deferred M5b multi-client interpolation + M4 two-build tests).
|
||||
|
||||
## Next
|
||||
Begin **M6 — server-authoritative grid build placement via RPC**, reusing `BaseGridMath` (legality + snap) and the runtime-ghost-into-base-cell spawn path from this slice.
|
||||
Reference in New Issue
Block a user