THE 40-MINUTE OUTAGE'S REAL FIX. The GUI's map dropdown offered every RES
name passing the type-14+26 existence check -- which includes INTERNAL
FRAGMENTS: artrucks is an include-node of arena1 (PROGRESS_LOG map anatomy:
arena1 -> {arenall -> cavern, artrucks}), not a mission. Picking it stalled
every pod's mission load forever with no error anywhere, and End/Re-arm kept
restoring the poisoned egg -- 22:02..22:49, three "different" failures, one
cause.
* eggmodel.CONSOLE_MAPS: the Mac 4.10 operator console's own adventure-tree
catalog (Console.ini; the same 8 the solo menu ships in btl4fe.cpp kMaps):
cavern grass rav polar3 polar4 arena1 arena2 dbase. ValueSets.maps now
offers exactly that, catalog order, filtered to what the RES carries
(permissive fallback only if the intersection is empty -- a foreign RES
must not present zero maps). artrucks is the one fragment the old filter
let through; now hidden.
* The relay WARNS at egg load/reload when the mission names a non-catalog
map (the camo-color-warning precedent: hand-edited eggs still work, the
operator just cannot miss it).
* The launch hold gains the PHANTOM-MISSION SIGNATURE diagnostic: 0/N ready
for 60s means every pod is stalled in shared mission content -- one line
naming the egg's map and the recovery (End Mission -> fix map -> Re-arm),
instead of the silent 10s HELD drumbeat the operator stared at for 40
minutes. Hint re-arms per launch.
VERIFIED: new suite scratchpad/test_map_guard.py (5 checks: catalog exact +
ordered, artrucks hidden, warning fires on a doctored egg, silent on a real
one, the 60s hint names the map); all five console suites pass. Python-only.
(While placing the hint, a blind text-insert broke the launch-received block's
indentation -- caught by py_compile before anything ran, repaired, and the
whole area re-verified by the rearm suite.)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
72 lines
2.0 KiB
Python
72 lines
2.0 KiB
Python
"""Map-catalog guard regression (the 2026-07-26 artrucks outage).
|
|
|
|
1. ValueSets.maps offers EXACTLY the Mac 4.10 console catalog (8 maps,
|
|
catalog order) -- internal RES fragments (artrucks...) hidden.
|
|
2. The relay warns loudly when an egg names an unplayable map.
|
|
3. A real map stays silent.
|
|
4. The 60s all-pods-stalled hint names the egg's map.
|
|
"""
|
|
import contextlib
|
|
import io
|
|
import os
|
|
import re
|
|
import shutil
|
|
import sys
|
|
import time
|
|
|
|
sys.path.insert(0, r"C:\git\bt411\tools")
|
|
os.chdir(r"C:\git\bt411\content")
|
|
import btconsole # noqa: E402
|
|
import eggmodel # noqa: E402
|
|
|
|
fails = []
|
|
|
|
|
|
def check(label, ok, extra=""):
|
|
print(" %-56s %s %s" % (label, "OK" if ok else "*** FAIL ***", extra))
|
|
if not ok:
|
|
fails.append(label)
|
|
|
|
|
|
v = eggmodel.ValueSets()
|
|
check("dropdown = the console catalog, in order",
|
|
v.maps == list(eggmodel.CONSOLE_MAPS), repr(v.maps))
|
|
check("artrucks hidden from the dropdown", "artrucks" not in v.maps)
|
|
|
|
shutil.copyfile("FOGDAY.EGG", "_maptest.EGG")
|
|
raw = re.sub(rb"^map=\S+", b"map=artrucks",
|
|
open("_maptest.EGG", "rb").read(), count=1, flags=re.M)
|
|
open("_maptest.EGG", "wb").write(raw)
|
|
buf = io.StringIO()
|
|
with contextlib.redirect_stdout(buf):
|
|
btconsole.Relay(1500, "_maptest.EGG", "127.0.0.1", 0, manual_launch=True)
|
|
check("relay warns on a phantom map",
|
|
"NOT a playable mission" in buf.getvalue())
|
|
|
|
buf = io.StringIO()
|
|
with contextlib.redirect_stdout(buf):
|
|
r = btconsole.Relay(1500, "FOGDAY.EGG", "127.0.0.1", 0, manual_launch=True)
|
|
check("real map stays silent", "NOT a playable mission" not in buf.getvalue())
|
|
|
|
|
|
class C:
|
|
ready = False
|
|
|
|
|
|
r.launches_sent = 0
|
|
r.launch_at = time.time() - 61
|
|
r.eggs_released = True
|
|
r.by_host = {2: C(), 3: C()}
|
|
r._hold_notice_at = 0
|
|
buf = io.StringIO()
|
|
with contextlib.redirect_stdout(buf):
|
|
r._tick_launch()
|
|
check("60s all-stalled hint names the map",
|
|
"stalled in MISSION LOAD" in buf.getvalue()
|
|
and "map=" in buf.getvalue())
|
|
|
|
os.remove("_maptest.EGG")
|
|
print()
|
|
print("ALL PASS" if not fails else "FAILURES: %s" % fails)
|
|
sys.exit(1 if fails else 0)
|