8.5 KiB
E3.M1 — ResourceNodeAndGatherLoop
Summary
| Field | Value |
|---|---|
| Module ID | E3.M1 |
| Epic | Epic 3 — Crafting Economy |
| Stage target | Prototype |
| Status | In Progress — Slice 2 backlog NEO-57–NEO-64 (E3M1-prototype-backlog; NEO-41 anchor below; see dependency register) |
| Linear | Label E3.M1 per decomposition README — Linear alignment |
Purpose
Authority: Client vs server authority — the server resolves whether a gather succeeds, what items are granted, remaining node capacity, and skill XP from gather; the client sends interact intent via E1.M3 — InteractionAndTargetingLayer (POST …/interact) and displays outcomes.
World resource nodes, gather interactions, and yield outputs feeding inventory (E3.M3) and skill XP (E2.M2). Ecology / respawn pacing per zone defers to E4.M2 — SpawnEcologyController.
Boundary: E1.M3 vs E3.M1
| Topic | E1.M3 (today) | E3.M1 (this module) |
|---|---|---|
| Primary job | Interactable eligibility (range, known id, kind) | Gather resolution: yields, depletion, inventory + XP side effects |
| Wire / HTTP | POST …/interact + InteractionResponse |
No separate gather route in prototype — E3.M1 hooks after E1.M3 allows interact |
| Registry | PrototypeInteractableRegistry / GET …/interactables |
ResourceNodeDef + ResourceYieldTable content; instance capacity store |
| Denials | out_of_range, unknown_interactable |
Adds node_depleted, inventory_full, etc. via gather engine |
Shared policy: horizontal reach on X/Z matches NEO-9 / E1.M3 — gather does not redefine range math.
Responsibilities
- Author
ResourceNodeDefandResourceYieldTablecontent; load and expose defs to server subsystems. - Track per-instance remaining gathers (prototype capacity/depletion); deny when exhausted.
- Resolve
GatherResult: item grants into E3.M3 inventory,salvageskill XP via E2.M2 grant operations. - Integrate with
resource_nodeinteractables inPrototypeInteractableRegistry(world anchors until E4.M1).
Deferred: zone spawn profiles, regen timers, probabilistic yields, cross-skill unlock nodes — gathering.md open questions.
Key contracts
| Contract | Kind | Role |
|---|---|---|
ResourceNodeDef |
Content | Node type, max gathers, gather lens, link to yield table. |
ResourceYieldTable |
Content | Fixed item outputs per gather (itemId, quantity). |
GatherResult |
Server-internal (prototype) | Success/deny, granted items, depletion snapshot, reason codes. |
Contract notes (contracts.md)
- Content defs live under
content/resource-nodes/with JSON Schema in CI (E3M1-01). GatherResultmay promote to wire JSON or Protobuf when the client needs explicit gather payloads; until then, prototype usesInteractionResponse+ inventory GET for verification.- Denials: stable
reasonCodestrings on interact deny (node_depleted,inventory_full, …) consistent with E1.M3 patterns.
Logical fields (illustrative):
| Contract | Illustrative fields |
|---|---|
ResourceNodeDef |
nodeDefId; displayName; gatherLens (consumer_salvage, subsurface, bio, urban_bulk); maxGathers — see content/resource-nodes/*_resource_nodes.json |
ResourceYieldTable |
nodeDefId; itemId; quantity — prototype: one row per node in *_resource_yields.json |
GatherResult |
success; reasonCode; grantsApplied[]; remainingGathers; optional xpGrantSummary |
Module dependencies
- E1.M3 — InteractionAndTargetingLayer (
POST …/interact, interactable descriptors). - E2.M2 — XpAwardAndLevelEngine (skill XP grant operations).
- E3.M3 — ItemizationAndInventorySchema (inventory grants) — logical dependency for Slice 2 yields; register lists E1.M3 + E2.M2 only so gather XP anchor (NEO-41) could land before inventory.
Dependents (by design)
- E3.M2 — RefinementAndRecipeExecution (crafted inputs from gathered materials).
- E4.M2 — SpawnEcologyController (respawn / ecology).
Designer note: gather lenses and yields
Prototype Slice 2 uses four nodes — one per gather lens. All prototype yields grant scrap_metal_bulk (different quantities per node are allowed) so the gather→refine loop can start without expanding the item catalog. Skill XP stays salvage + activity (10 XP) on every node until per-lens skill mapping is a deliberate content pass.
Depletion: each interactable instance has maxGathers successful collects; at zero, interact returns node_depleted. Regen on timer is out of scope for Slice 2 (E4.M2).
Prototype Slice 2 freeze (E3M1-01)
The first shipped four-node spine is frozen for downstream references (recipes, ecology, quests). nodeDefId must match interactableId in PrototypeInteractableRegistry for prototype wiring.
nodeDefId / interactableId |
gatherLens |
Notes |
|---|---|---|
prototype_resource_node_alpha |
consumer_salvage |
Existing NEO-9/NEO-41 anchor (12, −6) |
prototype_subsurface_vein_beta |
subsurface |
New anchor — plan PR sets X/Z |
prototype_bio_mat_gamma |
bio |
New anchor — plan PR sets X/Z |
prototype_urban_bulk_delta |
urban_bulk |
New anchor — plan PR sets X/Z |
Rules: Do not rename these ids after ship. CI enforces exactly four node defs and valid yield item references. Relaxing the gate belongs in a new Linear issue when the roster grows.
Related implementation slices
Epic 3 Slice 2 — gather nodes and outputs: 4–6 node types, yield tables, resource_gathered, gather_node_depleted.
Prototype implementation anchor (NEO-41): until GatherResult lands, a successful POST …/interact on kind: resource_node grants salvage skill XP only (activity, 10 XP) via SkillProgressionGrantOperations — no inventory or depletion. E3M1-07 migrates XP into the gather engine and adds item + capacity behavior (E3M1-prototype-backlog).
Resource node definitions HTTP (NEO-60): GET /game/world/resource-node-definitions — versioned read-only projection (schemaVersion 1, nodes) backed by IResourceNodeDefinitionRegistry; each row includes nested yield summary. Bruno bruno/neon-sprawl-server/resource-node-definitions/. Plan: NEO-60 implementation plan.
Resource node instance depletion store (NEO-61): IResourceNodeInstanceStore + ResourceNodeInstanceOperations — lazy-init remaining gathers from catalog maxGathers, atomic decrement, node_depleted / unknown_node reason codes; Postgres V006 or in-memory fallback. Interact wiring deferred to E3M1-07 (NEO-63). Plan: NEO-61 implementation plan.
Linear backlog (decomposed): E3M1-prototype-backlog.md — E3M1-01 NEO-57 through E3M1-08 NEO-64.
Source anchors
- Master plan:
neon_sprawl_vision.plan.md— Epic 3. - gathering.md
- Module dependency register