9.0 KiB
E1.M3 — Prototype story backlog (InteractionAndTargetingLayer)
Working backlog for Epic 1 — Slice 3 (interaction, targeting, ability input). Decomposition and contracts: E1.M3 — InteractionAndTargetingLayer.
Labels (Linear): every issue E1.M3; add Epic 1 / Slice 3 as your team prefers.
Precursor (do not re-scope): authoritative InteractionRequest + horizontal reach = E1.M1 / NEO-9. These stories build on that policy; they do not replace NEO-9 acceptance.
Linear issues (created): attach docs/plans/NEO-*-implementation-plan.md on the same branch as code when each story starts (same pattern as NEO-18).
| Slug | Linear |
|---|---|
| E1M3-01 | NEO-23 |
| E1M3-02 | NEO-24 |
| E1M3-03 | NEO-25 |
| E1M3-04 | NEO-26 |
| E1M3-05 | NEO-27 |
Dependency graph in Linear: NEO-24, NEO-25 → blocked by NEO-23. NEO-26 → blocked by NEO-23, NEO-24. NEO-27 → blocked by NEO-24.
Story order (recommended)
| Order | Slug | Linear | Depends on |
|---|---|---|---|
| 1 | E1M3-01 | NEO-23 | E1.M1 (PositionState, HorizontalReach), NEO-9 patterns |
| 2 | E1M3-02 | NEO-24 | E1M3-01, E1.M2 (presentation only) |
| 3 | E1M3-03 | NEO-25 | E1M3-01 or parallel after NEO-9 registry read |
| 4 | E1M3-04 | NEO-26 | E1M3-01, E1M3-02 |
| 5 | E1M3-05 | NEO-27 | E1M3-02; E9.M1 when schema exists |
E1M3-01 — TargetState v1 + server selection intent
Goal: Publish a versioned server-owned TargetState and a client→server selection intent (name TBD: e.g. TargetSelectRequest) over the existing HTTP JSON prototype channel, with reasonCode denials consistent with NEO-9 / InteractionResponse.
In scope
- Server: validate intent using authoritative
PositionState+ shared horizontal XZ reach rules; stub eligible target set (static ids or scene-registered entities) until sim entities exist. - Response: current
TargetState(locked id or empty, validity, optional sequence). - Unit + integration tests; server README section for the new route(s).
Out of scope
- Protobuf wire; full entity sim; PvP gating (E6.M1) beyond a single stub deny path if needed for API shape.
- Replacing
POST …/interact— remain separate surface (E1.M3 boundary).
Acceptance criteria
- Client cannot commit a locked target the server would reject: server is source of truth for
TargetState. - Denied selection returns 200 (or agreed status) + body with required
reasonCodewhen selection is rejected (match project conventions from NEO-9). - Moving the player with the existing move APIs changes in range / out of range outcomes for target lock where range applies.
- Documented field list matches the illustrative table in E1_M3 — Key contracts (refine names in the plan PR, not silently in code only).
E1M3-02 — Client tab-target + lock UI synced to server
Goal: Tab (or agreed binding) cycles server-eligible targets in deterministic order; visual lock state matches last acknowledged TargetState.
In scope
- Godot: input → emit selection intent → apply server response; optional optimistic highlight must reconcile on deny (authority).
- Clear target (e.g. Esc) if product agrees; document binding in
client/project.godotor module README.
Out of scope
- Nearest-in-cone auto-target; sticky soft-target under latency (deferred in E1.M3).
- Hotbar /
AbilityCastRequest— that is E1.M4 once E1M3-01/02 are in place.
Acceptance criteria
- With ≥2 stub targets, tab cycles order defined in module or plan (e.g. ascending id) and wraps.
- UI or debug overlay shows server lock id (or “none”) after each successful round-trip.
- Server denial updates UI to previous or cleared state per documented policy.
E1M3-03 — InteractableDescriptor list / projection (multi-entity)
Goal: Server exposes a small, versioned list (or per-zone snapshot) of InteractableDescriptor records so the client can tab/hover interactables beyond the single NEO-9 row without duplicating registry truth in GDScript long-term.
In scope
- Extend or complement
PrototypeInteractableRegistry(or successor) so multiple entries are addressable; single JSON GET or embedded list on an existing player/session endpoint — pick one and document. - Client: consume list for proximity preview (optional) or selection id set; constants in GDScript must stay documented as duplicate-until-codegen (NEO-9 precedent) or generated from server in this story if you add a trivial export path.
Out of scope
- Full data-driven content pipeline (contracts.md content kind).
- Gather loop rewards (E3.M1).
Acceptance criteria
- ≥2 interactables in server registry; client can issue
InteractionRequestagainst each id when in range (NEO-9 path still works). - Descriptor payload includes at least: id, world anchor,
interactionRadius, kind string or enum for future branching.
E1M3-04 — SelectionEvent surface + consumer
Goal: Any change to effective target or primary interactable selection is observable as a SelectionEvent (wire or client-local mirror of server events for prototype).
In scope
- Define minimal event shape: previous, next, cause (
tab,clear,server_correction, …). - One consumer: debug panel,
print, or thin HUD widget listing last N events.
Out of scope
- Full UI prompt system; party flows (E8.M1).
Acceptance criteria
- Tab, clear, and forced server correction (if testable) each emit distinguishable cause values.
- E1.M4 can subscribe to the same bus in a follow-up without reshaping the event (document subscription point).
E1M3-05 — Slice 3 telemetry hook sites
Goal: Align with Epic 1 Slice 3 hooks: target_changed, and reserve call sites for ability_cast_requested / ability_cast_denied (latter two may no-op until E1.M4 + E5.M1).
In scope
- Document function names or signals in client/server where events will emit;
TODO(E9.M1)until telemetry schema exists. - Optional: dev-only logging when flag enabled.
Out of scope
- Production ingest, dashboards, OpenTelemetry wiring.
Acceptance criteria
- Code or doc comment references event names matching epic_01 Slice 3.
- documentation_and_implementation_alignment.md updated when NEO-23 merges (status In Progress / contract partial per team rule).
After this backlog
- E1.M4 stories: hotbar +
AbilityCastRequestto E5.M1 stub or live consumer (separate plans). - Register: when E1M3-01 merges exported
TargetState(+ intent), update module_dependency_register.md E1.M3 row / note and E1.M3 Status per documentation_and_implementation_alignment.md.