Steam: the lobby + IDENTITY-TOKEN roster -- internet MP code-complete (step 4c)

NEW gated (BT_STEAM) game/glass/btl4lobby: an ISteamMatchmaking room replacing
the arcade Site-Management screen -- host creates (lobby data btl4=1), members
join by filter, pilots publish name/mech/color, the host ENTER mints the
roster and signals GO.

THE FAKEIP LESSON (live-verified, prior-art assumption DISPROVEN): a fresh
process gets a DIFFERENT FakeIP, so menu-time fake addresses go stale by
mission time -- the first cycle timed out connecting to its own stale address.
Redesign: roster addresses are opaque ipv4-shaped TOKENS (169.254.77.N with
ports 1501/1502) minted by the host at GO, mapped to Steam IDENTITIES;
connections ride ConnectP2P(identity, channel) with console=0/game=1 virtual
ports; the map reaches mission processes via env (BT_FE_MYFAKE +
BT_FE_STEAMMAP); the GetMyAddress seam feeds the pod its own token for roster
self-match; CheckSocket reports peers by token.  L4STEAMNET reworked (no
FakeIP allocation at all); the marshal gained the Steam-wire branch.

Verified single-machine (ON/ON, live Steam): menu -> HOST STEAM LOBBY ->
room -> GO -> token map minted -> egg roster carries the token -> mission
process up with 1 roster token incl. self -> pod self-matches -> stock
console ladder -> mission RUNS (46 ticks).  Remaining: the live 2-account
cross-machine session (docs/STEAM_TEST.md).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-07-18 00:03:17 -05:00
co-authored by Claude Fable 5
parent 48ede2f7d7
commit f703bb1d56
11 changed files with 875 additions and 124 deletions
+67 -2
View File
@@ -4,6 +4,9 @@
//###########################################################################
#include "btl4fe.hpp"
#ifdef BT_STEAM
#include "btl4lobby.hpp"
#endif
#include <windows.h>
#include <stdio.h>
@@ -25,7 +28,11 @@ static const char *kVehicles[] = { "bhk1", "madcat", "ava1" };
static const char *kColors[] = { "White", "Black", "Crimson" };
static const char *kModes[] =
{ "SOLO MISSION (networked)", "RAW SOLO (-egg, endless)",
"HOST LAN", "JOIN LAN" };
"HOST LAN", "JOIN LAN",
#ifdef BT_STEAM
"HOST STEAM LOBBY", "JOIN STEAM LOBBY",
#endif
};
static const int kPorts[] = { 1501, 1601, 1701, 1801 };
#define COUNT(a) ((int)(sizeof(a)/sizeof((a)[0])))
@@ -720,10 +727,68 @@ int
}
break;
default: // JOIN LAN: plain -net pod; the host's marshal feeds us
case 3: // JOIN LAN: plain -net pod; the host's marshal feeds us
spec->mode = BTFeLaunchJoinLan;
spec->eggPath[0] = 0; // no egg written; host provides
return 0;
#ifdef BT_STEAM
case 4: // HOST STEAM LOBBY: the room fills the roster (self first)
{
BTLobbyRoster roster;
if (BTLobby_HostAndRoom(self.name, self.vehicle, self.color,
&roster, spec->steamMyToken, sizeof(spec->steamMyToken),
spec->steamMap, sizeof(spec->steamMap)) != 0 ||
roster.memberCount == 0)
{
return 1; // cancelled / Steam unavailable
}
spec->mode = BTFeLaunchHostSteam;
//
// Roster -> egg pilots (FAKE game addresses; self is pilot 1)
// + the marshal pod list (self over TCP loopback, members at
// their FAKE console addresses over the Steam wire).
//
mission.pilotCount = 0;
sprintf(spec->podList, "127.0.0.1:%d", console_port);
for (int m = 0; m < roster.memberCount && m < 8; ++m)
{
const BTLobbyMember &member = roster.members[m];
BTFePilot &pilot = mission.pilots[mission.pilotCount++];
strncpy(pilot.name, member.name, sizeof(pilot.name) - 1);
strncpy(pilot.vehicle,
member.vehicle[0] ? member.vehicle : kVehicles[0],
sizeof(pilot.vehicle) - 1);
strncpy(pilot.color,
member.color[0] ? member.color : kColors[0],
sizeof(pilot.color) - 1);
sprintf(pilot.address, "%s:%d",
member.fakeAddress, member.gamePort);
if (!member.isSelf)
{
char entry[64];
sprintf(entry, ",%s:%d",
member.fakeAddress, member.consolePort);
strcat(spec->podList, entry);
}
}
}
break;
case 5: // JOIN STEAM LOBBY: wait for GO, then a Steam-wire pod
if (BTLobby_JoinAndWait(self.name, self.vehicle, self.color,
spec->steamMyToken, sizeof(spec->steamMyToken),
spec->steamMap, sizeof(spec->steamMap)) != 0)
{
return 1;
}
spec->mode = BTFeLaunchJoinSteam;
spec->eggPath[0] = 0;
return 0;
#endif
default:
return 1;
}
if (BTFeMission_WriteEgg(&mission, spec->eggPath) != 0)