Live race telemetry in the game-state feed #5
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Depends on
#2 Game-state feed
mintopia/blur
#4 Race state websocket
mintopia/blur
Reference
mintopia/blur#5
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What to build
During a race, the game-state feed (and so websocket clients) carries live race data: lap/total laps, the player's position, race time, per-racer standings, and race finish with final results. External apps can follow a race as it happens.
Acceptance criteria
BLUR_ENGINE=recompBlocked by
Harmonic Task 6: blocked, no code changes made. Findings from probing a live career race on recomp (probe scripts only in /tmp):
Amax.ChangeText(id, "HUD_0_LAP" / "HUD_0_POS_NUM" / "HUD_0_POS_NUM_OF" ...); values are filled by the engine.Amax.GetLevelData()->Laps,NumberOfCars,RaceMode,Route.Amax.GetNumVehicles()=20,Amax.GetPlayerVehicleIndex(0)=0.Multiplayer.GetVehiclePosition/GetVehicleIndexByPosition/GetRaceResults/VehiclesFinished,NetRace.RaceInProgress/HasRaceFinishedexist but are inert in an SP race (position 0, empty standings). They likely work in network races (untested; needs 2 instances).UIEnums.GameMessagehas no lap/position/finish messages (only RaceStartsIn, Sp* events).HUD_CURRENT_LAP(0xeea6b0, xref 0xc394f7),CMN_HUD_LAP_FORMAT,BEST_LAPin Blur.exe; xref site is not in a Ghidra-defined function. Needs reversing the race manager (lap, time, per-racer position/standings), then a recomp hook or guest-memory reader (gen.shregen), and MP verification with host+join.Needs a human decision/direction: accept native RE of the race manager (and a hook/reader in the host), or narrow scope (e.g. MP-only via the Lua getters above, total laps from GetLevelData).
Harmonic Task 6: implemented (commits
356f58a+ follow-up on harmonic/task-6).Feed keys (set while a race runs; need a connected
BLUR_STATE_WSclient):lap,laps,position,racers,race_time(s),standings(JSON, best first),speeds(JSON mph per racer, ~5/s),race_result(on finish;final:trueonce all finished,completed:falseif the race ends first), plusracer,car,mods. In network races each human'sstandingsentry hasname,car(icon name) andmods;local:truemarks this machine's player. Docs:docs/state-websocket.md, ADR 0013.How: host thread reads racer objects (position
+0xefc, the HUD field; lap, lap timer, speed) and the network player list from guest memory (src/host/race_scan.cpp); pure feed logic inrace_feed.cpp(unit testrace_feed_test).BLUR_PLAYER_NAMEsets the player name (defaultblur).Verified on recomp: scripted full 3-lap SP race; two game instances on one Mac (LAN host + join, scripted input, distinct names alpha/bravo): both clients saw correct lap/position/standings/speeds, names/cars/mods resolved per client (local racer index differs per client and matches each HUD: host 1/2, client 2/2), race_result on host finish. fps median 120 (vsync cap), min 114-116, with the feed enabled and no client vs disabled. ctest 15/15.
Limits: names/cars/mods only for humans in network races (AI and SP: local car only, no mods in SP); both test clients shared one save so cars/mods were identical (names differed); 3+ instances on one Mac can't be tested (docs/multiplayer-lan.md); a client connecting mid-race gets
race_timefrom the current lap only; offsets are specific to the shipped Blur.exe.Comment-policy fixes: moved update() param comment to update(), replaced trailing comment with named condition (racers_reset_at_teardown), removed stale key list from game_state.h header. No behaviour change.
Completed and merged by Harmonic (task 6).