From fa935777ccbd17289df23d7285f948ee4e597734 Mon Sep 17 00:00:00 2001 From: arcattack Date: Wed, 22 Jul 2026 22:36:18 -0500 Subject: [PATCH] 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) --- tools/btconsole.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tools/btconsole.py b/tools/btconsole.py index 17ae82f..c606b74 100644 --- a/tools/btconsole.py +++ b/tools/btconsole.py @@ -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: