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) <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-21 10:28:51 -05:00
co-authored by Claude Opus 4.8
parent d89ae71db5
commit 10ed66bd7c
9 changed files with 117 additions and 147 deletions
+41 -52
View File
@@ -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"
"$<TARGET_FILE_DIR:btl4>")
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"
"$<TARGET_FILE_DIR:btl4>")
# 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
+25 -11
View File
@@ -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)
+15 -18
View File
@@ -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)
+6 -11
View File
@@ -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
+6 -11
View File
@@ -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
+6 -16
View File
@@ -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.
+5 -5
View File
@@ -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
+8 -12
View File
@@ -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(
+5 -11
View File
@@ -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):