Files
BT411/game/glass/btl4lobby.hpp
T
Joe DiPrimaandClaude Opus 5 2df1369168 #116 THE REAL STEAM CAUSE: experience never rode the lobby -- joiners' pages were authored by the HOST as the "veteran" fallback
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 in
3109cfc patched 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).  The 3109cfc join-trim selector stays: correct for mode=join.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-02 10:50:19 -05:00

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);