feat(ecology): F4 — natural nodes over AoI + protocol bump (20) #256

Merged
panda merged 7 commits from feat/ecology-f4 into main 2026-08-02 14:30:59 +02:00
Collaborator

Summary

F4 of the ecology foundation (epic #250, slice #251; on F1 #252 + F2 #253 + F3a #254): natural nodes now travel to clients over the area of interest. A player near a materialized chunk receives its pine/rock nodes — spawn on enter AoI, remove on leave — the spawner generating each chunk lazily on first observation.

  • Wire (Shared/Protocol): NaturalNodeState DTO + NaturalNodeSpawned/NaturalNodeRemoved messages; ProtocolVersion 19 → 20.
  • AoI: WorldTick, per observer per tick, calls World.EnsureChunksInView (lazy generation of the AoI's chunks) then reconciles nearby nodes via InterestManagerexactly the ground-item path (id-keyed enter/left, from authoritative anchor cells, only within AoiRadius). Server reads: NaturalNodeRegistry.Within/StatesWithin, EcologySpawner.EnsureChunksInView (World.cs stays delegation-only).
  • Client stores nodes in ClientWorld.Nodes via two dispatcher cases — no rendering (that is F5).

Owner-agreed deferrals: NaturalNodeChanged → the harvest slice (baseline stages are terminal, so no node changes stage in F4); the big-node AoI rule → with multi-cell footprint (F4 nodes are 1×1).

⚠️ Follow-up surfaced by the review — nodes are not yet physical (issue #255)

F4 transports each node's BlocksWalk/BlocksSight, but movement + line-of-sight still consult only the map, never the node registry — so a tree is walk-through/see-through server-side. Harmless while nodes are invisible, but due before F5 renders them. Tracked as #255 and flagged in docs/architecture.md.

How it was tested

  • Unit: protocol round-trip (+ camelCase discriminator); NaturalNodeRegistry.Within; EcologySpawner.EnsureChunksInView (AoI chunk coverage) + World.NaturalNodesWithin; InterestManager node reconcile (entered-once / left-on-leave).
  • WebSocket integration (CreateWebSocketClient): a player seeded on a real all-grass field connects and receives a NaturalNodeSpawned with the pine art (snowy_pine, blocks) — a genuine end-to-end AoI assertion (the legacy map's spawn is a redwood biome, so the test targets a verified grass patch; deterministic, not flaky).
  • Whole solution builds 0 warnings; CSharpier 509 files clean; check-doc-refs resolves; full dotnet test green (GameServer.Tests 340, Shared 177, Client.Core 194, …).
  • Built subagent-driven (TDD per task) + a whole-branch opus review: ready to merge — no Critical/Important-blocking; the one Important is the forward-looking collision gap (#255), the Minors are the harvest change-tracking note (added) + accepted friends-scale perf.

Screenshots: N/A — nodes are stored client-side but not drawn (render is F5). First visible nodes come after F5 (and after the collision follow-up #255).

Checklist

  • just lint (CSharpier + analyzers, 0 warnings)
  • just test green (whole solution)
  • Whole solution builds
  • check-doc-refs green
  • ProtocolVersion bumped in the same change (20)
  • World.cs delegation-only; single-threaded; InterestManager node set under its lock
  • Tests added (unit + WebSocket integration)
  • Linked #251 (epic #250); follow-up #255
## Summary **F4 of the ecology foundation** (epic #250, slice #251; on F1 #252 + F2 #253 + F3a #254): natural nodes now **travel to clients over the area of interest**. A player near a materialized chunk receives its pine/rock nodes — spawn on enter AoI, remove on leave — the spawner generating each chunk **lazily on first observation**. - **Wire** (`Shared/Protocol`): `NaturalNodeState` DTO + `NaturalNodeSpawned`/`NaturalNodeRemoved` messages; **`ProtocolVersion` 19 → 20**. - **AoI**: `WorldTick`, per observer per tick, calls `World.EnsureChunksInView` (lazy generation of the AoI's chunks) then reconciles nearby nodes via `InterestManager` — **exactly the ground-item path** (id-keyed enter/left, from authoritative anchor cells, only within `AoiRadius`). Server reads: `NaturalNodeRegistry.Within`/`StatesWithin`, `EcologySpawner.EnsureChunksInView` (`World.cs` stays delegation-only). - **Client** stores nodes in `ClientWorld.Nodes` via two dispatcher cases — **no rendering** (that is F5). **Owner-agreed deferrals:** `NaturalNodeChanged` → the **harvest** slice (baseline stages are terminal, so no node changes stage in F4); the big-node AoI rule → with multi-cell footprint (F4 nodes are 1×1). ### ⚠️ Follow-up surfaced by the review — nodes are not yet *physical* (issue #255) F4 transports each node's `BlocksWalk`/`BlocksSight`, but movement + line-of-sight still consult only the map, never the node registry — so a tree is walk-through/see-through server-side. Harmless while nodes are invisible, but **due before F5 renders** them. Tracked as **#255** and flagged in `docs/architecture.md`. ## How it was tested - **Unit:** protocol round-trip (+ camelCase discriminator); `NaturalNodeRegistry.Within`; `EcologySpawner.EnsureChunksInView` (AoI chunk coverage) + `World.NaturalNodesWithin`; `InterestManager` node reconcile (entered-once / left-on-leave). - **WebSocket integration (`CreateWebSocketClient`):** a player seeded on a real all-grass field connects and **receives a `NaturalNodeSpawned` with the pine art** (`snowy_pine`, blocks) — a genuine end-to-end AoI assertion (the legacy map's spawn is a redwood biome, so the test targets a verified grass patch; deterministic, not flaky). - Whole solution **builds 0 warnings**; CSharpier **509 files** clean; `check-doc-refs` resolves; **full `dotnet test` green** (GameServer.Tests 340, Shared 177, Client.Core 194, …). - Built **subagent-driven** (TDD per task) + a **whole-branch opus review: ready to merge** — no Critical/Important-blocking; the one Important is the forward-looking collision gap (#255), the Minors are the harvest change-tracking note (added) + accepted friends-scale perf. **Screenshots:** N/A — nodes are stored client-side but **not drawn** (render is F5). First *visible* nodes come after F5 (and after the collision follow-up #255). ## Checklist - [x] `just lint` (CSharpier + analyzers, 0 warnings) - [x] `just test` green (whole solution) - [x] Whole solution builds - [x] `check-doc-refs` green - [x] `ProtocolVersion` bumped in the same change (20) - [x] `World.cs` delegation-only; single-threaded; `InterestManager` node set under its lock - [x] Tests added (unit + WebSocket integration) - [x] Linked #251 (epic #250); follow-up #255
panda merged commit 82b00d568a into main 2026-08-02 14:30:59 +02:00
panda deleted branch feat/ecology-f4 2026-08-02 14:30:59 +02:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
marco/IsoMmo!256
No description provided.