Adds client-side wire support for the bookmark catalog (#614) and the
two associated player actions. PROTOCOL_VERSION bumps from 21 to 23:
- v22 (server): RequestBookmarkCatalog + ConfirmBookmark player actions
- v23 (server): bookmark_catalog field on ObserverSnapshot
Decode:
- protocol.gd decode_snapshot extracts optional bookmark_catalog.
Defensive parse of BookmarkWire fields (id, title, subtitle, flavor,
default_location, allowed_locations, allowed_locations_cultures,
career, starting_capital_tractus). Missing or malformed → null.
- snapshot_handler.gd caches the catalog into GameState.bookmark_catalog
on each snapshot (server pushes on tick 0; re-fetchable via
RequestBookmarkCatalog).
- GameState gains bookmark_catalog: Array = [] (untyped per autoload
parse-order discipline; default empty so callers can iterate without
null checks).
Encode:
- encode_request_bookmark_catalog() — unit variant, sent to trigger a
re-push if the cached catalog is missing.
- encode_confirm_bookmark(bookmark_id, starting_location_id) — struct
variant matching server rmp_serde shape. Called from character
creation on Start (lands in Workstream 6).
Tests:
- 5 new cases in test_protocol.gd: hand-built bookmark_catalog decode
(all 9 fields asserted), fixture-based decode round-trip, missing-
field null behavior, RequestBookmarkCatalog encode roundtrip,
ConfirmBookmark encode roundtrip.
- All 12 existing snapshot fixtures regenerated from server via
`cargo test --test gen_fixtures -- --ignored`. The new
snapshot_with_bookmark_catalog.msgpack fixture was generated by the
same pass.
Verification:
- gdlint clean
- godot --headless --path client --quit — no SCRIPT ERROR
- test_protocol 62/62, test_client_p3 24/24, test_implant_nav_stack
52/52, test_implant_registry 42/42, test_implant_app_lifecycle 36/36
Workstream 4 (Option A sequencing via loading_screen + SimBridge
connect) lands next.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Per-player settings via rusqlite (bundled, zero runtime dep). Server
owns the settings DB; client sends ChangeSettings commands over IPC.
Extensible key-value with typed columns (String/Int/Float/Bool).
Protocol bumped to v20 with settings_response in ObserverSnapshot.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add debug_response: None to all ObserverSnapshot constructors in
integration tests
- Bump PROTOCOL_VERSION assertion 17 → 18 in serialization tests
- Regenerate golden proof_room_tick_10.json (BoundaryWall tiles)
- Regenerate client msgpack fixtures for new snapshot fields
- Fix debug.rs resource optionality (Option<ResMut> for
ContaminationActive/EventQueue)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Protocol v17: add state_hash (desync detection) and sim_errors
(structured error reporting) to ObserverSnapshot. Add SimError,
SimErrorKind, SimErrorBuffer types. Wrap main loop app.update() in
catch_unwind — on panic, send a final SimError snapshot before exit.
Report recoverable deserialization errors to client via SimErrorBuffer.
Compute per-tick state hash from player position + NPC count + tick.
Update all test fixtures and golden files for protocol v17.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Updates all client-side msgpack test fixtures and server test
harnesses to include the new triangle_crisis_events field added
in protocol v16.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Five new .msgpack fixtures: snapshot_minimal, snapshot_full,
player_input_move, player_input_interact, malformed. Rust generator in
gen_fixtures.rs, 7 Rust validation tests in serialization.rs, GDScript
cross-language test in test_ipc_fixtures.gd (22 assertions).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>