Feed: apply the ADR 0019 message contract #31

Closed
opened 2026-10-20 18:41:23 +00:00 by mintopia · 4 comments
Owner

Refactor every feed message to ADR 0019.

Acceptance

  • Envelope {type, race_id, race_ms, ...} on every message; events carry event + data.
  • change.value native JSON; null = cleared; optional fields absent.
  • snake_case, all times integer _ms, racer/victim/attacker, mods always an array, lowercase icon names.
  • hit moves to the envelope with serial (+0x14) added.
  • roster = client state in snapshot and lobby: [{racer, join_ref, name, car, mods, local, ai}]; standings drops name/car/mods.
  • car_names/mod_names no longer on the wire (repo data, #30).
  • Drop race_time; event key -> race_type; speeds folded into standings as mph; race_result = {final, completed, standings}.
  • track_name/route_name documented.
  • powerups stays a fixed 3-slot array, null = empty slot (ADR 0019 exception).
  • race_result times in ms as time_ms (was whole seconds as time).
  • race_id: minted UUIDv7 per race until #34 finds a game ID.
  • docs/state-websocket.md, examples/live-timing, ws_tap.py, tests/state_ws_test.mm updated; no compatibility shim.

Rules

  • Wire format: ADR 0019 (docs/decisions/0019-feed-message-contract.md). Repo data/tools: ADR 0020.
  • Fix and verify on BLUR_ENGINE=recomp only.
  • Update docs/state-websocket.md and examples/live-timing for any feed change.
  • Test races: use the scripts/ scenarios (windowed, low settings) once #33 exists.
Refactor every feed message to ADR 0019. ## Acceptance - Envelope `{type, race_id, race_ms, ...}` on every message; events carry `event` + `data`. - `change.value` native JSON; `null` = cleared; optional fields absent. - snake_case, all times integer `_ms`, `racer`/`victim`/`attacker`, `mods` always an array, lowercase icon names. - `hit` moves to the envelope with `serial` (`+0x14`) added. - `roster` = client state in snapshot and lobby: `[{racer, join_ref, name, car, mods, local, ai}]`; `standings` drops `name`/`car`/`mods`. - `car_names`/`mod_names` no longer on the wire (repo data, #30). - Drop `race_time`; `event` key -> `race_type`; `speeds` folded into `standings` as `mph`; `race_result` = `{final, completed, standings}`. - `track_name`/`route_name` documented. - `powerups` stays a fixed 3-slot array, `null` = empty slot (ADR 0019 exception). - `race_result` times in ms as `time_ms` (was whole seconds as `time`). - `race_id`: minted UUIDv7 per race until #34 finds a game ID. - `docs/state-websocket.md`, `examples/live-timing`, `ws_tap.py`, `tests/state_ws_test.mm` updated; no compatibility shim. ## Rules - Wire format: ADR 0019 (`docs/decisions/0019-feed-message-contract.md`). Repo data/tools: ADR 0020. - Fix and verify on `BLUR_ENGINE=recomp` only. - Update `docs/state-websocket.md` and `examples/live-timing` for any feed change. - Test races: use the `scripts/` scenarios (windowed, low settings) once #33 exists.
Author
Owner

Research findings (static: Blur.exe strings + current src), 2026-10-20.

Drift inventory checked against ADR 0019. Covered by the acceptance list except:

  • race_result.time is whole seconds today, unlabelled. Under ADR 0019 it becomes _ms (e.g. time_ms) inside race_result.standings.
  • powerups uses null slots ([null,null,null]), while ADR 0019 says to leave optional fields out. Decide: keep a fixed 3-slot array with null = empty slot (positional, document it as an exception), or a compact array of held kinds.

Already intended by ADR 0019, no action: ids are local to each instance (match LAN by serial), hit race_ms is the local racer's clock, no schema version.

Current emitters: src/host/race_feed.cpp, game_state.cpp, state_ws.mm, hit_event.cpp, lua_patch.cpp, patches/Screens/Commands.post.lua, patches/Screens/Ingame/Hud.post.lua.

Research findings (static: Blur.exe strings + current src), 2026-10-20. Drift inventory checked against ADR 0019. Covered by the acceptance list except: - `race_result.time` is whole seconds today, unlabelled. Under ADR 0019 it becomes `_ms` (e.g. `time_ms`) inside `race_result.standings`. - `powerups` uses `null` slots (`[null,null,null]`), while ADR 0019 says to leave optional fields out. Decide: keep a fixed 3-slot array with `null` = empty slot (positional, document it as an exception), or a compact array of held kinds. Already intended by ADR 0019, no action: ids are local to each instance (match LAN by `serial`), hit `race_ms` is the local racer's clock, no schema version. Current emitters: `src/host/race_feed.cpp`, `game_state.cpp`, `state_ws.mm`, `hit_event.cpp`, `lua_patch.cpp`, `patches/Screens/Commands.post.lua`, `patches/Screens/Ingame/Hud.post.lua`.
Author
Owner

Decided: powerups keeps null slots; race_result time becomes time_ms in ms. Added to acceptance; ADR 0019 updated.

Decided: `powerups` keeps `null` slots; `race_result` time becomes `time_ms` in ms. Added to acceptance; ADR 0019 updated.
Author
Owner

null

null
Author
Owner

Completed and merged by Harmonic (task 37).

Completed and merged by Harmonic (task 37).
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
mintopia/blur#31
No description provided.