Server / tick rate (src/game/server.cpp, server.h, governor.h)
- Late ticks and stalls now need two bad rate windows in a row before the tick rate steps down (
kLateWindows = 2; owner's call, 2026-10-24).- Before: one 3 s rate window with more than 1% of ticks over the stall threshold (4 ms at 1000 Hz) was enough. A cloud VM's host sometimes doesn't run the server for 15-50 ms (steal). On a 4 vCPU test VM, a 1 ms sleep woke more than 4 ms late 25 times a minute, up to 21 ms (51 ms when spinning). One 35 ms pause is about 31 ticks over 4 ms, just over 1% of a window, so a server dropped to 500 Hz at the next break for a hitch nobody felt.
- Now: the first such window only arms the check and logs
tick rate: late ticks in one window (x% of ticks over N ms late), waiting for a second. The next window must also have late ticks to schedule the step down (mid-round) or take it (between rounds). A clean window disarms the check and logsthe next window was clean: no step down (a one-off host pause). An unjudged window (rate check off, editing, paused, no players, map-load hold) or any rate change also disarms it, because the new rate has its own stall threshold. - Covered: stalls, and late ticks with light load (busy at most 50%).
- Still immediate: busy over 50%, upload over the cap, send failures, and most players losing snapshots or with their ping up. A pause can't produce those: busy grows by at most the pause's length (1-2% of 3 s), loss counts gaps in tick numbers (the catch-up leaves none), ping uses a window minimum of a smoothed value, and upload is a 3 s average. A window with late ticks plus one of these acts at once, as before.
- Undoing a step up that doesn't hold: still happens mid-round. For late ticks it now counts from the first window of the run, so one pause right after a raise no longer undoes it and doubles the wait before the next try.
- Load governor (prod and testing sharing a box): it is no longer told a server is overloaded for a single late-only window. Without this, governed servers (which never step down on their own) kept the false positive.
status: showslate ticks in the last window: waiting for a second before stepping downwhile armed, andtick rate steps down at the next break (why)while a step down is pending.- Trade-off: a host that really can't hold the rate takes one extra window (3 s) to be noticed. Between rounds each step down takes two windows (6 s) instead of one. Mid-round the step waits for the break anyway, so players see no difference.
- Cost: an int and a double on the server, checked once per window. No allocations, nothing per tick.
Physics editor (tools/physics_editor/references/)
- 12 more games: Quake Live (VQL cvars), Quake Champions (Ranger, from the June 2018 patch notes), Reflex, UT2004 and UT3 (UnrealScript defaults), Halo 3 and Halo Reach (a player's in-game measurements), DOOM Eternal (cvar defaults in metres), CoD4, Fortnite, Portal 2, and CS 1.6 as competitive servers run it (sv_accelerate 5, sv_stopspeed 75), kept next to the engine-default CS 1.6. The owner asked "did you search for estimates?" for the games that had none.
- Gaps filled: Apex gravity, jump, air cap and air accel (from a measured 56 u jump and 0.74 s airtime: gravity = 8h/T², take-off = 4h/T); Overwatch 2 gravity (17.53 m/s², from the Workshop) and jump; UT99 gravity, JumpZ, step and accel equivalents; Minecraft step height 0.6.
- How estimates are made: jump speed from a measured height is sqrt(2gh); Unreal's ground accel is AccelRate / GroundSpeed and air accel AirControl x AccelRate / AirSpeed / 10. The README lists every formula and the confidence labels (a developer's own patch notes count as exact).
- Still not covered (searched, nothing usable published): Diabotical, UT4, DOOM 2016, Splitgate, Halo 2/4/5/Infinite, recent CoD (only sprint speeds, noted in the CoD4 entry), Valorant's jump and gravity, Reflex's physics constants, Quake Champions' jump and gravity.
- One flagged doubt: UT3's v^2/2g jump height (99.7 UU) is far above the game's own AI limit (MaxJumpHeight 49); its note says so.
- Celeste's super-jump note now says Quark's hyper hop started at the same 0.5 and 1.18.28 raised it to 0.866; the references were regenerated against 1.18.28 (34 games, 266 values, check.py OK).
Tests (tests/rules_tests.h, tests/tests.cpp)
- New
testRateTwoWindows(tickrate group andrules rate): stalling, clean, stalling doesn't step down; a second stalling window in a row does. A newrateJudged()helper pumps until the rate check has judged N more windows, so window edges are exact. testRateBetweenRoundsandtestRateUndoStepUpcheck that one window only arms the check (no pending step, governor not told,statussays waiting) and two act.- The timingTest host-pause retries stay: the tests still judge single windows, and one run's clean window saw a 13 ms host stall.
Docs
- RELEASE_CHECKLIST "Server CPU and rate" row: a step down needs two 3 s windows in a row; the new log and status lines to expect. README's load governor paragraph and governor.h's
overloadedcomment say the same.