The other half of the setup-page-as-room work, both halves Cyd's ask. JOIN STEAM GAME now sits down where it stands. The mission column - scenario buttons and the track, time, weather and length drop-downs - greys out and MIRRORS the host: the owner's published setup is mapped from display names back to catalog indices on every heartbeat, so a member watches the host change the track from inside their own setup screen. The right column stays theirs - callsign, role, vehicle, colour, badge, recording - and republishes as they change it, so the host's roster tracks them the same way. LAUNCH GAME reads WAITING FOR THE HOST and answers to nobody; the go arrives through the same timer, registers the peers, and leaves the menu as a member launch. JOIN becomes LEAVE LOBBY while seated. The room screen is now unused by both roles - kept compiled, but nobody's flow reaches it. A member's launch also now sets the RECORDING flag from its own pick. Nothing on the member path ever set it before - the same published-but-never-acted-on seam as the member cam - so a member who ticked RECORDING recorded nothing, all the way back to the feature landing. One host at a time, while the flow is young: HOST STEAM GAME first runs the same worldwide search joining uses, and if an RP412 lobby is already open anywhere it refuses with A LOBBY IS ALREADY OPEN - JOIN IT rather than opening a second room nobody can tell from the first. Check-then-create is not airtight against two people clicking in the same breath, but for a playtest group on voice it is the rule that was asked for. If the host leaves, ownership would migrate silently and turn some member's page into a host's - the member poll treats inheriting ownership as THE LOBBY CLOSED and steps out instead. The old modal exits are gone with it: steamAction, the post-loop RPL4Lobby_Join call, and the member's room re-entry path. The menu's modal loop now ends only at launch or close, whoever you are. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
145 lines
5.0 KiB
C
145 lines
5.0 KiB
C
#pragma once
|
|
|
|
#include "..\munga\style.h"
|
|
|
|
//########################################################################
|
|
//########################### RPL4 Steam Lobby ###########################
|
|
//########################################################################
|
|
//
|
|
// The multiplayer front door (docs/RP412-FRONTEND-DESIGN.md section 3):
|
|
// an ISteamMatchmaking lobby stands in for the arcade's Site Management
|
|
// screen. Every member publishes its FakeIP + fake ports + persona +
|
|
// loadout as lobby member data; the owner is the console. Launching
|
|
// writes a "go" roster into lobby data - each pod registers every
|
|
// peer with the Steam transport and enters the race, the owner
|
|
// through the hosted-race path (it builds the egg and marshals), the
|
|
// members as network pods waiting for the owner's console connection.
|
|
//
|
|
// The lobby OBJECT outlives races - that is the point of the single
|
|
// binary. After a race everyone lands back in the room for the next
|
|
// launch.
|
|
//
|
|
// Compiled to stubs without RP412_STEAM.
|
|
//
|
|
enum RPL4LobbyOutcome
|
|
{
|
|
LobbyRoomLeft = 0, // player left the lobby - back to the menu
|
|
LobbyRoomClosed, // window went away - quit
|
|
LobbyLaunchHost, // owner launched: hosted-race path is primed
|
|
LobbyLaunchMember // owner launched: enter the race as a pod
|
|
};
|
|
|
|
// True when the Steam transport is up (lobby UI is offered).
|
|
Logical
|
|
RPL4Lobby_Available();
|
|
|
|
// True when this build has Steam and environ.ini asked for it, whether
|
|
// or not it actually came up. The menu offers the lobby buttons on this
|
|
// and greys them out on Available() - a player who turned Steam on and
|
|
// then launched without the client running should be told so, not left
|
|
// looking at a menu that quietly has two fewer buttons than the last
|
|
// time they saw it.
|
|
Logical
|
|
RPL4Lobby_Configured();
|
|
|
|
// True while we sit in a lobby (races return to the room).
|
|
Logical
|
|
RPL4Lobby_InRoom();
|
|
|
|
//------------------------------------------------------------------------
|
|
// Hosting, from the setup menu.
|
|
//
|
|
// The host never leaves the configuration page: HostOpen claims the lobby
|
|
// and returns immediately, the menu keeps showing (and changing) the
|
|
// mission, joiners appear under GAME LENGTH via RosterLines, and LAUNCH
|
|
// GAME goes through HostLaunch. The room screen is for members only.
|
|
//------------------------------------------------------------------------
|
|
|
|
enum RPL4LobbyHostOpen
|
|
{
|
|
HostOpenFailed = 0, // Steam said no (or is not there)
|
|
HostOpenCreated, // the lobby is ours (also: already was)
|
|
HostOpenLobbyExists // one host at a time - join the open one
|
|
};
|
|
|
|
// Create the lobby and publish our row + the mission setup. Does not
|
|
// open any window. Refuses when an RP412 lobby is already open anywhere:
|
|
// one host at a time while the flow is young.
|
|
int
|
|
RPL4Lobby_HostOpen();
|
|
|
|
enum RPL4LobbyJoinOpen
|
|
{
|
|
JoinOpenNothingFound = 0, // no open lobby, or Steam said no
|
|
JoinOpenJoined, // seated; our row is published
|
|
JoinOpenWrongBuild // bounced at the door (dialog shown)
|
|
};
|
|
|
|
// Find the open lobby and sit down in it. Does not open any window: the
|
|
// setup menu stays up, mission column greyed and mirroring the host.
|
|
int
|
|
RPL4Lobby_JoinOpen(HWND main_window);
|
|
|
|
enum RPL4LobbyMemberPoll
|
|
{
|
|
MemberPollNothing = 0, // keep waiting
|
|
MemberPollLaunch, // the go arrived; peers registered - launch
|
|
MemberPollClosed // the lobby is over (host left / mismatch)
|
|
};
|
|
|
|
// A seated member's heartbeat question: anything to act on?
|
|
int
|
|
RPL4Lobby_MemberPoll();
|
|
|
|
// The host's published mission setup as display names (each buffer at
|
|
// least 48 bytes). Empty strings before the first publish arrives.
|
|
void
|
|
RPL4Lobby_GetSetup(
|
|
char *scenario, char *map, char *time_of_day,
|
|
char *weather, char *length);
|
|
|
|
// True when we are in a lobby we own.
|
|
Logical
|
|
RPL4Lobby_IsOwner();
|
|
|
|
// Run the Steam callbacks once - the menu's timer calls this so member
|
|
// joins/leaves and their data show up while no room screen is pumping.
|
|
void
|
|
RPL4Lobby_Pump();
|
|
|
|
// Republish our member row and (as owner) the mission setup. Call after
|
|
// the host changes anything on the menu, so members' rooms track it.
|
|
void
|
|
RPL4Lobby_PublishSetup();
|
|
|
|
// The roster as display lines ("callsign vehicle [cam|WRONG BUILD]").
|
|
// Returns the number written, 0 when not in a lobby.
|
|
int
|
|
RPL4Lobby_RosterLines(char lines[][48], int max_lines);
|
|
|
|
// The owner's go: verify everyone, publish the roster, prime the hosted
|
|
// race. False (and a log line saying who) when the room is not ready.
|
|
Logical
|
|
RPL4Lobby_HostLaunch();
|
|
|
|
// Leave the lobby and clear the hosted-race environment.
|
|
void
|
|
RPL4Lobby_Leave();
|
|
|
|
// Find-and-join a lobby, then run the room screen (members).
|
|
int
|
|
RPL4Lobby_Join(HINSTANCE instance, HWND main_window);
|
|
|
|
// Re-enter the room of the lobby we are already in (post-race).
|
|
int
|
|
RPL4Lobby_Room(HINSTANCE instance, HWND main_window);
|
|
|
|
// Post-race score sheet: the owner publishes its console's results
|
|
// into lobby data; members pull them into the local results intake so
|
|
// the same results screen shows everywhere. Both are no-ops when not
|
|
// in a lobby (or not the respective role).
|
|
void
|
|
RPL4Lobby_PushRaceResults();
|
|
void
|
|
RPL4Lobby_PullRaceResults();
|