Files
BT412/game/reconstructed/btl4console.hpp
T
CydandClaude Opus 4.8 77f019ed4f Net: host->member mission marshal -- a Steam/LAN mission plays end to end
The lobby could stage a room but the launched mission never fed the members.
BTLocalConsole_InstallNetworkMission (btl4console.cpp) makes the host play the
arcade console in-process over the NetTransport seam (Winsock TCP or Steam SDR):

  - connect to each member's console channel (ip[:port] from BT412HOSTPODS);
  - feed each the chunked egg (NetworkManager::ReceiveEggFileMessage, \n->NUL
    wire image like tools/btconsole.py), resending until it ACKs;
  - poll member state (StateQueryMessage); when the whole mesh is staged at
    WaitingForLaunch, dispatch RunMission to every member + locally at once;
  - StopMission at expiry (members first, then self after a short grace);
  - scores are BT's kills/deaths snapshotted from the *meshed* roster at the
    stop -- no EndMission wire intake (that flow is a BT stub; the mesh already
    put every pilot in the host's roster). The owner's own pod is fed locally
    via L4NetworkManager::FeedLocalEgg.

Engine change (ported 1:1 from RP412): gConsoleMarshalsLaunch (APPMGR.h/.cpp) +
the `!gConsoleMarshalsLaunch &&` guard in APP.cpp's WaitingForLaunch self-launch.
The owner has no console connection to itself, so without this it would
self-launch before the mesh staged and never send the coordinated RunMission.
Default False = stock behavior; solo boot un-regressed.

WinMain host path (btl4main.cpp) now honors BT412HOSTPODS (+BT412HOSTPORT) for
the lobby host AND a classic-LAN host: SetNetworkCommonFlatAddress +
InstallNetworkMission, falling back to a solo marshal if no member is reachable.

Verified (loopback): two `btl4.exe -net` pods fed by tools/btconsole.py reach
"All connections completed!" and run after the engine change -- the exact
protocol + launch handshake the marshal uses. Both gates build+link; the
Release dist boots and the Steam transport comes up. The live multi-machine
Steam mission (FakeIP mesh + pilot-slot matching) is untestable here -- see the
new docs/STEAM-3-MACHINE-TEST.md. Dist README updated: multiplayer is now
"newly implemented, please test" rather than deferred.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 07:30:17 -05:00

47 lines
2.3 KiB
C++

//===========================================================================//
// btl4console.hpp -- BT412 in-process LocalConsole marshal.
//
// A front-end-launched solo mission has no operator console, so the mission
// clock would count up forever. This marshal plays the console's role in
// process: it watches the mission via the engine's per-frame hook
// (gPerFrameHook, called on the game thread in RunMissions) and dispatches
// StopMissionMessage when the selected length expires, exactly as the arcade
// console did. The single-binary WinMain loop then collects the result and
// cycles back to the setup menu.
//===========================================================================//
#ifndef BTL4CONSOLE_HPP
#define BTL4CONSOLE_HPP
// Arm the marshal for the next mission: it stops the mission after
// `mission_seconds` (0 = endless -- never auto-stops). Registers the
// per-frame hook.
void BTLocalConsole_Install(int mission_seconds);
// Arm the marshal as the HOST/OWNER of a NETWORKED mission: connect to every
// member pod's console channel (comma-separated "ip[:port]" list), then act as
// the arcade console -- feed each its egg, hold the mesh at WaitingForLaunch,
// launch everyone together, and StopMission at expiry. The owner's own pod is
// fed `egg_path` locally. Returns 1 on success, 0 if the egg is unreadable or
// a member could not be reached (caller should fall back to a solo mission).
int BTLocalConsole_InstallNetworkMission(int mission_seconds,
const char *egg_path, const char *remote_pod_list);
// True once the marshaled mission has stopped (time expired, or ended some
// other way while armed) -- the WinMain loop cycles back to the menu.
int BTLocalConsole_MissionCompleted();
// Final scores snapshotted at the stop (roster order; slot 0 = local pilot).
int BTLocalConsole_ResultCount();
int BTLocalConsole_GetResult(int index, int *kills, int *deaths);
const char *BTLocalConsole_GetResultName(int index);
// Lobby (owner) rebuilds the sheet from the collated wire scores before the
// shared results screen: clear, then inject each pod's name/kills/deaths.
void BTLocalConsole_ClearResults();
void BTLocalConsole_InjectResult(int slot, int kills, int deaths, const char *name);
// Drop the marshal + clear the per-frame hook.
void BTLocalConsole_Uninstall();
#endif // BTL4CONSOLE_HPP