The user's question broke my first story: "did lynx host tho?" He did (Oracle joined LYNX's lobby that night) -- but more importantly the affected players' logs read mode=steam, which gets the FULL menu, so the FeJoinOnly fix in3109cfcpatched a real gap (mode=join) that is NOT the path the affected trio ran. Oracle COULD see and cycle the selector; it still didn't matter. Traced: * The steam lobby serialized exactly three member fields: nm / vh / cl. Experience never travelled. * The steam HOST rebuilds mission.pilots[] from the lobby roster (name/vehicle/color only), so every non-self page has EMPTY experience -- and BTFeMission_WriteEgg stamps the "veteran" fallback on empty. * The steam JOINER writes NO egg at all (spec->eggPath[0]=0); his mission arrives from the HOST's console feed -- i.e. the host's egg, where HIS page says veteran no matter what his own console shows. * The host's own page keeps his menu choice only as slot-0 residue of the pre-roster self fill -- why BOTH hosts (Sauron AND Lynx) were clean while all three joiners heated in "standard". FIX: experience is now published as lobby member data ("xp") beside nm/vh/cl, unpacked into BTLobbyMember, and stamped onto each member's egg page in the host's roster loop. Both exported lobby entry points + PublishSelf gain the parameter; the fe passes the local menu selection. An older client in the lobby simply has no "xp" -- the veteran fallback applies to THAT member only, exactly the pre-fix behavior, so mixed-build lobbies do not break. Per-player mixing (the original design, per the user: the sysop set each user's tier; mixed matches were legal) now works over steam end to end: each member's OWN choice -> lobby -> the host-authored egg page -> the console feed -> that node's master player. VERIFICATION BOUNDARY: builds both configs; the chain is code-traced; the lobby legs need a real Steam session -- field re-test is a JOINER selecting Standard and logging [exp] experience=1 heatModelOn=0 (plus the [fe] line on both sides). The3109cfcjoin-trim selector stays: correct for mode=join. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
69 lines
2.5 KiB
C++
69 lines
2.5 KiB
C++
#pragma once
|
|
|
|
//###########################################################################
|
|
//
|
|
// btl4lobby -- the Steam lobby (BT_STEAM only): an ISteamMatchmaking room
|
|
// replacing the arcade Site-Management screen for internet MP testing.
|
|
//
|
|
// The MENU process runs the lobby (the Steam transport is installed there
|
|
// first, so each member's FakeIP is known): members publish their fake
|
|
// address/ports + pilot identity as lobby member data; the host's room
|
|
// screen lists members and its ENTER writes the GO signal; everyone then
|
|
// relaunches into the mission -- the host with the marshal armed against
|
|
// the members' fake CONSOLE addresses, members as plain -net pods with
|
|
// BT_STEAM_NET=1 waiting to be fed over the Steam wire.
|
|
//
|
|
// Known limitation (documented): the lobby object does not survive the
|
|
// per-mission process relaunch -- after a mission everyone re-joins from
|
|
// the menu. FakeIP stability across the immediate relaunch is assumed
|
|
// (Valve persists assignments per app+account); the live 2-account test
|
|
// is the step's exit criterion (docs/STEAM_TEST.md).
|
|
//
|
|
//###########################################################################
|
|
|
|
struct BTLobbyMember
|
|
{
|
|
char name[32];
|
|
char fakeAddress[48]; // the minted roster TOKEN ip
|
|
int consolePort; // token console port (1501)
|
|
int gamePort; // token game port (1502)
|
|
char vehicle[16];
|
|
char color[16];
|
|
char experience[16]; // #116: per-player by design (sysop-set
|
|
// in the pod; mixed matches legal) --
|
|
// without it on the wire, the host's
|
|
// egg authored every JOINER as the
|
|
// WriteEgg "veteran" fallback
|
|
int isSelf;
|
|
unsigned long long steamID;
|
|
};
|
|
|
|
struct BTLobbyRoster
|
|
{
|
|
int memberCount;
|
|
BTLobbyMember members[8];
|
|
};
|
|
|
|
//
|
|
// Host: create the lobby, run the room screen, on ENTER write GO and fill
|
|
// the roster (self first). Returns 0 = launch, nonzero = cancelled.
|
|
//
|
|
int
|
|
BTLobby_HostAndRoom(
|
|
const char *pilot_name, const char *vehicle, const char *color,
|
|
const char *experience,
|
|
BTLobbyRoster *roster_out,
|
|
char *my_token_out, int my_token_capacity,
|
|
char *steam_map_out, int steam_map_capacity);
|
|
|
|
//
|
|
// Member: find + join a lobby, run the room screen, return when the host
|
|
// signals GO. Returns 0 = launch, nonzero = cancelled / none found.
|
|
//
|
|
int
|
|
BTLobby_JoinAndWait(
|
|
const char *pilot_name, const char *vehicle, const char *color,
|
|
const char *experience,
|
|
char *my_token_out, int my_token_capacity,
|
|
char *steam_map_out, int steam_map_capacity);
|