Walk-up callsign/mech request: join menu -> relay -> the session egg
The 1995 front-desk conversation, over the internet. join.bat/
join_lan.bat now open a JOIN-GAME menu (the FE in BT_FE_JOIN trim:
CALLSIGN edit + the 18-mech list + JOIN); the choice relaunches into the
normal join with BT_CALLSIGN/BT_MECH env, rides the relay SEAT_REQUEST
as {callsign NUL mech NUL} (empty payload = roster defaults, wire-
compatible), and the relay validates the mech tag, HOLDS egg delivery
until every pod's console pad is connected, rewrites the egg via
eggmodel (vehicle= + rasterized callsign bitmaps, graceful no-PySide6
fallback) and streams it to all pads -- so every player's egg copy
carries every player's callsign.
The hold is gated on CONSOLE-PAD count, not game-side registration: a
pod HELLOs only after parsing the egg's roster, so a registration gate
deadlocks (hit live in the first run; pods animate in WAITING FOR
MISSION ASSIGNMENT during the hold).
Verified 2-node e2e (env-injected requests): thor/vulture requested over
roster defaults bhk1/ava1 -> relay held 1/2, released at 2/2, rewrote
both seats (relay log), the delivered egg carries vehicle=thor/vulture +
name=VIPER/MONGOOSE, both pods launched and built [cyl] tables for both
requested mechs. Join-menu layout screenshot-verified; the menu's
click-through relaunch awaits live human verification.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
eb618fe9e6
commit
fcedc046cf
+63
-11
@@ -588,6 +588,25 @@ static int
|
||||
return s;
|
||||
}
|
||||
|
||||
//
|
||||
// BT_FE_JOIN=1 (join.bat / join_lan.bat): the JOIN-GAME menu -- the walk-up
|
||||
// desk conversation of the 1995 centers, over the internet. Only CALLSIGN +
|
||||
// MECH are the player's to pick (the operator owns the mission + the rest of
|
||||
// the loadout); the choice rides the relay SEAT_REQUEST and the relay writes
|
||||
// it into the session egg (btconsole.py).
|
||||
//
|
||||
static int
|
||||
FeJoinOnly()
|
||||
{
|
||||
static int s = -1;
|
||||
if (s < 0)
|
||||
{
|
||||
const char *e = getenv("BT_FE_JOIN");
|
||||
s = (e != NULL && *e != '0') ? 1 : 0;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
static int
|
||||
GroupSize(int group)
|
||||
{
|
||||
@@ -719,6 +738,15 @@ static void
|
||||
{
|
||||
menu.itemCount = 0;
|
||||
int y;
|
||||
if (FeJoinOnly())
|
||||
{
|
||||
// JOIN trim: the mech list + the JOIN button; callsign is the edit
|
||||
// control (repositioned in BTFrontEnd_Run). Everything else is the
|
||||
// operator's call.
|
||||
y = MenuTopY; AddGroup(GroupVehicle, MenuCol2X, &y);
|
||||
AddButton(GroupLaunch, MenuCol5X, MenuClientH - 190, 220, 52);
|
||||
return;
|
||||
}
|
||||
// col1: the mission
|
||||
y = MenuTopY; AddGroup(GroupMap, MenuCol1X, &y);
|
||||
AddGroup(GroupScenario, MenuCol1X, &y);
|
||||
@@ -843,8 +871,10 @@ static void
|
||||
|
||||
HFONT old_font = (HFONT)SelectObject(dc, menu.titleFont);
|
||||
RECT title_rect = { MenuCol1X, 14, client.right - 24, 54 };
|
||||
DrawMenuText(dc, "BATTLETECH -- MISSION CONSOLE", &title_rect,
|
||||
kGreenBright, DT_LEFT | DT_TOP | DT_SINGLELINE);
|
||||
DrawMenuText(dc,
|
||||
FeJoinOnly() ? "BATTLETECH -- JOIN GAME"
|
||||
: "BATTLETECH -- MISSION CONSOLE",
|
||||
&title_rect, kGreenBright, DT_LEFT | DT_TOP | DT_SINGLELINE);
|
||||
|
||||
SelectObject(dc, menu.textFont);
|
||||
|
||||
@@ -896,12 +926,15 @@ static void
|
||||
// Edit labels (the controls themselves are child windows in col5).
|
||||
//
|
||||
RECT label = { MenuCol5X, MenuNameLabelY, MenuCol5X + 240, MenuNameLabelY + MenuRowH };
|
||||
DrawMenuText(dc, "PILOT NAME", &label, kGreenDim,
|
||||
DT_LEFT | DT_VCENTER | DT_SINGLELINE);
|
||||
label.top = MenuPeersLabelY;
|
||||
label.bottom = label.top + MenuRowH;
|
||||
DrawMenuText(dc, "LAN PEERS (host: ip:port,...)", &label, kGreenDim,
|
||||
DT_LEFT | DT_VCENTER | DT_SINGLELINE);
|
||||
DrawMenuText(dc, FeJoinOnly() ? "CALLSIGN" : "PILOT NAME", &label,
|
||||
kGreenDim, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
|
||||
if (!FeJoinOnly())
|
||||
{
|
||||
label.top = MenuPeersLabelY;
|
||||
label.bottom = label.top + MenuRowH;
|
||||
DrawMenuText(dc, "LAN PEERS (host: ip:port,...)", &label, kGreenDim,
|
||||
DT_LEFT | DT_VCENTER | DT_SINGLELINE);
|
||||
}
|
||||
|
||||
//
|
||||
// Buttons (framed, RP412 style).
|
||||
@@ -911,7 +944,7 @@ static void
|
||||
{
|
||||
const MenuItem &item = menu.items[i];
|
||||
const char *text =
|
||||
(item.group == GroupLaunch) ? "L A U N C H" :
|
||||
(item.group == GroupLaunch) ? (FeJoinOnly() ? "J O I N" : "L A U N C H") :
|
||||
(item.group == GroupSteamHost) ? "HOST STEAM LOBBY" :
|
||||
(item.group == GroupSteamJoin) ? "JOIN STEAM LOBBY" : NULL;
|
||||
if (text == NULL)
|
||||
@@ -926,7 +959,9 @@ static void
|
||||
DeleteObject(frame);
|
||||
|
||||
RECT help = { MenuCol1X, client.bottom - 30, client.right - 24, client.bottom - 6 };
|
||||
DrawMenuText(dc, "click to select ENTER = launch ESC = quit",
|
||||
DrawMenuText(dc,
|
||||
FeJoinOnly() ? "click to select ENTER = join ESC = quit"
|
||||
: "click to select ENTER = launch ESC = quit",
|
||||
&help, kGreenDim, DT_LEFT | DT_TOP | DT_SINGLELINE);
|
||||
|
||||
SelectObject(dc, old_font);
|
||||
@@ -1037,7 +1072,8 @@ int
|
||||
DWORD style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
|
||||
AdjustWindowRect(&frame_rect, style, FALSE);
|
||||
menu.window = CreateWindowW(
|
||||
L"BTFrontEndWnd", L"BattleTech - Mission Console",
|
||||
L"BTFrontEndWnd",
|
||||
FeJoinOnly() ? L"BattleTech - Join Game" : L"BattleTech - Mission Console",
|
||||
style, 100, 80,
|
||||
frame_rect.right - frame_rect.left, frame_rect.bottom - frame_rect.top,
|
||||
NULL, NULL, GetModuleHandleW(NULL), NULL);
|
||||
@@ -1067,6 +1103,10 @@ int
|
||||
SendMessageW(menu.peersEdit, WM_SETFONT, (WPARAM)menu.textFont, TRUE);
|
||||
SetWindowTextA(menu.nameEdit, pilot_name);
|
||||
SetWindowTextA(menu.peersEdit, peers);
|
||||
if (FeJoinOnly())
|
||||
{
|
||||
ShowWindow(menu.peersEdit, SW_HIDE); // operator's concern, not the joiner's
|
||||
}
|
||||
|
||||
ShowWindow(menu.window, SW_SHOW);
|
||||
SetForegroundWindow(menu.window);
|
||||
@@ -1104,6 +1144,18 @@ int
|
||||
//
|
||||
// Resolve the launch spec + write the egg.
|
||||
//
|
||||
if (FeJoinOnly())
|
||||
{
|
||||
// JOIN GAME: no egg, no port math -- the relay owns the session. The
|
||||
// callsign + mech request rides the SEAT_REQUEST payload (L4NET reads
|
||||
// BT_CALLSIGN / BT_MECH, set by WinMain from this spec).
|
||||
spec->mode = BTFeLaunchJoinRelay;
|
||||
strncpy(spec->joinCallsign, pilot_name[0] ? pilot_name : "Pilot",
|
||||
sizeof(spec->joinCallsign) - 1);
|
||||
strncpy(spec->joinVehicle, kVehicles[menu.selection[GroupVehicle]].key,
|
||||
sizeof(spec->joinVehicle) - 1);
|
||||
return 0;
|
||||
}
|
||||
int console_port = kPorts[menu.selection[GroupPort]];
|
||||
const RoleEntry &scenario = kScenarios[menu.selection[GroupScenario]];
|
||||
BTFeMission mission;
|
||||
|
||||
Reference in New Issue
Block a user