phase(N.4) Adjustment 6: add PartOverrides + HiddenPartsMask to WorldEntity

Resolves Adjustment 4 (Option A): WorldEntity now carries the server-
sent AnimPartChange data as PartOverrides and a HiddenPartsMask bitmask.
EntitySpawnAdapter.OnCreate populates AnimatedEntityState from these
fields at spawn time. GameWindow's CreateObject handler converts the
network-layer AnimPartChange records into lightweight PartOverride
structs.

This unblocks Task 22: the WbDrawDispatcher can now resolve per-part
GfxObj overrides and hidden-part suppression from entity state.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-05-08 15:10:22 +02:00
parent 16a36dda8f
commit 5b4fd4b61d
4 changed files with 70 additions and 14 deletions

View file

@ -992,6 +992,31 @@ behavior (does the adapter call the cache with the right args?). The
decode-byte conformance is structural: same function = same output.
Mark Task 20 ✅ structurally; no separate test file.
### Adjustment 6 (2026-05-08): Resolved Adjustment 4 — Option A (fields on WorldEntity)
**Context.** Adjustment 4 deferred the `HiddenPartsMask` + `AnimPartChanges`
plumbing decision to Task 22. Two options:
- **A**: add fields to `WorldEntity`, populate at spawn time
- **B**: thread as separate args into `EntitySpawnAdapter.OnCreate`
**Decision: Option A.** Reasoning:
1. The data is already computed at spawn time in GameWindow's CreateObject
handler — adding two fields is a 4-line change.
2. Option B would spread network-layer types across the streaming subsystem,
violating the same separation-of-concerns principle as Adjustment 2.
3. The 0xF625 ObjDescEvent (appearance update) replays through the same
spawn path, so WorldEntity fields work automatically for hot-swap updates.
**Implementation:**
- `WorldEntity` gains `PartOverrides: IReadOnlyList<PartOverride>` (default
empty) and `HiddenPartsMask: ulong` (default 0).
- `PartOverride(byte PartIndex, uint GfxObjId)` is a lightweight record struct
in Core.World that decouples from the network-layer `CreateObject.AnimPartChange`.
- `EntitySpawnAdapter.OnCreate` now calls `state.HideParts(entity.HiddenPartsMask)`
and `state.SetPartOverride(...)` for each override.
- GameWindow's CreateObject handler builds the `PartOverride[]` from the
server-sent `AnimPartChanges` list.
### Task 6 (original — kept for history)
**Files:**