Interaction prompt system (#405) — decodes v4 nearby_interactions from server snapshots, displays context-sensitive "E - Talk to [NPC]" prompt with fade animation, extensible get_interaction_target()/get_selected_verb() interface for future radial verb menu
v4 protocol alignment — all tests updated for strict PROTOCOL_VERSION enforcement, 1-indexed verb priorities, corrected ExamineNpc "Observe" label
E2E test resilience — player entity found by kind instead of array index, wall/corner proof tests check specific NPC positions to support server's 3-NPC proof room layout
Files changed
Area
Files
Change
Protocol
protocol.gd
Decode nearby_interactions from v4 snapshots
State
game_state.gd
Store nearby_interactions, tick_rate comment fix
SimBridge
sim_bridge.gd
Test mode generates interactions near NPCs, correct priorities/labels
UI
interaction_prompt.gd, interaction_prompt.tscn
New prompt component
Main
main.gd, main.tscn
Wire E key to interaction target
Tests
test_interaction_prompt.gd
17 test cases for protocol, state, bridge, UI, encoding
Tests
test_protocol.gd, test_local_bridge.gd
Version enforcement alignment
Tests
test_e2e_connection.gd, test_sprint2_proof.gd
Entity ordering resilience
Test plan
112/112 tests passing (0 errors, 0 failures)
E2E tests pass against freshly built server binary
Server-driven interaction prompt that displays "E - Talk" when near
an interactable NPC. Decodes v4 nearby_interactions from snapshot,
stores in GameState, renders via InteractionPrompt UI with fade
animation. Extensible interface (get_interaction_target/get_selected_verb)
for future radial verb menu (v0.2).
- Protocol: decode nearby_interactions array with nested VerbOption structs,
entity relationship/observation fields, tick_rate in GameTime
- GameState: store/clear nearby_interactions per snapshot
- SimBridge: test mode generates v4 format with structured verbs
- InteractionPrompt: PanelContainer with fade in/out, polls GameState
- Tests: 19 new test cases covering protocol, state, sim bridge, UI, encoding
- Fixture assertions updated for v4 protocol version
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Server team shipped strict PROTOCOL_VERSION enforcement (c05ff7b),
1-indexed verb priorities, and "Observe" label for ExamineNpc.
Updates all test snapshots to include version: 4, fixes sim_bridge
test mode priorities (0-indexed → 1-indexed) and labels, replaces
v1 backward-compat tests with strict version rejection tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Server proof room now has 3 NPCs instead of 1. Find player entity
by kind instead of assuming entities[0]. Wall-hides test checks
specific NPC position (16.5, 13.5) rather than asserting zero NPC
count. Corner-reveal test searches for NPC1 by position.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PR #17: feat(client): interaction prompt system + v4 protocol alignment
Hoshe (Code Quality): APPROVE
Summary: Clean interaction prompt system with proper separation of concerns (display-only UI, server-driven data). Protocol v4 alignment is correctly enforced across all tests. Comprehensive test coverage (24 new tests) with no critical issues.
#
File
Severity
Issue
1
interaction_prompt.gd:25-29
warning
Empty-check inconsistency: _process checks interactions.size() > 0 but _show_prompt re-checks verbs.is_empty(). Not a bug (nested catch works), but consolidating the logic would be cleaner.
2
protocol.gd:162-169
suggestion
Dropped interactions (malformed decode) are silently discarded — no decode_warnings counter like entities have. Consider debug logging for dropped interactions.
3
sim_bridge.gd:237-248
suggestion
Test interaction range npc_dist <= 2 is a magic number. Extract to named constant TEST_INTERACTION_RANGE.
4
main.gd:32-39
suggestion
TODO for Interact(InteractData) has no ticket reference. Add ticket # for tracking.
Tyre (Architecture): APPROVE
Summary: Architecture is sound: server-driven interaction data flows through protocol layer into GameState, UI reads reactively, input encoding is ready for future extension. Respects D-010 (information boundaries), D-020 (client-server separation), and D-030 (testability). The TODO in main.gd correctly defers server integration until the Rust side is ready.
#
File
Severity
Issue
1
game_state.gd:24
warning
nearby_interactions field not documented as "v4+ field" like game_time and player_facing are documented as "v2 fields". Add version comment for consistency.
2
protocol.gd:104-105
suggestion
_decode_nearby_interaction drops zero-verb interactions silently. Add push_warning before returning null for debugging visibility.
3
test_protocol.gd
suggestion
Consider adding test_decode_snapshot_rejects_version_wrong_type (version as String "4" instead of int 4) for belt-and-suspenders validation.
4
test_interaction_prompt.gd:65
suggestion
test_prompt_get_selected_verb_returns_first_kind is v0.1-specific — add comment noting radial menu (v0.2) will change selection logic.
5
test_e2e_connection.gd:119-126
suggestion
"Find player by kind" pattern now appears in multiple test files. Consider extracting to test utility helper.
Verdict: APPROVED
Both reviewers approve. Solid implementation — server-driven interaction prompt with proper v4 protocol enforcement, 24 new tests, entity ordering resilience fix. All comments are minor suggestions.
## Review: client -> main (type: code)
PR #17: feat(client): interaction prompt system + v4 protocol alignment
---
### Hoshe (Code Quality): APPROVE
**Summary:** Clean interaction prompt system with proper separation of concerns (display-only UI, server-driven data). Protocol v4 alignment is correctly enforced across all tests. Comprehensive test coverage (24 new tests) with no critical issues.
| # | File | Severity | Issue |
|---|------|----------|-------|
| 1 | interaction_prompt.gd:25-29 | warning | Empty-check inconsistency: `_process` checks `interactions.size() > 0` but `_show_prompt` re-checks `verbs.is_empty()`. Not a bug (nested catch works), but consolidating the logic would be cleaner. |
| 2 | protocol.gd:162-169 | suggestion | Dropped interactions (malformed decode) are silently discarded — no `decode_warnings` counter like entities have. Consider debug logging for dropped interactions. |
| 3 | sim_bridge.gd:237-248 | suggestion | Test interaction range `npc_dist <= 2` is a magic number. Extract to named constant `TEST_INTERACTION_RANGE`. |
| 4 | main.gd:32-39 | suggestion | TODO for Interact(InteractData) has no ticket reference. Add ticket # for tracking. |
---
### Tyre (Architecture): APPROVE
**Summary:** Architecture is sound: server-driven interaction data flows through protocol layer into GameState, UI reads reactively, input encoding is ready for future extension. Respects D-010 (information boundaries), D-020 (client-server separation), and D-030 (testability). The TODO in main.gd correctly defers server integration until the Rust side is ready.
| # | File | Severity | Issue |
|---|------|----------|-------|
| 1 | game_state.gd:24 | warning | `nearby_interactions` field not documented as "v4+ field" like `game_time` and `player_facing` are documented as "v2 fields". Add version comment for consistency. |
| 2 | protocol.gd:104-105 | suggestion | `_decode_nearby_interaction` drops zero-verb interactions silently. Add `push_warning` before returning null for debugging visibility. |
| 3 | test_protocol.gd | suggestion | Consider adding `test_decode_snapshot_rejects_version_wrong_type` (version as String "4" instead of int 4) for belt-and-suspenders validation. |
| 4 | test_interaction_prompt.gd:65 | suggestion | `test_prompt_get_selected_verb_returns_first_kind` is v0.1-specific — add comment noting radial menu (v0.2) will change selection logic. |
| 5 | test_e2e_connection.gd:119-126 | suggestion | "Find player by kind" pattern now appears in multiple test files. Consider extracting to test utility helper. |
---
### Verdict: APPROVED
Both reviewers approve. Solid implementation — server-driven interaction prompt with proper v4 protocol enforcement, 24 new tests, entity ordering resilience fix. All comments are minor suggestions.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
nearby_interactionsfrom server snapshots, displays context-sensitive "E - Talk to [NPC]" prompt with fade animation, extensibleget_interaction_target()/get_selected_verb()interface for future radial verb menuFiles changed
protocol.gdnearby_interactionsfrom v4 snapshotsgame_state.gdnearby_interactions, tick_rate comment fixsim_bridge.gdinteraction_prompt.gd,interaction_prompt.tscnmain.gd,main.tscntest_interaction_prompt.gdtest_protocol.gd,test_local_bridge.gdtest_e2e_connection.gd,test_sprint2_proof.gdTest plan
🤖 Generated with Claude Code
Review: client -> main (type: code)
PR #17: feat(client): interaction prompt system + v4 protocol alignment
Hoshe (Code Quality): APPROVE
Summary: Clean interaction prompt system with proper separation of concerns (display-only UI, server-driven data). Protocol v4 alignment is correctly enforced across all tests. Comprehensive test coverage (24 new tests) with no critical issues.
_processchecksinteractions.size() > 0but_show_promptre-checksverbs.is_empty(). Not a bug (nested catch works), but consolidating the logic would be cleaner.decode_warningscounter like entities have. Consider debug logging for dropped interactions.npc_dist <= 2is a magic number. Extract to named constantTEST_INTERACTION_RANGE.Tyre (Architecture): APPROVE
Summary: Architecture is sound: server-driven interaction data flows through protocol layer into GameState, UI reads reactively, input encoding is ready for future extension. Respects D-010 (information boundaries), D-020 (client-server separation), and D-030 (testability). The TODO in main.gd correctly defers server integration until the Rust side is ready.
nearby_interactionsfield not documented as "v4+ field" likegame_timeandplayer_facingare documented as "v2 fields". Add version comment for consistency._decode_nearby_interactiondrops zero-verb interactions silently. Addpush_warningbefore returning null for debugging visibility.test_decode_snapshot_rejects_version_wrong_type(version as String "4" instead of int 4) for belt-and-suspenders validation.test_prompt_get_selected_verb_returns_first_kindis v0.1-specific — add comment noting radial menu (v0.2) will change selection logic.Verdict: APPROVED
Both reviewers approve. Solid implementation — server-driven interaction prompt with proper v4 protocol enforcement, 24 new tests, entity ordering resilience fix. All comments are minor suggestions.
Pull request closed