From 10ed66bd7c1de1ffecd43607facb1f5ce43536f7 Mon Sep 17 00:00:00 2001 From: arcattack Date: Tue, 21 Jul 2026 10:28:51 -0500 Subject: [PATCH] UNIFY: one exe -- retire the pod/glass/steam compile split The three build dirs (build\ pod, build-glass\, build-steam\) were compile- time splits of the same game; the tax was real: a stale steam exe shipped 2 days behind, the felt keymap flipped with the boot flavor, and cockpit clicks were silently dead in the pod build (the trigger-config incident). Now everything compiles into the single build\ exe: - CMakeLists: BT_GLASS/BT_STEAM options removed; the glass TUs (PadRIO, bindings, panel, glass windows, plasma) + FE/console + Steam transport compile unconditionally; both macros always defined (seam markers). - Steam: steam_api.lib linked with /DELAYLOAD:steam_api.dll + delayimp -- the DLL maps only when SteamAPI is first called, and every call site gates on BT_STEAM_NET=1 (BTSteamNet_* short-circuit on steamActive), so machines without the DLL run everything but Steam sessions. - CABINET GUARD (btl4main): the miniconsole menu previously claimed any zero-arg launch -- unified, that would hijack the pod cabinet's boot shape. The menu now requires BT_PLATFORM=glass (or BT_FE_MENU=1); platform parse moved above the fe_menu_mode computation. A bare boot behaves exactly like the old pod build (DEV profile, wait for egg). - Bats (play_solo/join/join_lan/play_steam) + the btoperator.py template: single build\ path + BT_PLATFORM=glass. mkdist: one exe (+DLL scan picks up OpenAL32 + steam_api). build-glass\/build-steam\/build-glass2\ (a stale Jul-20 cache) deleted. Verified matrix on the unified exe: bare zero-arg boot == old pod exe (same DEV profile + egg-load path; the segfault on a missing egg is pre-existing, baselined vs the zip exe) glass + BT_BTNTEST scripted click -> [cfgmap] ENTER/EXIT (trigger config) runs with steam_api.dll ABSENT (delay-load proven) glass zero-arg -> miniconsole menu 2-node loopback MP: 145 ticks each, cross-connected BT_STEAM_NET=1 without Steam client -> "staying on Winsock", game runs KB: context/glass-cockpit.md compile-gates section rewritten for the unified model. Co-Authored-By: Claude Opus 4.8 (1M context) --- CMakeLists.txt | 93 ++++++++++++++++++---------------------- context/glass-cockpit.md | 36 +++++++++++----- game/btl4main.cpp | 33 +++++++------- players/join.bat | 17 +++----- players/join_lan.bat | 17 +++----- players/play_solo.bat | 22 +++------- players/play_steam.bat | 10 ++--- tools/btoperator.py | 20 ++++----- tools/mkdist.py | 16 +++---- 9 files changed, 117 insertions(+), 147 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 935724d..8e0b03d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,34 +11,22 @@ set(CMAKE_CXX_STANDARD 14) set(DXSDK "C:/Program Files (x86)/Microsoft DirectX SDK (June 2010)" CACHE PATH "Legacy DirectX SDK root") #===========================================================================# -# Compile gates -- the desktop developer layer (glass cockpit). -# Default OFF: a no-flags configure builds the PURE POD GAME (the build of -# record). BT_GLASS adds PadRIO input, the on-screen cockpit panel/plasma, -# and the miniconsole mission launcher; BT_STEAM adds the Steam transport + -# lobby on top. Convention: BT_GLASS/BT_STEAM are the only COMPILE-time -# gates -- every other BT_* name is a runtime env gate (BTEnvOn). -# Build dirs: build-pod/ (defaults), build/ (-DBT_GLASS=ON), -# build-steam/ (-DBT_GLASS=ON -DBT_STEAM=ON). See context/glass-cockpit.md. +# ONE BUILD (unified 2026-07-21; was pod / glass / steam compile splits). +# Everything compiles into the single exe; behavior is selected at RUNTIME +# by env gates only -- BT_PLATFORM=glass arms the desktop-cockpit profile +# (PadRIO clicks, bindings.txt keymap, plasma window, miniconsole menu), +# BT_STEAM_NET=1 arms the Steam transport (steam_api.dll is DELAY-LOADED, +# so machines without the DLL run fine while the gate stays off). A bare +# boot (no env, no args) behaves like the old pod build: DEV profile, no +# menu, waits for the console egg -- the cabinet default is unchanged. +# The BT_GLASS/BT_STEAM macros remain (always defined) as seam markers. #===========================================================================# -option(BT_GLASS "Desktop developer layer: PadRIO glass cockpit, miniconsole front end" OFF) -option(BT_STEAM "Steam transport + lobby for internet MP testing (requires BT_GLASS)" OFF) -if(BT_STEAM AND NOT BT_GLASS) - message(FATAL_ERROR "BT_STEAM requires BT_GLASS (configure with -DBT_GLASS=ON)") -endif() -message(STATUS "bt411 gates: BT_GLASS=${BT_GLASS} BT_STEAM=${BT_STEAM}") - set(BT_DEFS WIN32 _WINDOWS UNICODE _UNICODE NOMINMAX _CRT_SECURE_NO_DEPRECATE _CRT_SECURE_NO_WARNINGS - _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) + _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS + BT_GLASS BT_STEAM) set(BT_OPTS /permissive /W0 /wd4996 /EHsc /bigobj /MP) -if(BT_GLASS) - list(APPEND BT_DEFS BT_GLASS) -endif() -if(BT_STEAM) - list(APPEND BT_DEFS BT_STEAM) -endif() - #===========================================================================# # Engine: MUNGA (shared sim/render engine) + MUNGA_L4 (Win32/D3D9 HAL). # The 2007 RP411 Windows engine, carrying our BT render/loader work @@ -248,15 +236,13 @@ add_library(munga_engine STATIC "engine/MUNGA_L4/bgfload.cpp" "engine/MUNGA_L4/image.cpp" ) -if(BT_GLASS) - target_sources(munga_engine PRIVATE - "engine/MUNGA_L4/L4PADRIO.cpp" - "engine/MUNGA_L4/L4PADBINDINGS.cpp" - "engine/MUNGA_L4/L4PADPANEL.cpp" - "engine/MUNGA_L4/L4GLASSWIN.cpp" - "engine/MUNGA_L4/L4PLASMAWIN.cpp" - ) -endif() +target_sources(munga_engine PRIVATE + "engine/MUNGA_L4/L4PADRIO.cpp" + "engine/MUNGA_L4/L4PADBINDINGS.cpp" + "engine/MUNGA_L4/L4PADPANEL.cpp" + "engine/MUNGA_L4/L4GLASSWIN.cpp" + "engine/MUNGA_L4/L4PLASMAWIN.cpp" +) target_include_directories(munga_engine BEFORE PRIVATE "${CMAKE_SOURCE_DIR}/engine/shim" "${DXSDK}/Include") @@ -360,13 +346,11 @@ target_include_directories(btl4 BEFORE PRIVATE "${CMAKE_SOURCE_DIR}/game/original/BT_L4" "${CMAKE_SOURCE_DIR}/game/fwd" "${DXSDK}/Include") -if(BT_GLASS) - target_sources(btl4 PRIVATE - "game/glass/btl4fe.cpp" - "game/glass/btl4console.cpp" - ) - target_include_directories(btl4 BEFORE PRIVATE "${CMAKE_SOURCE_DIR}/game/glass") -endif() +target_sources(btl4 PRIVATE + "game/glass/btl4fe.cpp" + "game/glass/btl4console.cpp" +) +target_include_directories(btl4 BEFORE PRIVATE "${CMAKE_SOURCE_DIR}/game/glass") target_compile_definitions(btl4 PRIVATE ${BT_DEFS}) target_compile_options(btl4 PRIVATE ${BT_OPTS}) target_link_libraries(btl4 PRIVATE @@ -384,19 +368,24 @@ target_link_libraries(btl4 PRIVATE # UNRESOLVED tolerates the dead offline-tool factory in mech3.cpp. See docs. target_link_options(btl4 PRIVATE /FORCE) -if(BT_STEAM) - set(STEAMWORKS "${CMAKE_SOURCE_DIR}/extern/steamworks_sdk_164") - target_sources(munga_engine PRIVATE "engine/MUNGA_L4/L4STEAMNET.cpp") - target_sources(btl4 PRIVATE "game/glass/btl4lobby.cpp") - target_include_directories(munga_engine PRIVATE "${STEAMWORKS}/public") - target_include_directories(btl4 PRIVATE "${STEAMWORKS}/public") - target_link_libraries(btl4 PRIVATE - "${STEAMWORKS}/redistributable_bin/steam_api.lib") - add_custom_command(TARGET btl4 POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different - "${STEAMWORKS}/redistributable_bin/steam_api.dll" - "$") -endif() +# Steam transport: compiled in, DELAY-LOADED. steam_api.dll is only mapped +# when the first SteamAPI call runs, and every call site gates on +# BT_STEAM_NET=1 (btl4main step-4b bring-up; L4NET's BTSteamNet_* short- +# circuit on steamActive) -- so a machine without the DLL runs everything +# except Steam sessions. +set(STEAMWORKS "${CMAKE_SOURCE_DIR}/extern/steamworks_sdk_164") +target_sources(munga_engine PRIVATE "engine/MUNGA_L4/L4STEAMNET.cpp") +target_sources(btl4 PRIVATE "game/glass/btl4lobby.cpp") +target_include_directories(munga_engine PRIVATE "${STEAMWORKS}/public") +target_include_directories(btl4 PRIVATE "${STEAMWORKS}/public") +target_link_libraries(btl4 PRIVATE + "${STEAMWORKS}/redistributable_bin/steam_api.lib" + delayimp) +target_link_options(btl4 PRIVATE "/DELAYLOAD:steam_api.dll") +add_custom_command(TARGET btl4 POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${STEAMWORKS}/redistributable_bin/steam_api.dll" + "$") # Copy the OpenAL runtime DLL next to the built exe. (libsndfile is gone: its # repo DLL was a no-op STUB -- L4AUDRES now loads the soundbank WAVs with an diff --git a/context/glass-cockpit.md b/context/glass-cockpit.md index a7eeafb..968958a 100644 --- a/context/glass-cockpit.md +++ b/context/glass-cockpit.md @@ -14,20 +14,34 @@ pod — and stay far enough out of the game that nothing a real pod requires can consumer product (GDI-grade UI is the ceiling). Pod fidelity outranks desktop convenience in every trade-off. -## The compile gates (the ONLY compile-time feature gates in the tree) +## ONE unified build (2026-07-21; the compile-gate split is RETIRED) -| Gate | Default | Adds | -|---|---|---| -| `BT_GLASS` | OFF | PadRIO input (XInput+keyboard), per-display cockpit windows (or the legacy single button panel), desktop plasma window, `glass` platform preset, miniconsole mission launcher | -| `BT_STEAM` | OFF (requires `BT_GLASS`) | Steam transport (`ISteamNetworkingSockets`) + `ISteamMatchmaking` lobby | +The pod/glass/steam **compile** split (three build dirs, three exes) is gone — it caused +version skew (a stale steam exe shipped 2 days behind), tripled build time, and the +"clicks silently dead in the wrong build" incident. Now **everything compiles into the one +`build/` exe** and behavior is selected at RUNTIME: -- A **no-flags configure is the pure pod game** — the build of record. `cmake` options are - cached, so a developer configures a `build/` with `-DBT_GLASS=ON` once. -- Build dirs: `build-pod/` (defaults, purity), `build/` (dev, glass ON), `build-steam/` (ON/ON). -- **Convention:** `BT_GLASS`/`BT_STEAM` are compile gates; every other `BT_*` name is a RUNTIME - env gate (`BTEnvOn`) — do not add compile gates without updating this file. +| Runtime gate | Arms | +|---|---| +| `BT_PLATFORM=glass` | the desktop-cockpit profile: `L4CONTROLS=PAD` → PadRIO (clickable cockpit buttons, bindings.txt keymap), plasma window, and the miniconsole menu on a zero-arg launch | +| `BT_STEAM_NET=1` | the Steam transport (FakeIP/SDR; degrades to Winsock without the Steam client). `steam_api.dll` is **DELAY-LOADED** (`/DELAYLOAD` + delayimp) — machines without the DLL run everything else | +| (nothing) | the old pod-build behavior byte-for-byte: DEV profile, no menu, waits for the console egg — **the cabinet default is unchanged** | + +- The `BT_GLASS`/`BT_STEAM` macros are now ALWAYS defined (seam markers only — the `#ifdef` + sites remain as documentation of the layer boundaries). Every gated code path was audited: + all are instance-guarded (`PadRIO::activeInstance`, `steamActive`) or env-gated at runtime. +- **Menu guard (cabinet protection):** the miniconsole previously claimed any zero-arg launch; + unified, it requires `BT_PLATFORM=glass` (or `BT_FE_MENU=1`) — a bare cabinet boot can never + land in the menu (btl4main.cpp, platform parse moved above the fe_menu_mode computation). +- Verified matrix (2026-07-21): bare boot ≡ old pod exe (same DEV profile, same egg-load path); + glass + scripted click → ConfigureMappables end-to-end; exe runs WITHOUT steam_api.dll + present; glass zero-arg → menu; 2-node loopback MP (145 ticks each); `BT_STEAM_NET=1` + without Steam → "staying on Winsock" + game runs. +- **Convention:** every `BT_*` name is a RUNTIME env gate (`BTEnvOn`); there are NO compile + feature gates anymore — do not add one without updating this file. - No weak-linkage/optional symbols — `/FORCE` turns unresolved externals into runtime AVs - ([[reconstruction-gotchas]]); gated calls must be structurally present-or-absent at compile time. + ([[reconstruction-gotchas]]); everything links always, so this class of trap no longer varies + by build flavor. ## Plan of record (2026-07-17) diff --git a/game/btl4main.cpp b/game/btl4main.cpp index c6fe8d6..56d4d50 100644 --- a/game/btl4main.cpp +++ b/game/btl4main.cpp @@ -289,15 +289,6 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine // the child inherited L4CONTROLS=KEYBOARD, and the glass preset could // never select PAD -- no PadRIO, no panel, plasma only). // - int fe_menu_mode = 0; -#ifdef BT_GLASS - { - int fe_has_egg = lpCmdLine && strstr(lpCmdLine, "-egg") != NULL; - int fe_has_net = lpCmdLine && strstr(lpCmdLine, "-net") != NULL; - fe_menu_mode = !fe_has_egg && !fe_has_net && getenv("BT_FE_EGG") == NULL; - } -#endif - int gBTPlatformPod = 0; int gBTPlatformGlass = 0; { @@ -315,15 +306,21 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine if (pv[0] && _stricmp(pv, "glass") == 0) gBTPlatformGlass = 1; } -#ifndef BT_GLASS - if (gBTPlatformGlass) - { - std::cout << "[boot] platform 'glass' ignored: not in this build " - "(configure with -DBT_GLASS=ON); falling back to DEV" - << std::endl << std::flush; - gBTPlatformGlass = 0; - } -#endif + } + + // UNIFIED-BUILD GUARD (2026-07-21): the miniconsole menu is a GLASS- + // platform feature. It must NOT claim a bare zero-arg boot -- that is + // the POD CABINET's launch shape (DEV profile, wait for the console + // egg). The menu runs only when the glass platform is selected + // (BT_PLATFORM=glass / -platform glass, e.g. play_steam.bat) or forced + // with BT_FE_MENU=1. (Platform parse moved ABOVE this block so the + // flag is available; it reads only env/cmdline, no profile putenvs.) + int fe_menu_mode = 0; + { + int fe_has_egg = lpCmdLine && strstr(lpCmdLine, "-egg") != NULL; + int fe_has_net = lpCmdLine && strstr(lpCmdLine, "-net") != NULL; + fe_menu_mode = !fe_has_egg && !fe_has_net && getenv("BT_FE_EGG") == NULL + && (gBTPlatformGlass || getenv("BT_FE_MENU") != NULL); } if (fe_menu_mode) diff --git a/players/join.bat b/players/join.bat index 1563a5e..47578cf 100644 --- a/players/join.bat +++ b/players/join.bat @@ -2,23 +2,18 @@ rem BT411 -- join 107.202.218.169's game (internet). Seat/mech assigned rem by the operator. Keep this file next to content\ + build\. cd /d %~dp0 -rem Prefer the GLASS build when present (dev checkout): PadRIO makes the -rem cockpit surround's buttons mouse-clickable (trigger config etc.). The -rem pod build renders the same cockpit but clicks are a no-op there; player -rem zips ship only build\. -set GAME=build\Release\btl4.exe -if exist "build-glass\Release\btl4.exe" ( - set GAME=build-glass\Release\btl4.exe - set BT_PLATFORM=glass -) -if not exist "%GAME%" goto badpath +rem ONE unified build (2026-07-21): the exe carries every layer; the GLASS +rem platform env arms the desktop cockpit (clickable MFD buttons, trigger +rem config, bindings.txt keymap). +set BT_PLATFORM=glass +if not exist "build\Release\btl4.exe" goto badpath if not exist "content\OPERATOR.EGG" goto badpath set BT_RELAY=107.202.218.169:1500 set BT_LOG=join.log set BT_START_INSIDE=1 set BT_DEV_GAUGES=1 cd content -..\%GAME% -egg OPERATOR.EGG -net 1501 +..\build\Release\btl4.exe -egg OPERATOR.EGG -net 1501 echo. echo The game has exited. If you did NOT quit on purpose echo (crash, or it never connected), send the operator the diff --git a/players/join_lan.bat b/players/join_lan.bat index da11c50..a78f96b 100644 --- a/players/join_lan.bat +++ b/players/join_lan.bat @@ -5,23 +5,18 @@ rem unreliable on this network, so it is pinned). If the operator's IP changes, rem update the address below (find it on the operator PC with `ipconfig`). rem Joining over the INTERNET? Use join.bat instead. cd /d %~dp0 -rem Prefer the GLASS build when present (dev checkout): PadRIO makes the -rem cockpit surround's buttons mouse-clickable (trigger config etc.). The -rem pod build renders the same cockpit but clicks are a no-op there; player -rem zips ship only build\. -set GAME=build\Release\btl4.exe -if exist "build-glass\Release\btl4.exe" ( - set GAME=build-glass\Release\btl4.exe - set BT_PLATFORM=glass -) -if not exist "%GAME%" goto badpath +rem ONE unified build (2026-07-21): the exe carries every layer; the GLASS +rem platform env arms the desktop cockpit (clickable MFD buttons, trigger +rem config, bindings.txt keymap). +set BT_PLATFORM=glass +if not exist "build\Release\btl4.exe" goto badpath if not exist "content\OPERATOR.EGG" goto badpath set BT_RELAY=10.0.0.46:1500 set BT_LOG=join.log set BT_START_INSIDE=1 set BT_DEV_GAUGES=1 cd content -..\%GAME% -egg OPERATOR.EGG -net 1501 +..\build\Release\btl4.exe -egg OPERATOR.EGG -net 1501 echo. echo The game has exited. If you did NOT quit on purpose echo (crash, or it never connected), send the operator the diff --git a/players/play_solo.bat b/players/play_solo.bat index a9fd790..37a8dee 100644 --- a/players/play_solo.bat +++ b/players/play_solo.bat @@ -2,27 +2,17 @@ rem BT411 -- single-player practice (no network, no operator). rem Edit the -egg below for other maps (ARENA2/DBASE/FOGDAY/...). cd /d %~dp0 -rem Prefer the GLASS build when present (dev checkout): it carries PadRIO, the -rem click-to-button seam that makes the cockpit surround's MFD red buttons, -rem radar rails and joystick buttons mouse-clickable (trigger config needs -rem this). The pod build renders the same cockpit but its clicks are a no-op -rem (PadRIO is not compiled there); player zips ship only build\. -set GAME=build\Release\btl4.exe -if exist "build-glass\Release\btl4.exe" ( - set GAME=build-glass\Release\btl4.exe - rem The GLASS platform profile is what creates PadRIO (L4CONTROLS=PAD): - rem without it the boot falls to the DEV profile (KEYBOARD only) and every - rem cockpit click is silently discarded -- trigger config dead, keymap on - rem the btinput/CONTROLS.MAP engine instead of PadRIO/bindings.txt. - set BT_PLATFORM=glass -) -if not exist "%GAME%" goto badpath +rem ONE unified build (2026-07-21): the exe carries every layer; the GLASS +rem platform env arms the desktop cockpit (clickable MFD buttons, trigger +rem config, bindings.txt keymap). +set BT_PLATFORM=glass +if not exist "build\Release\btl4.exe" goto badpath if not exist "content\OPERATOR.EGG" goto badpath set BT_START_INSIDE=1 set BT_DEV_GAUGES=1 set BT_LOG=join.log cd content -..\%GAME% -egg ARENA1.EGG +..\build\Release\btl4.exe -egg ARENA1.EGG echo. echo The game has exited. If it closed unexpectedly, echo send the operator content\join.log. diff --git a/players/play_steam.bat b/players/play_steam.bat index 03d3d41..8c15a1d 100644 --- a/players/play_steam.bat +++ b/players/play_steam.bat @@ -3,15 +3,15 @@ rem BT411 -- STEAM play (EXPERIMENTAL, dev testers). Launches the glass rem front-end menu: HOST a Steam lobby or JOIN one from the menu -- there rem is no address to configure; sessions form through the Steam lobby. rem Requires: the Steam client RUNNING and logged in, and the steam build -rem (build-steam\) extracted next to content\. +rem extracted next to content\. cd /d %~dp0 -if not exist "build-steam\Release\btl4.exe" goto badpath +if not exist "build\Release\btl4.exe" goto badpath if not exist "content\BTL4.RES" goto badpath set BT_PLATFORM=glass set BT_STEAM_NET=1 set BT_LOG=steam.log cd content -..\build-steam\Release\btl4.exe +..\build\Release\btl4.exe echo. echo The game has exited. If it closed unexpectedly, send the operator echo content\steam.log. Steam not running = the menu still works but @@ -22,10 +22,10 @@ exit /b echo. echo ================================================== echo ERROR: this file is not in the right place, or -echo this zip does not include the STEAM build. +echo the zip was not fully extracted. echo. echo It must sit in the EXTRACTED game folder, next to -echo the 'content' and 'build-steam' folders. +echo the 'content' and 'build' folders. echo ================================================== echo. pause diff --git a/tools/btoperator.py b/tools/btoperator.py index d3d18c2..d4f5e40 100644 --- a/tools/btoperator.py +++ b/tools/btoperator.py @@ -786,15 +786,11 @@ class Operator(QMainWindow): def guarded(header, sets, run, tail): return ("@echo off\n" + header + "cd /d %~dp0\n" - # Prefer the GLASS build when present (dev checkout): PadRIO - # makes the cockpit buttons mouse-clickable; the pod build's - # clicks are a no-op. Player zips ship only build\\. - "set GAME=build\\Release\\btl4.exe\n" - "if exist \"build-glass\\Release\\btl4.exe\" (\n" - " set GAME=build-glass\\Release\\btl4.exe\n" - " set BT_PLATFORM=glass\n" - ")\n" - "if not exist \"%GAME%\" goto badpath\n" + # ONE unified build (2026-07-21): every layer is in the one + # exe; BT_PLATFORM=glass arms the desktop cockpit (clickable + # buttons / trigger config / bindings.txt keymap). + "set BT_PLATFORM=glass\n" + "if not exist \"build\\Release\\btl4.exe\" goto badpath\n" "if not exist \"content\\" + egg_name + "\" goto badpath\n" + sets + @@ -834,7 +830,7 @@ class Operator(QMainWindow): "set BT_RELAY=%s:%d\nset BT_LOG=join.log\n" "set BT_START_INSIDE=1\nset BT_DEV_GAUGES=1\n" % (host, self.f_port.value()), - "..\\%GAME% -egg %s -net 1501\n" % egg_name, + "..\\build\\Release\\btl4.exe -egg %s -net 1501\n" % egg_name, net_tail)) lan_ip = _detect_lan_ip() lan_relay = ("%s:%d" % (lan_ip, self.f_port.value())) if lan_ip else "auto" @@ -851,7 +847,7 @@ class Operator(QMainWindow): "rem Joining over the INTERNET? Use join.bat instead.\n", "set BT_RELAY=%s\nset BT_LOG=join.log\n" "set BT_START_INSIDE=1\nset BT_DEV_GAUGES=1\n" % lan_relay, - "..\\%GAME% -egg %s -net 1501\n" % egg_name, + "..\\build\\Release\\btl4.exe -egg %s -net 1501\n" % egg_name, net_tail)) with open(os.path.join(out_dir, "play_solo.bat"), "w", newline="\r\n") as f: @@ -862,7 +858,7 @@ class Operator(QMainWindow): "(ARENA2/DBASE/FOGDAY/...).\n", "set BT_START_INSIDE=1\nset BT_DEV_GAUGES=1\n" "set BT_LOG=join.log\n", - "..\\%GAME% -egg ARENA1.EGG\n", + "..\\build\\Release\\btl4.exe -egg ARENA1.EGG\n", "echo.\necho The game has exited. If it closed unexpectedly,\n" "echo send the operator content\\join.log.\npause\n")) self.log.appendPlainText( diff --git a/tools/mkdist.py b/tools/mkdist.py index b6ecb2e..08083e0 100644 --- a/tools/mkdist.py +++ b/tools/mkdist.py @@ -49,21 +49,15 @@ def main(): ["git", "ls-files", "-z", "content/"]).decode().split("\0") tracked = [t for t in tracked if t] - exes = ["build/Release/btl4.exe", "build-glass/Release/btl4.exe"] - bats = ["players/play_solo.bat", "players/join.bat", "players/join_lan.bat"] + # ONE unified build (2026-07-21): every layer (pod game + glass cockpit + + # Steam transport) lives in the single exe; steam_api.dll is delay-loaded. + exes = ["build/Release/btl4.exe"] + bats = ["players/play_solo.bat", "players/join.bat", "players/join_lan.bat", + "players/play_steam.bat"] for p in exes + bats: if not os.path.exists(p): sys.exit("MISSING: %s -- build/refresh it first" % p) - # Steam build (EXPERIMENTAL): included when present -- play_steam.bat - # hosts/joins internet sessions through the Steam lobby (needs the Steam - # client running; steam_api.dll ships next to the exe). - if os.path.exists("build-steam/Release/btl4.exe"): - exes.append("build-steam/Release/btl4.exe") - bats.append("players/play_steam.bat") - else: - print(" (no build-steam -- play_steam.bat left out)") - # Runtime DLLs living next to each exe (OpenAL32.dll etc.) -- the exe # fails to load without them (caught by the clean-extract boot test). for exe in list(exes):