9.9 KiB
NEO-90 — Implementation plan
Story reference
| Field | Value |
|---|---|
| Key | NEO-90 |
| Title | E5M2-04: GET /game/world/npc-behavior-definitions |
| Linear | https://linear.app/neon-sprawl/issue/NEO-90/e5m2-04-get-gameworldnpc-behavior-definitions |
| Module | E5.M2 — NpcAiAndBehaviorProfiles · Epic 5 Slice 2 · backlog E5M2-04 |
| Branch | NEO-90-npc-behavior-definitions-get |
| Precursor | NEO-89 — INpcBehaviorDefinitionRegistry + DI (Done on main) |
| Pattern | NEO-78 — GET /game/world/ability-definitions; NEO-68 — recipe definitions world GET |
| Client counterpart | None (server-only); player-visible labels/HUD land in NEO-97 / capstone NEO-98 |
Kickoff clarifications
| Topic | Question | Agent recommendation | Answer |
|---|---|---|---|
| Response array key | Top-level JSON array name? | npcBehaviors — matches content/npc-behaviors/*.json catalog envelope. |
User: npcBehaviors. |
| Manual QA doc | Add docs/manual-qa/NEO-90.md? |
Skip — server-only HTTP; Bruno + integration tests (NEO-78/89 pattern). | User: skip. |
No other blocking decisions — route path, schemaVersion 1, registry injection, row fields (all required schema fields), and frozen three-id order are specified in E5M2-04 and the E5.M2 freeze box.
Goal, scope, and out-of-scope
Goal: Expose a stable, read-only JSON endpoint that returns all three loaded prototype NPC behavior definitions for Bruno, tooling, and future client labels (NEO-97) — backed by INpcBehaviorDefinitionRegistry without duplicating catalog truth.
In scope (from Linear + E5M2-04):
GET /game/world/npc-behavior-definitionswith versioned envelope (schemaVersion1,npcBehaviorsarray).- Row fields:
id,displayName,archetypeKind,maxHp,aggroRadius,leashRadius,telegraphWindupSeconds,attackDamage,attackCooldownSeconds(all required in v1; no optional omissions). - Behaviors ordered by
idordinal, matchingGetDefinitionsInIdOrder(). - Bruno folder
bruno/neon-sprawl-server/npc-behavior-definitions/. server/README.mdroute section.- API integration tests (AAA).
Out of scope (from Linear + backlog):
- Runtime state, telegraphs, aggro, NPC instance registry (NEO-91+).
- Godot client wiring (NEO-97).
docs/manual-qa/NEO-90.md(kickoff decision).
Acceptance criteria checklist
- GET returns all three prototype behavior defs with
schemaVersion1 and stable field names. - Rows appear in ascending
idorder (ordinal). - Bruno happy GET passes in CI Bruno step.
Technical approach
-
Route:
GET /game/world/npc-behavior-definitions— parameterless read; injectINpcBehaviorDefinitionRegistryonly (notNpcBehaviorDefinitionCatalog). -
Response shape: Top-level
schemaVersion(NpcBehaviorDefinitionsListResponse.CurrentSchemaVersion= 1) plusnpcBehaviorsarray. Each row maps fromNpcBehaviorDefRow: all nine schema fields with camelCase JSON names matching existing world-definition APIs. -
Ordering: Build list from
registry.GetDefinitionsInIdOrder()(already ordinal by id). Tests assert exact id sequence (frozen three from E5.M2 freeze box):prototype_elite_mini_boss,prototype_melee_pressure,prototype_ranged_control(ordinal sort of the three ids — same order as
NpcBehaviorDefinitionRegistryTests/PrototypeNpcBehaviorRegistryconstants). -
Implementation: New
NpcBehaviorDefinitionsWorldApi+NpcBehaviorDefinitionsListDtos.csinGame/Npc/(mirrorAbilityDefinitionsWorldApi). Wireapp.MapNpcBehaviorDefinitionsWorldApi()fromProgram.csafter other world definition APIs (nearMapAbilityDefinitionsWorldApi()). -
Bruno:
bruno/neon-sprawl-server/npc-behavior-definitions/withGet npc behavior definitions.bru+folder.bru. Tests: 200, JSON,schemaVersion1,npcBehaviors.length === 3, ascending id order, exact frozen-three registry sequence, spot-checkprototype_melee_pressureandprototype_elite_mini_bossmetadata. -
Docs: Add
server/README.mdsubsection under NPC behavior catalog documenting GET + curl example. Update E5_M2 Related implementation slices and documentation_and_implementation_alignment.md E5.M2 row when landed.
Expected prototype row values (from content)
id |
displayName |
archetypeKind |
maxHp |
aggroRadius |
leashRadius |
telegraphWindupSeconds |
attackDamage |
attackCooldownSeconds |
|---|---|---|---|---|---|---|---|---|
prototype_melee_pressure |
Melee Pressure | melee_pressure |
100 | 8.0 | 16.0 | 1.5 | 15 | 3.0 |
prototype_ranged_control |
Ranged Control | ranged_control |
80 | 10.0 | 20.0 | 2.0 | 12 | 4.0 |
prototype_elite_mini_boss |
Elite Mini-Boss | elite_mini_boss |
200 | 8.0 | 18.0 | 2.5 | 25 | 5.0 |
Files to add
| Path | Purpose |
|---|---|
server/NeonSprawl.Server/Game/Npc/NpcBehaviorDefinitionsWorldApi.cs |
Map* extension registering GET route; maps registry → JSON. |
server/NeonSprawl.Server/Game/Npc/NpcBehaviorDefinitionsListDtos.cs |
Versioned response + row DTOs for JSON serialization. |
server/NeonSprawl.Server.Tests/Game/Npc/NpcBehaviorDefinitionsWorldApiTests.cs |
HTTP integration: 200, schema v1, three ids in order, spot-check rows. |
bruno/neon-sprawl-server/npc-behavior-definitions/Get npc behavior definitions.bru |
Manual / Bruno verification against dev server. |
bruno/neon-sprawl-server/npc-behavior-definitions/folder.bru |
Bruno folder metadata (match ability-definitions). |
docs/plans/NEO-90-implementation-plan.md |
This plan. |
Files to modify
| Path | Rationale |
|---|---|
server/NeonSprawl.Server/Program.cs |
Register MapNpcBehaviorDefinitionsWorldApi() alongside other game world definition APIs. |
server/README.md |
Document GET /game/world/npc-behavior-definitions, curl example, links to plan/Bruno. |
docs/decomposition/modules/E5_M2_NpcAiAndBehaviorProfiles.md |
Related implementation slices — HTTP read model bullet (NEO-90). |
docs/decomposition/modules/documentation_and_implementation_alignment.md |
E5.M2 row — note NEO-90 HTTP projection when landed. |
docs/plans/E5M2-prototype-backlog.md |
E5M2-04 acceptance checkboxes + landed note when complete. |
Tests
| File | Coverage |
|---|---|
server/NeonSprawl.Server.Tests/Game/Npc/NpcBehaviorDefinitionsWorldApiTests.cs |
Integration: GET /game/world/npc-behavior-definitions via InMemoryWebApplicationFactory; ReadFromJsonAsync; assert schemaVersion 1; npcBehaviors count 3; ordered id list equals frozen three in ordinal id order; spot-check prototype_melee_pressure (maxHp 100, attackDamage 15, archetypeKind melee_pressure) and prototype_elite_mini_boss (maxHp 200, attackDamage 25, telegraphWindupSeconds 2.5). AAA per csharp-style. |
Bruno scripts complement automated tests for manual dev-server verification. No docs/manual-qa/NEO-90.md (server-only per kickoff).
Open questions / risks
| Question / risk | Agent recommendation | Status |
|---|---|---|
| Linear blockedBy NEO-89 | Branch from main where NEO-89 is merged (confirmed at kickoff). |
adopted |
| Optional fields later | When content adds new optional behavior-def fields, bump schemaVersion or extend v1 in a follow-up issue. |
deferred |
| Client not in this story | Cross-link NEO-97 / NEO-98; Bruno is not prototype-complete per full-stack epic decomposition. | adopted |
| Numeric JSON types | Emit radii/timings as JSON number (double); HP/damage as integer; tests assert numeric equality. | adopted |
Decisions (kickoff)
npcBehaviorstop-level array key — matches content catalog envelope (user confirmed).- No manual QA doc — server-only HTTP; Bruno + automated tests (user confirmed).
- Registry-only injection — HTTP layer depends on
INpcBehaviorDefinitionRegistry, notNpcBehaviorDefinitionCatalog.
Reconciliation (implementation)
NpcBehaviorDefinitionsWorldApi+NpcBehaviorDefinitionsListDtosregistered viaMapNpcBehaviorDefinitionsWorldApi()inProgram.cs; injectsINpcBehaviorDefinitionRegistryonly.NpcBehaviorDefinitionsWorldApiTests— integration test for schema v1, frozen-three id order,prototype_melee_pressure/prototype_elite_mini_bossspot-checks.- Bruno:
bruno/neon-sprawl-server/npc-behavior-definitions/Get npc behavior definitions.bruwith response-shape tests. server/README.md, E5.M2 module doc, alignment register, and E5M2 backlog updated.