Skip to content

Fix code audit findings: stuck loading, audio interruptions, save format, collisions - #21

Merged
mbeczynski merged 6 commits into
mainfrom
fix/audit-2026-10-21
Oct 22, 2026
Merged

mbeczynski merged 6 commits into
mainfrom
fix/audit-2026-10-21

Conversation

@mbeczynski

Copy link
Copy Markdown
Contributor

Fixes from the 21.10 code review (state 695114c). Each finding was first confirmed in the code.

App

  • Stuck race loading: the player's car is exempt from the in-race load hold and is loaded on demand. Before the fix, picking a not-yet-loaded car in the garage, once six other cars were loaded, left the loading screen spinning forever. A failed load now shows a message with "Try again" instead of the placeholder model. The loading screen has a Menu button and a 60 s limit, and its waits end when the screen is left.
  • Audio interruptions: when a call, the alarm or Siri interrupts the game, sounds stop, so nothing plays on the stopped engine (it raised an exception) and the race pauses. Media-services reset is handled. Returning from the background resumes the same music track.
  • Rewards on the finish line: stars and coins are saved when the player finishes, not when the results appear 3 s later.
  • Background during loading: the race is paused once it is revealed.
  • Track build error: countdown and engine sound no longer run under the error screen.
  • Saves: a campaign save that cannot be read is backed up before a new game overwrites it. An unknown car no longer resets the whole profile.
  • Menu frame stats: the per-frame stats (Debug/Family) no longer grow for the whole session.

RaceCore

  • Campaign save format: new version field and a tolerant decoder. Missing fields get defaults and unknown upgrades are skipped; the encoded format is unchanged apart from version.
  • Collisions:
    • Only the player can cause a takedown. A rival hitting the player, or another rival, exchanges speed instead of boosting the player to 90% of the rival's speed.
    • The restart after a wreck ramps up over 0.3 s instead of jumping to 12 m/s in one step.
    • Walls, canister pickups and near misses use each car's own size.
    • AI and auto-steer steer around wrecked cars ahead.
  • Rival stats: based on a fixed template, not on the catalog's starter car.

CI and README

  • CI builds the Family and Release configurations.
  • README no longer claims that CI runs the UI tests. They need the local models and a GPU-backed simulator, so they run locally.

Tests

  • swift test: 79 tests, 0 failures (65 before; the new tests failed on the old code).
  • New LoadingUITests: car picked before it loaded, failed car load, backgrounding during loading. The stuck-loading test hangs on the old code (over 100 s) and starts the race in 2.8 s with the fix.
  • Full XCUITest on the iPad (A16), iOS 27.0 simulator, from a clean install: 13/13 passed. This covers all 40 tracks, every car to the finish, every car × 3 colours, gameplay and loading. No crash reports.
  • Debug, Family and Release builds pass.

Not changed: the store/demo model (a product decision), the memory and rendering items (B11–B14), test isolation (T2).

🤖 Generated with Claude Code

mbeczynski and others added 6 commits October 22, 2026 08:52
- Player car is exempt from the in-race load hold and loaded on demand;
  a failed load shows an error with retry instead of a placeholder model.
- Loading screen has a Menu button and a 60 s limit; waits stop on cancel.
- Audio interruptions stop sound playback safely and pause the race;
  the same music track resumes after returning from the background.
- Race rewards are settled when the player crosses the line.
- Backgrounding during loading pauses the race once it is revealed.
- Nothing runs under the track error screen.
- Unreadable campaign save is backed up before a new game overwrites it;
  an unknown car no longer resets the whole profile.
- Menu frame stats no longer grow for the whole session.
- CI also builds Family and Release; README states UI tests run locally.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add a format version and a custom decoder: missing keys fall back to
defaults and unknown upgrade names are skipped instead of failing the
whole save (which made the app start a new game and overwrite progress).
Encoding is unchanged, so existing saves stay compatible.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The app swaps the catalog and starterCar for local models, which silently
changed rival strength on every track.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…voidance

- Rivals never wreck the player or each other; such hits fall back to the
  normal side damping or rear speed exchange (no more 20 -> 54 m/s jumps).
- Wreck restart speed is reached over 0.3 s instead of in one step.
- Walls, pickups and near misses use each car's own shape.
- AI and autopilot steer around a wrecked car ahead.
- Tests for the wall wreck threshold and rival/rival, rival/player hits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The fixed delay often elapsed before the race screen opened, so the test
passed on the old code too. Now the car starts loading exactly in the
state that used to hang (race screen open, six cars loaded); the old code
times out, the fix starts the race. Tests start from car 0, since the car
picked in a previous run stays in the saved profile.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@mbeczynski
mbeczynski merged commit 90bfa5a into main Oct 22, 2026
1 check passed
@mbeczynski
mbeczynski deleted the fix/audit-2026-10-21 branch October 22, 2026 09:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant