fix(timer): epoch headless timers from simulation_time, not wall clock
A mcrfpy.Timer stamped its epoch (last_ran) from GameEngine::runtime -- an sf::Clock reading wall time -- at creation and every control method, while GameEngine::step() ticks timers against simulation_time. The two clocks are in unrelated frames, so a timer's FIRST fire under step() depended on process-startup wall timing: headless replay was nondeterministic. Steady state looked fine because the first fire re-stamps last_ran into the simulation frame; only the first fire was contaminated. Add a timer_now() helper that returns getSimulationTime() when headless and runtime otherwise, and route all 9 epoch reads in PyTimer.cpp through it. Windowed mode is unchanged; headless timers are now a pure function of the step() sequence. Surfaced by the #381 screenshot oracle: timer-driven snippets 048 and 191 rarely flipped their PNG. Post-fix both are byte-identical across 15 runs and the full snippet oracle is 272/272 stable; suite 621/621. Regression test asserts exact fire counts and callback runtimes across three scenarios (interval boundaries, deterministic first fire, one-shot). closes #383 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LTh2ZW7bd3XSd9qK86Z2CE
This commit is contained in:
parent
2f937dba91
commit
a358ef4e4e
3 changed files with 99 additions and 9 deletions
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue