Download

← All updates

Update

quark 1.18.15

Everything that changed in this version, and why.

Two owner answers to the cleanup crew's open questions (2026-10-24): the hide and seek always-send radius (NET-10) is 24 m, and dedicated servers with no humans pause. No protocol, file format or setting change.

Dedicated server pause (src/game/server.cpp, server.h, src/server/main.cpp)

  • Why: a bots-only server burned about 1-4% of a core (server CPU report: 4.2% with 7 bots at 1000 Hz on the Oracle box, which also runs production and the Discord bot) playing a match nobody watches. The owner picked "pause" over "125 Hz until someone joins" and "keep running".
  • What: ServerConfig::pauseWithoutHumans, set only by quark_server. Server::updatePause, each frame(): with no humans connected (players away in their reconnect grace count as humans), no live ranked match (its ticket deadline runs on game time) and no edit waiting for its autosave (that runs on the tick), the server pauses: no simulate(), no snapshots, tick_ and timeMs_ (so every game timer: respawns, rounds, votes, bot timers) stand still. Logged once each way: "paused: no humans (bots wait)" / "resumed".
  • Still running while paused: packet receive (a connect resumes the server in the same frame), the reachability probe, the load governor, timeouts and drops, ranking server replies, the restart flag. All of these run on wall time.
  • Sleep: idle() waits up to 50 ms on the socket (was 5 ms with no humans), so a paused server wakes ~20 times a second instead of ~200; any packet still wakes it at once.
  • No catch-up, no rate verdict: nextTick_ follows the clock while paused, so resuming doesn't run a burst of 20 ticks, and the tick-rate check resets its window at both edges and while paused, so a pause never steps the tick rate.
  • The first human gets a normal game: on pausing, a running vote is cancelled (it would otherwise resume with time left in front of the next player) and a match past warmup is reset to warmup (rulesReset), so a joiner doesn't land in a frozen mid-match or end screen. A fresh server pauses at tick 0, already in warmup.
  • Not paused: games hosted from the client, vs bots, and every test server (the flag defaults off), so bot tests and the map / bot editors' sims run as before.
  • Left as is: balance bots are updated in simulate(), so a paused server may list them until a player joins (fixed within 1 s after).
  • Test (server group): testPauseWithoutHumans: with the flag, 2 bots alone pause at tick 0 with the clock at 0 and idle() sleeps the long wait; a real client connects, resumes, gets snapshots, tick and clock advance; after it leaves the server stays live through the grace, then pauses again in warmup with the clock frozen; each log line once; without the flag, bots alone keep ticking.

Hide and seek visibility (src/game/server.cpp)

  • Why (NET-10): players and projectiles within kVisNear (20 m) of a viewer are always sent with no ray check. The owner chose 24 m for hide and seek.
  • What: kVisNearHide = 24.0f; updatePlayerVisibility and updateProjectileVisibility pick the radius once per pass (MODE_HIDE: 24 m, every other mode: 20 m), so the pair loop costs the same.
  • Trade-off: a seeker's client is sent hiders up to 24 m away through walls (a modified client could show them); in return no hider within 24 m appears late round a corner, and those pairs cast no rays.

Docs

  • docs/RELEASE_CHECKLIST.md (dedicated servers): a bots-only server logs "paused", a join logs "resumed" and starts at warmup; the 30-minute soak needs a player on, since bots alone now pause.