Skip to content

Steam friends: make Join work — read rich presence from field 71, support lobby and server joins - #10

Open
Leb-Sun wants to merge 2 commits into
steam-launch-optionsfrom
steam-friend-join
Open

Steam friends: make Join work — read rich presence from field 71, support lobby and server joins#10
Leb-Sun wants to merge 2 commits into
steam-launch-optionsfrom
steam-friend-join

Conversation

@Leb-Sun

@Leb-Sun Leb-Sun commented Aug 2, 2026

Copy link
Copy Markdown
Owner

Join never appeared in the friends drawer. The cause was in the persona-state parser:
CMsgClientPersonaState.Friend field 25 was being read as the rich-presence submessage,
but 25 is steamid_source (a fixed64). Rich presence is field 71. Every friend therefore
came back with an empty connect string, and isJoinable — which required exactly that — was
never true.

Parsing

  • Read rich presence from field 71; field 25 is left to the skip path.
  • Parse the other join sources Steam sends: game_lobby_id (73), game_server_ip (4)
    and game_server_port (5).
  • These three are Option<..> rather than plain integers so the merge can tell absent
    (keep what we have) from an explicit 0 (the server cleared it). Persona pushes are
    partial, so collapsing the two loses joinability on unrelated updates.

Stateful merge

Rich presence and lobby id have no "cleared" wire form. Without handling that, a friend who
switches games keeps the previous game's join data and Join offers a stale target. When a
push changes game_played_app_id, rich presence, lobby id and game-server fields are cleared
before the new values are applied.

Choosing what to join

SteamFriendEntry.joinArgs mirrors Steam's own precedence:

  1. the rich-presence connect command line,
  2. otherwise +connect_lobby <lobby_id> for an open lobby,
  3. otherwise +connect <ip>:<port> for a game server.

isJoinable now keys off joinArgs instead of the connect string alone, which is what lets
open-lobby games (no connect in rich presence) offer Join at all.

connect is friend-controlled and ends up on a Windows command line, so it is filtered to
drop control characters and double quotes before use. game_server_ip arrives host-order, so
the high byte is the first octet.

UI

The Join button additionally requires the game to be installed — previously it could be
offered for a game the user does not have.

Delivery

The second commit forwards the join args on the native LaunchApp path, which builds the
game's command line from localconfig rather than the launcher's argv, so a join has to ride
that too. The argv and ColdClient paths already carried it via appendSteamJoinConnect.

Tests

Added to the Rust unit tests: field 25 as steamid_source is skipped and does not populate
rich presence; lobby and game-server fields parse; an explicit zero lobby id is treated as
present-and-cleared rather than absent; lobby state survives a partial persona update and
clears when the friend changes game.

Base

Stacked on steam-launch-options (upstream WinNative-Emu#600). The delivery commit touches the
localconfig block introduced there; the parsing and UI work does not depend on it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant