neon-sprawl/docs/decomposition/modules/E3_M1_ResourceNodeAndGather...

9.4 KiB
Raw Blame History

E3.M1 — ResourceNodeAndGatherLoop

Summary

Field Value
Module ID E3.M1
Epic Epic 3 — Crafting Economy
Stage target Prototype
Status Ready — Slice 2 backlog NEO-57NEO-64 complete (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 ResourceNodeDef and ResourceYieldTable content; 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, salvage skill XP via E2.M2 grant operations.
  • Integrate with resource_node interactables in PrototypeInteractableRegistry (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).
  • GatherResult may promote to wire JSON or Protobuf when the client needs explicit gather payloads; until then, prototype uses InteractionResponse + inventory GET for verification.
  • Denials: stable reasonCode strings 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 NEO-9/NEO-41 anchor (12, 6)
prototype_subsurface_vein_beta subsurface NEO-63 anchor (18, 6)
prototype_bio_mat_gamma bio NEO-63 anchor (12, 0)
prototype_urban_bulk_delta urban_bulk NEO-63 anchor (18, 0)

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.

Epic 3 Slice 2gather nodes and outputs: 46 node types, yield tables, resource_gathered, gather_node_depleted.

Interact path (NEO-63): POST …/interact on kind: resource_node delegates to GatherOperations — success grants inventory + salvage XP + depletion; denies return allowed: false + reasonCode (node_depleted, inventory_full, …). Four anchors in PrototypeInteractableRegistry. Plan: NEO-63 implementation plan; server README — Gather via interact (NEO-63).

Gather engine (NEO-62): GatherOperations.TryGatherGatherResult (success, reasonCode, grantsApplied[], remainingGathers, optional xpGrantSummary) — inventory + salvage XP + depletion commit in one orchestrated path; server-internal until promoted to wire. Plan: NEO-62 implementation plan; server README — Gather engine (NEO-62).

Gather telemetry hooks (NEO-64): comment-only resource_gathered + gather_node_depleted hook sites in GatherOperations.TryGather (TODO(E9.M1); no ingest). gather_node_depleted fires on success when remainingGathers reaches 0 — not on pre-gather depletion deny. Plan: NEO-64 implementation plan; server README — Gather telemetry hooks (NEO-64); manual QA: NEO-64.

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. Plan: NEO-61 implementation plan.

Linear backlog (decomposed): E3M1-prototype-backlog.mdE3M1-01 NEO-57 through E3M1-08 NEO-64.

Source anchors