With RP412STEAM=1 but no Steam client, the lobby buttons were not drawn
at all - the menu simply had two fewer buttons than last time, with the
only explanation a line near the top of rpl4.log that scrolls past during
a normal startup. It reads as a broken build, and it cost someone a
puzzled look today.
The buttons are now laid out whenever environ.ini asks for Steam, and
greyed out when the wire did not come up, with STEAM NOT RUNNING above
them. Clicks on a greyed button do nothing - a dead control that still
fires would be worse than the silence it replaces.
Two conditions rather than one, so RPL4Lobby_Configured joins Available:
configured is the ini switch, available is whether the transport got a
FakeIP. Configured keeps the #ifdef in the lobby module, so a build
without the Steam SDK still shows no buttons at all rather than a pair
that can never work.
The notice does not fit inside a button - they are about sixteen
characters wide and "HOST STEAM GAME - STEAM NOT RUNNING" is more than
twice that, so appending it clipped mid-word. It goes on its own line
above the pair instead.
Verified both ways, with the Steam client up and with it unavailable:
bright and clickable, dim and inert.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The lobby capped at four, which is half a grid. The pod hall raced eight
and the egg builder already carries the owner plus maxExtraPilots, so
eight members fit with room to spare. CreateLobby now asks Steam for
eight and the roster arrays follow.
Checked what eight has to travel through before raising it: the go
roster is 43 bytes a member against an 800 byte buffer, the score sheet
41 against 600, and the pods list 21 against 512, so all three hold
eight with margin. The member side parses the go string with a cursor
rather than a fixed array, and RegisterRoster walks the count it is
given, so neither needed touching.
The layout is the part that could not just be renumbered. Rows were a
fixed sixteenth of the window, and eight of those ran off the bottom of
every window we support - the buttons are laid out upward from the
bottom edge while the roster runs down from the top, so the two meet in
the middle. The room now measures the band between the title and the
topmost button and sizes its rows to it, counted in half rows as
setup lines + gap + eight rows + gap + hint
so the row height falls out of the space actually available. It never
grows past the old sixteenth, so a two player lobby does not get circus
sized rows, and when the band cannot give eight rows the room the font
needs, the block is drawn in a font that does fit rather than letting
rows overlap.
The minimum row is the font cell plus two, not the cell plus an eighth.
That sounds like a detail and is not: at 1920x1080 the generous version
missed by one pixel and paid for it by dropping the conditions line out
of every football lobby, which is the one thing in the room nobody can
see for themselves.
Verified live on hosted lobbies at 1904x1041, and modelled across every
window size from 3440x1440 down to 800x480 in race and football, host
and member. Race keeps both setup lines everywhere; football, which
carries four stacked buttons, keeps both down to 1080 and drops to one
below that.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The room told you who was in it and nothing about what you were about to
fly into. Only the owner's menu decides the mission, so nobody else could
see the track or the conditions until the race had already started.
The owner now publishes its picks as lobby data (track, time of day,
weather, game length) and the room draws them under the title: the track
on its own line, the conditions under it. Published as display names
rather than catalog keys, because the map list differs between race and
football and resolving it at the source saves the room from knowing
which table a key came from.
Football also names the VTV now. The team sheet was team and position
only, but the vehicle still decides how someone plays the position, and
it was already travelling as member data, just never drawn. Both roster
rows now run keys back through the catalogs, so nobody reads bttlbrg
where Battle Barge belongs, and the rows widened from the middle half to
two thirds to carry three fields.
The setup lines are only taken if they fit. Buttons are laid out upward
from the bottom edge while the roster runs down from the top, so on a
short window the two extra lines would have pushed the roster into MY
TEAM. The room measures the gap first and takes two lines, one, or none.
Checked against every window size from 3440x1440 down to 640x400 in both
scenarios.
Verified live on a hosted lobby. Race shows the track, the conditions
line, and Battle Barge / Red. Football shows the same setup with Battle
Barge, Blue / Aqua, Crusher, tracking the MY TEAM and MY POSITION
buttons as they cycle.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Closes the gap left by the football commit. Members publish their
picks as lobby member data (tm/ps) alongside their loadout, and the
owner publishes the scenario (sc) so members know when the picks
matter. The lobby room turns into a team sheet: each member row shows
their team and position, and MY TEAM / MY POSITION buttons cycle the
local pick and republish it live, so everyone watches the sides fill
out before the host launches.
The egg builder honors explicit picks and only fills gaps:
- pilots who chose a team get it; the rest are spread across the
host team and one other so the sides stay balanced
- a team with no volunteer runner promotes its first UNPICKED member,
never overriding someone who chose crusher or blocker
- if two pilots on a team both claim runner, the first keeps it and
the second lines up
- colors stay derived: runner in the team runner color, everyone else
in the team color
Verified: a three-pilot egg puts the host on crusher in team color
with an unpicked teammate promoted to runner in runner color, the
other side gets its own runner, and the teams/pilots blocks group
correctly; the lobby room cycles picks and repaints the roster; both
scenarios still pass their single-player regressions.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
README.md rewritten around the lineage: Red Planet 4.10 on the
Tesla 1 pod platform, 4.11 the Win32 port, 4.12 the Steamification
of 4.11 - with the arcade-to-consumer replacement table, current
status (v4.12.1 verified on three machines), playing/building/docs
sections brought up to date.
And ahead of internet-wide beta testing: lobby search now applies the
worldwide distance filter - Steam defaults to roughly same-region
results, which would have hidden lobbies from cross-region testers
even though joining them works fine.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Round seven was the first complete Steam race: three machines, five
minutes, wall deaths respawning, the console ending the race on time,
and rematches launched from the same lobby. The one gap the run showed:
only the owner saw scores - members went straight back to the room.
The owner now publishes its console results (host, score, name, keyed
by the race nonce) into lobby data right after teardown; members pull
the sheet (waiting up to 8s for it to land), inject it into the local
results intake, and the same RACE RESULTS screen shows on every
machine before the room.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Round four reached one step from the race: eggs delivered, both
members ACKed with complete meshes, one member entered LoadingMission.
Two failures remained, both now fixed.
One: Steam reports incoming callers under locally-allocated ALIAS
FakeIPs, not their global ones - the owner accepted both mesh legs
but its identity check compared the alias against the egg address and
never counted the connections (no Connected to GameMachineHost on the
owner). The peer table now carries each member SteamID (lobby go
roster gained a field) and Accept resolves the caller identity back
to the global FakeIP the egg promised.
Two: mission load stalls the game thread for 10-30s with nothing
pumping, and Steam default 10s connected-timeout sheared every
connection mid-load (end reason 4001, rx ages 11.5-20.5s - right at
load duration). Connected timeout is now 90s; TCP never timed out an
idle arcade link and races pump every frame once running.
Self-test still green (ping, survives listener close).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
RPL4LOBBY implements the multiplayer front door on ISteamMatchmaking.
The setup menu grows HOST STEAM RACE / JOIN STEAM RACE buttons when
the Steam wire is live; hosting creates a tagged public lobby, joining
finds one. Every member publishes FakeIP + fake ports + persona +
loadout as member data; the room screen lists members (host marked)
and gives the owner a launch button.
Launching writes a nonced go-roster into lobby data. Each pod
registers every peer with the Steam transport (two-port peer table:
engine console/game ports map to Steam fake ports on connect) and
enters the race: the owner through the hosted-race path - it builds
the multi-pilot egg from real personas and loadouts and its console
marshals everyone - and members as network pods that boot straight
into WaitingForEgg for the owner to feed over the wire.
The lobby outlives races: members loop back through WinMain into the
room (no local console needed - MissionCompleted is waived for member
races), and the owner returns to the room after its results screen.
Leaving the lobby clears the hosted-race priming.
Verified on this box: menu buttons appear under RP412STEAM=1, hosting
creates a lobby on the Steam backend, the room runs and leaves back to
the menu; single-player cycling and the LAN hosted race both still
pass. Full three-account mesh test is next, on real hardware.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>