Standardized YAML frontmatter on all 115 sprint briefing files across sprints 1-26 with title, description, type, status, sprint number, and team fields. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
138 lines
7.8 KiB
Markdown
138 lines
7.8 KiB
Markdown
---
|
|
title: "Sprint 19 — Client Briefing"
|
|
description: "Save/load client UI, game session management, GDScript test framework"
|
|
type: sprint
|
|
status: archived
|
|
sprint: 19
|
|
team: "client"
|
|
---
|
|
|
|
# Sprint 19: Persist — Client Tasks
|
|
|
|
**Goal:** The player can save and resume a game session with per-game directories; the simulation tier system gains eviction and scope pinning; and the first test infrastructure ships with information boundary validation and IPC hardening.
|
|
|
|
**Branch:** `client`
|
|
**Agents:** Stig (UI), Oscar (networking)
|
|
|
|
## Carry-over from Sprint 18
|
|
|
|
None. Sprint 18 closed clean.
|
|
|
|
## New Tickets
|
|
|
|
| # | Title | Blocked by |
|
|
|---|-------|------------|
|
|
| #554 | Save/load: client UI | #553 (server) |
|
|
| #258 | Game session management | — |
|
|
| #205 | GDScript test framework setup | — |
|
|
| #206 | Scene testing utilities | #205 |
|
|
| #348 | Debug visualization overlay | — |
|
|
|
|
Use `db/connectors/ticket show <id>` for full details.
|
|
|
|
## Key Decisions
|
|
|
|
- `decisions/architecture.md` — D-020 (IPC architecture, MessagePack), D-085 (per-game save directory structure)
|
|
- `decisions/questions.md` — Q-029 (save file format design — open, Sprint 19 uses MessagePack quick-and-dirty format)
|
|
|
|
## Open Questions to Resolve Early
|
|
|
|
- **Q-029: Save file format design** — Sprint 19 ships MessagePack quick-and-dirty format. Do not over-engineer the loading screen metadata. A readable directory name (`<timestamp>-<seed>/`) per D-085 is sufficient for v0.1. The full versioning/migration design is tracked in Q-029 for a later sprint.
|
|
|
|
## Notes
|
|
|
|
### #554 — Save/load: client UI
|
|
|
|
Blocked by #553 (server must implement `SaveCommand`/`LoadCommand` IPC messages before client can wire F5/F6).
|
|
|
|
What this ticket must deliver:
|
|
- F5 key mapped in `client/scripts/autoloads/input_mapper.gd` to send a `SaveGame` IPC action to the server with the active game directory path (`user://saves/<game-id>/quicksave.sav`)
|
|
- F6 key mapped to send `LoadGame` IPC action with the same path
|
|
- Server responds with `SaveComplete`/`LoadComplete` — client shows a brief HUD notification ("Saved" / "Loading...")
|
|
- Loading screen scene: reads `user://saves/` directory, lists subdirectories sorted by last-modified (most recent first), shows most recent save filename per game directory per D-085
|
|
- F6 from the main menu opens the loading screen
|
|
- The active `game-id` is tracked in `GameState` autoload (add `current_game_id: String`)
|
|
|
|
Integration points: `client/scripts/autoloads/input_mapper.gd` (key bindings), `client/scripts/autoloads/game_state.gd` (current_game_id field), `client/scripts/protocol/` (new IPC message encoding), `client/scripts/ui/` (loading screen scene).
|
|
|
|
Save directory path per D-085: `user://saves/<timestamp>-<seed>/` where game-id is created on New Game (#258). F5 quicksave writes to `user://saves/<game-id>/quicksave.sav`. Loading screen lists directories sorted by `FileAccess.get_modified_time()`.
|
|
|
|
Wireframe reference: `docs/design/wireframes/menus/v01-save-load.png`.
|
|
|
|
### #258 — Game session management
|
|
|
|
New Game creates the per-game save directory before any save occurs (D-085 requirement: "directory created on New Game — even before the first save, so the path exists for quicksave/autosave").
|
|
|
|
What this ticket must deliver:
|
|
- `GameState.current_game_id: String` — format `<timestamp>-<seed>` (e.g. `20260225-143022-a7b3f1`)
|
|
- On "New Game": generate game-id (timestamp + RNG hex suffix), create `user://saves/<game-id>/` directory via `DirAccess.make_dir_recursive()`
|
|
- On "Continue" / loading screen selection: set `current_game_id` from the selected directory name
|
|
- "Quit to menu" flow: prompt "Save before quitting?" — F5 save if confirmed
|
|
- Wire the game-id into the `SimBridge` startup: server subprocess launched with `--game-id <id>` argument (or equivalent) so server can log with the same ID
|
|
|
|
Integration points: `client/scripts/autoloads/game_state.gd` (new fields), `client/scripts/protocol/server_process.gd` (subprocess launch args), `client/scripts/ui/` (main menu scene: New Game / Continue buttons).
|
|
|
|
Note: `game_state.gd` is already the largest autoload with 300+ lines. Keep game session logic in a thin wrapper on `GameState` — do not add another 100-line block directly. Consider a `session_manager.gd` helper if the logic exceeds 40 lines.
|
|
|
|
### #205 — GDScript test framework setup
|
|
|
|
The project has no GDScript test infrastructure yet. The Godot client has no equivalent of `cargo test`.
|
|
|
|
What this ticket must deliver:
|
|
- Install and configure **GUT (Godot Unit Test)** as the GDScript test framework — it has the best Godot 4 support and is actively maintained
|
|
- Create `client/tests/` as the test root directory
|
|
- `client/tests/run_gut.gd`: the GUT runner script that CI can invoke headlessly (`godot --headless -s client/tests/run_gut.gd`)
|
|
- Exit code 0 = all pass, non-zero = failures — required for CI integration (#270 test runner scripts)
|
|
- A single smoke test `client/tests/test_protocol.gd`: verifies `Protocol.decode_snapshot(bytes)` returns non-null for a minimal valid msgpack fixture
|
|
|
|
GUT installation: add as a Godot addon. Check if there is already an `addons/` directory in `client/`.
|
|
|
|
### #206 — Scene testing utilities
|
|
|
|
Blocked by #205 (GUT must be installed first).
|
|
|
|
What this ticket must deliver:
|
|
- `client/tests/util/scene_helper.gd`: loads a scene file by path, instantiates it into a temporary viewport, provides `assert_node_exists(path)`, `assert_signal_emitted(node, signal_name)`, and `get_node_at(path)` helpers
|
|
- `client/tests/test_game_state.gd`: tests for `GameState.apply_snapshot()` — verify that a snapshot dictionary with known fields updates the correct `GameState` fields
|
|
- `client/tests/test_protocol.gd` (extend from #205 smoke test): add roundtrip test for `Protocol.encode_player_input()` and `Protocol.decode_player_input()`
|
|
|
|
These utilities are the scaffolding for all future client tests. Keep them minimal and dependency-free — do not require a running server.
|
|
|
|
### #348 — Debug visualization overlay
|
|
|
|
Dev tool (F3 toggle). The stub `client/scripts/ui/debug_overlay.gd` already exists.
|
|
|
|
What this ticket must deliver:
|
|
- Extend `debug_overlay.gd` to draw on a `CanvasLayer` above the game world:
|
|
- **Pathfinding waypoints**: draw lines between waypoint positions from `GameState.visible_entities` (entities with kind `Npc` — estimate waypoints from position delta between ticks)
|
|
- **Line-of-sight rays**: draw lines from player position to each visible entity
|
|
- **Vision cone boundary**: draw the forward/peripheral arc boundary using `GameState.visibility_sectors`
|
|
- **Information state tags**: draw confidence label (Suspects/KnowsOf/KnowsDetails/Direct) above each visible NPC from `GameState.player_knowledge`
|
|
- **Tick timing graph**: small line chart in corner showing tick delta over the last 30 ticks
|
|
- F3 toggle: connected to `InputMapper` action `toggle_debug_overlay`
|
|
- Debug overlay is **dev-only**: compiled out in export builds via `OS.is_debug_build()` check
|
|
|
|
Integration points: `client/scripts/autoloads/game_state.gd` (data source), `client/scripts/autoloads/input_mapper.gd` (F3 action), `client/scripts/ui/debug_overlay.gd` (extend existing stub).
|
|
|
|
## Dependency Chain
|
|
|
|
```
|
|
#205 (GDScript test framework) → #206 (scene testing utilities)
|
|
|
|
#258 (game session management) → #554 (save/load client UI: needs current_game_id)
|
|
#553 (server, ECS extraction) → #554 (save/load client UI: needs IPC commands)
|
|
|
|
#348 (debug overlay) → standalone, parallel track
|
|
```
|
|
|
|
Parallel starts: #258, #205, #348 all unblocked week 1.
|
|
#554 starts after #553 (server) reaches review stage and #258 lands.
|
|
#206 starts after #205 merges.
|
|
|
|
## PR Workflow
|
|
|
|
When ready to submit, create a PR with `tea` CLI. **All flags are required** to avoid TTY prompts (see CLAUDE.md "Gitea access" section):
|
|
```bash
|
|
tea pr create --repo jpmschweitzer/settled-reach --login schweitz --title "feat(client): description" --description "body" --base main --head client
|
|
```
|