Restart empty missions after the last disconnect and every five hours

Use connected player counts to protect loading players and spectators, and elapsed real time for idle restarts. Reuse native mission termination and cover restart timing, authority and lifecycle guards with targeted regressions.
This commit is contained in:
2026-10-14 13:56:56 +02:00
parent bf85f62dca
commit 0048527fe2
6 changed files with 164 additions and 24 deletions
+17 -19
View File
@@ -68,25 +68,23 @@ The combined unconscious-camera/weapon revision passed eighteen native Workbench
The server's scene deadline now reaches the existing owned-ticket rejection even while a remote native preload completion is delayed. Rejection cannot assign a character, consume a life, or revive a stale ticket after a late acknowledgement. The ordinary verified admission path remains intact. Actual-method red/green regressions pass; the normal generated route independently verifies ordinary native admission. Remote timeout timing remains a multiplayer test requirement. [Evidence and scope](mission-hq-fixes-2026-10-01.md).
## Exhausted rounds on an empty server (5 October 2026)
## Empty-server restarts (14 October 2026)
An active round that has already admitted players now evaluates its no-survivor
end condition even when no clients are connected. Previously the empty-server
return reset that timer every tick. Once the last reconnect reservation expired
and its body was removed, the old round could remain open indefinitely. Returning
players still had a spent life, saw the spectator camera, and had to wait for the
30-second defeat grace and the next round's generation.
When the last player disconnects, the next server tick ends the mission through
the normal native end/reload sequence. This includes players who leave before
admission finishes. Living reconnect reservations do not keep a completely empty
mission running. While another player remains connected, the existing reserved
body and reconnect behavior still applies.
The existing grace now advances while the server is empty. Living reserved bodies
still prevent defeat, including the existing 15-minute reconnect window. A fresh
round with no admitted players waits normally and does not repeatedly restart.
No life is refunded, no new body is substituted during a round, and connected
players retain the existing defeat and admission behavior. Reservation expiry,
start of the no-survivor grace, and exhausted-round termination now produce
explicit log messages.
A fresh mission with no connections restarts after five hours of real elapsed
time. Each newly loaded mission starts a new five-hour window. Mission time and
time-multiplier settings do not change this interval. Connected players, including
spectators and players loading in, prevent the empty-server restart. The check
also runs during preparation; it stops with the mission's services. Both restart
reasons are written to the server log.
`test_initial_admission_exhaustion.py` reproduces the old failure using the actual
`ServerTick` body and covers reservation retention, expiry, grace cancellation,
and a fresh idle round. Reconnect, admission and native-end policy checks also
pass. The observed live server generated its next round and successfully spawned
the returning player; that recovery preceded deployment of this source fix.
`test_empty_server_restart.py` executes the production restart check and tick
wrapper, covering the five-hour boundary, repeated empty rounds, last disconnect,
connections between ticks, preparation, authority and duplicate-end prevention.
The restart uses the existing native end/reload path. These offline checks do
not establish live dedicated-server disconnect/reload timing.