Relay: hold the mission start until every pod is READY (loaded)

Live finding (round 3): firing RunMission while a pod is still loading
drowns that pod's load in the running mission's update streams -- the
same event queue serves both, so the load starves (the operator, always
last to join via the mech menu, loaded 5+ minutes or crashed while
testers took ~20s; solo loads on the same box take ~60s).  The launch
timer now also waits for every registered pod's READY (route -10) so
everyone enters together, 1995-style; a held launch announces who's
still loading every 10s, and a 180s cap force-fires so a wedged pod
can't hold the night hostage.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-22 22:36:18 -05:00
co-authored by Claude Opus 4.8
parent 0360a26612
commit fa935777cc
+26
View File
@@ -729,6 +729,32 @@ class Relay:
return
if time.time() < self.launch_at:
return
# ALL-READY GATE (2026-07-22, live finding round 3): firing the
# mission while a pod is still LOADING drowns that pod's load in the
# running mission's update streams (same event queue) -- the operator,
# who always joins last, loaded 5+ minutes or crashed while testers
# took ~20s. Hold the RunMission pair until every REGISTERED pod has
# sent READY (route -10): everyone enters together, 1995-style.
# Escape hatches: a pod that never readies is announced every 10s
# (the operator sees who), and a 3-minute cap force-fires so one
# wedged pod cannot hold the night hostage.
if self.launches_sent == 0:
not_ready = [h for h, c in sorted(self.by_host.items())
if not getattr(c, "ready", False)]
if not_ready and time.time() < self.launch_at + 180.0:
now = time.time()
if now - getattr(self, "_hold_notice_at", 0) >= 10.0:
self._hold_notice_at = now
names = ", ".join(
"PLAYER %d" % (h - FIRST_GAME_HOST_ID + 1)
for h in not_ready)
print(f"[relay] launch HELD -- still loading: {names} "
f"({len(self.by_host) - len(not_ready)}/"
f"{len(self.by_host)} ready)", flush=True)
return
if not_ready:
print(f"[relay] launch FORCED after 180s hold -- "
f"{len(not_ready)} pod(s) never readied", flush=True)
pkt = run_mission_packet()
for conn in list(self.console_conns):
try: