Net: Steam lobby (btl4lobby) + launch-mode wiring (Workstream C.2)
Port RP412's RPL4LOBBY to BT: an ISteamMatchmaking room stands in for the arcade Site-Management screen. Compiled both gates -- stubs without BT412_STEAM, the full room under it (both configs build + link clean). Lobby (game/reconstructed/btl4lobby.*): - Room screen (green-on-black, like the menu), owner = console. - Member data: FakeIP + fake console/game ports + persona + mech/color/badge (ip/cp/gp/nm/vh/cl/bd keys). - Nonced "go" launch roster -> SteamNetTransport_RegisterPeer for every peer. - Push/PullRaceResults over lobby data rebuild the shared score sheet. Front end (btl4fe.*): HOST/JOIN buttons when BTLobby_Available() (Steam transport up); the menu loop exits on a steam action and BTFrontEnd_Run routes the lobby outcome -- host builds the egg with every member as a [pilots] mesh entry (BTFrontEnd_SetHostedPilots), member returns launch mode 2. Results screen prefers the marshal's collated result names. Marshal (btl4console.*): add GetResultName / ClearResults / InjectResult so the lobby owner can refill the sheet from the collated wire scores; Result gains a name field. WinMain (btl4main.cpp): install the Steam transport on BT412STEAM env (before the front end, so the lobby is offered); branch on BTFrontEnd_LastLaunchMode() -- host owns the marshal clock + joins the mesh, member enters as a network pod on :1501 (SetNetworkCommonFlatAddress + gConsoleLossEndsMission); Push (host) / Pull (member) results, then relaunch. CMake: btl4lobby.cpp joins bt410_l4; that lib gets BT412_STEAM + the Steamworks include under the gate. build-steam/ gitignored. Deferred (untestable here -- needs Steam + multiple machines): the host->member wire egg-feed marshal (InstallNetworkRace); a member currently waits for a console connection nothing supplies, so a live host+member race is blocked on it. The lobby object does not survive the per-mission relaunch. docs/STEAM-3-MACHINE-TEST.md for BT not yet authored. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+56
-5
@@ -368,6 +368,21 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||
|
||||
std::cout << "BattleTech v4.10 (reconstructed port)" << std::endl << std::flush;
|
||||
|
||||
// STEAM NETWORKING (BT412_STEAM build + BT412STEAM env): bring the Steam
|
||||
// transport up BEFORE the front end so the lobby is available (its HOST/JOIN
|
||||
// buttons appear only when a FakeIP was allocated) and the race mesh routes
|
||||
// over SDR/FakeIP. Any failure silently leaves the process on Winsock TCP.
|
||||
#ifdef BT412_STEAM
|
||||
if (getenv("BT412STEAM") != NULL && atoi(getenv("BT412STEAM")) != 0)
|
||||
{
|
||||
extern Logical SteamNetTransport_Install();
|
||||
if (SteamNetTransport_Install())
|
||||
std::cout << "[steam] transport up -- lobby available" << std::endl << std::flush;
|
||||
else
|
||||
std::cout << "[steam] transport unavailable -- TCP fallback" << std::endl << std::flush;
|
||||
}
|
||||
#endif
|
||||
|
||||
// CPU pin (timing stability). BT_AFFINITY overrides the mask; =0 disables --
|
||||
// required for multi-instance runs (two instances pinned to core 0 starve
|
||||
// each other, and the L4NET connect-retry loop busy-waits).
|
||||
@@ -530,13 +545,17 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||
//=======================================================================//
|
||||
extern int BTFrontEnd_Run();
|
||||
extern int BTFrontEnd_LastMissionSeconds();
|
||||
extern int BTFrontEnd_LastLaunchMode();
|
||||
extern void BTFrontEnd_ShowResults();
|
||||
extern void BTLocalConsole_Install(int mission_seconds);
|
||||
extern int BTLocalConsole_MissionCompleted();
|
||||
extern void BTLobby_PushRaceResults();
|
||||
extern void BTLobby_PullRaceResults();
|
||||
|
||||
int launch_mode = 0; // 0 solo, 1 lobby host, 2 lobby member
|
||||
if (front_end_mode)
|
||||
{
|
||||
ShowWindow(hWnd, SW_HIDE); // the menu is its own window
|
||||
ShowWindow(hWnd, SW_HIDE); // the menu (and lobby room) are their own windows
|
||||
if (!BTFrontEnd_Run())
|
||||
{
|
||||
std::cout << "[frontend] menu closed -- exiting" << std::endl << std::flush;
|
||||
@@ -545,12 +564,33 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||
}
|
||||
ShowWindow(hWnd, SW_SHOW);
|
||||
|
||||
launch_mode = BTFrontEnd_LastLaunchMode();
|
||||
int secs = BTFrontEnd_LastMissionSeconds();
|
||||
const char *ov = getenv("BT_MISSION_SECONDS");
|
||||
if (ov != 0) secs = atoi(ov);
|
||||
BTLocalConsole_Install(secs);
|
||||
std::cout << "[frontend] menu LAUNCH -> marshal armed (" << secs << "s)"
|
||||
<< std::endl << std::flush;
|
||||
|
||||
if (launch_mode == 2)
|
||||
{
|
||||
// LOBBY MEMBER: no local egg -- the mission arrives over the wire
|
||||
// from the host (the lobby already registered the mesh peers).
|
||||
// Become a network pod on the session port; the host's marshal owns
|
||||
// the clock, and console-loss ends our mission when the host stops.
|
||||
L4Application::SetNetworkCommonFlatAddress(1501);
|
||||
gConsoleLossEndsMission = True;
|
||||
std::cout << "[frontend] lobby MEMBER -> network pod on :1501"
|
||||
<< std::endl << std::flush;
|
||||
}
|
||||
else
|
||||
{
|
||||
// SOLO or LOBBY HOST: the egg was built locally and the in-process
|
||||
// marshal owns the mission clock (the host is also the console). A
|
||||
// host additionally joins the mesh on the session port.
|
||||
if (launch_mode == 1)
|
||||
L4Application::SetNetworkCommonFlatAddress(1501);
|
||||
BTLocalConsole_Install(secs);
|
||||
std::cout << "[frontend] menu LAUNCH (" << (launch_mode == 1 ? "host" : "solo")
|
||||
<< ") -> marshal armed (" << secs << "s)" << std::endl << std::flush;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
@@ -606,8 +646,19 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||
// restarted the pod per mission. A `-egg`/`-net` pass, or a mission that
|
||||
// ended some other way (window closed), just exits.
|
||||
//-------------------------------------------------------------------//
|
||||
if (front_end_mode && BTLocalConsole_MissionCompleted() && IsWindow(hWnd))
|
||||
// The mission ran (not the menu-closed early return) if we front-end-moded
|
||||
// and the window still lives (a user window-close destroys hWnd -> quit, no
|
||||
// relaunch). Solo/host end via the local marshal; a member ends when the
|
||||
// host stops the race (console-loss), so it has no local completion flag.
|
||||
bool mission_ran = front_end_mode && IsWindow(hWnd)
|
||||
&& (launch_mode == 2 || BTLocalConsole_MissionCompleted());
|
||||
if (mission_ran)
|
||||
{
|
||||
// Distribute (host) or collect (member) the shared score sheet over the
|
||||
// lobby so every pod shows the same board; solo needs neither.
|
||||
if (launch_mode == 1) BTLobby_PushRaceResults();
|
||||
else if (launch_mode == 2) BTLobby_PullRaceResults();
|
||||
|
||||
// Scoreboard first (kills/deaths snapshotted at the stop), then relaunch.
|
||||
ShowWindow(hWnd, SW_HIDE);
|
||||
BTFrontEnd_ShowResults();
|
||||
|
||||
Reference in New Issue
Block a user