Repository navigation
EOSPlus+Steam friend-join: mainline generic LAN-emu fixes - #2
Merged
Merged
Conversation
…n read Fixes the splitux Satisfactory co-op join (E007 "unable to join user backend sessions"). Root cause, proven from logs: the host's EOS session grows from 17 to 27 attributes when it finishes loading the save (adds the gameplay attrs the join-migration requires), but the joiner reads the session ~2s before the complete copy reaches its discovery cache, commits to the stale 17-attr snapshot, and the migration fails so P2P never starts. The test bench masks this with a 15s launch stagger (host always fully loaded before the joiner searches); splitux launches instances together so the read lands inside the propagation gap every time. Two changes close the gap: - EOS_Sessions_UpdateSession now broadcasts the session over LAN discovery immediately on every create/update, instead of waiting for the next ~2s announce tick. The joiner's cache reflects the host's 27-attr session within milliseconds of the host producing it. - EOS_SessionDetails_CopyInfo re-pulls the latest advertised session from the live discovery cache (via a new back-pointer on the details handle + discovery_find_cached_session) when it has gained attributes, instead of returning the frozen search/Find-time snapshot. (cherry picked from commit 24f8b10)
EOS_LobbySearch_Find with a target_user_id filter only checked the lobby's members[] roster. LAN-broadcast lobbies carry just the owner on the wire (members[] is empty until the lobby is joined), so a search-by-user for the host — the common 'find friend's game / join by presence' path, e.g. StarRupture's join menu — always returned 0 results even though the lobby was discovered. Match the target user against the owner as well, so an owner-hosted wire-discovered lobby is found. (cherry picked from commit 9a02476)
Steam+EOS games (e.g. StarRupture) drive their friends/join browser off the *Steam* friends list: for each Steam friend they call EOS_Connect_GetExternalAccountMapping(type=STEAM, steam_id) to get the friend's ProductUserId, then attribute a discovered lobby to that friend. The LAN emulator never carried Steam IDs, so that lookup always failed and the browser showed 'No sessions available' even though the lobby search itself returned the host. Relay each instance's Steam ID (EOSLAN_STEAM_ID, set by the bench from the goldberg account_steamid) in the LAN user beacon, store it per-peer, and resolve it: GetExternalAccountMapping now dispatches type=STEAM to a new social_bridge_resolve_puid_by_steam (local + discovered peers). Generic to any Steam+EOS friends-driven join UI, not StarRupture-specific. Wire format: steam_id[24] added after puid in the user-beacon serialize/ parse; both peers run the same build so the format stays consistent. (cherry picked from commit 66c06a3)
A well-formed EpicAccountId is 32 hex chars; FromString was instead handing back the LOCAL user for any shorter/garbage string. Steam+EOS games bridging external accounts call FromString on a Steam ID string (e.g. the 17-char '76561198000000001') while building a friend's net id. Returning the local user there pairs a *remote* host's ProductUserId with the *joiner's* EpicAccountId, which violates UE's one-puid<->one-epic registry invariant (FUniqueNetIdEOSRegistry assert InEpicAccountId == FoundEpicAccountId) and hard-crashes the game the moment the Steam friends list is read. Return NULL (-> IsValid() false) like real EOS, so the caller treats the id as absent (PUID-only) rather than a conflicting epic. Surfaced by StarRupture once Steam->PUID external mapping started resolving. (cherry picked from commit 397931e)
Same wire-discovered-owner bug as lobby_search (9a02476), in the Sessions interface. SessionSearch_Find's target_user_id filter only scanned registered_players[], which is empty on LAN-discovered sessions (members aren't carried on the wire; owner_id is a process-local pointer, only owner_id_string survives). StarRupture's friends 'Join Game' browser does a per-friend Sessions search keyed on the friend's puid, so it returned 0 even though the friend was hosting -> 'No sessions available'. Match the session owner by string (owner_id_string vs ToString(target_user_id)). Added ACCEPT/REJECT logging to confirm whether the per-friend search is reached. (cherry picked from commit 9b2fb41)
Friends 'Join Game' in EOSPlus+Steam titles (e.g. StarRupture) is driven by EOS presence, not session/lobby search: the joiner enumerates Steam friends and calls EOS_Presence_CopyPresence(host) per friend. The host never touches the Presence interface — it creates a bPresenceEnabled EOS lobby with a CUSTOMJOININFO attribute and relies on real EOS auto-tying that lobby to its presence join-info. The emu only populated g_local_presence via SetJoinInfo/SetData, so the host's user beacon carried empty presence, the joiner's CopyPresence returned 0 records, and the browser showed 'No sessions available' despite the lobby being fully discoverable. Mirror a presence-enabled lobby into the local user's published presence: lobby id as join-info, lobby attributes as presence data records (join-critical keys CUSTOMJOININFO/MapName/conn-counts first, capped at MAX_PRESENCE_RECORDS). Wired on lobby create/update/join, cleared on leave/destroy. Gated by g_game_set_presence so games that drive presence directly (Satisfactory) are untouched. This is the EOS-side analog of the goldberg connect/Joinable auto-derive. (cherry picked from commit 8aa2337)
… hosts The first friend/presence notification (which triggers the game's one-shot FetchFriendInfoAsync + presence re-read) was held until the host had an EOS session_id. EOSPlus+Steam titles like StarRupture host via a presence-enabled lobby, not a session, so session_id is always empty: the hold never released, the friend was never announced as joinable, and the game never re-read CopyPresence after the lobby's 8 presence records arrived -> 'No sessions available' forever, even though the records were correctly relayed and cached. Also release the hold once the host's beacon carries presence records (record_count > 0), i.e. the presence-enabled lobby is fully populated. The one-shot fetch then still runs against complete data. (cherry picked from commit 0a5b50e)
…ords The host's presence-enabled lobby data now reaches the joiner (CopyPresence returns 8 records), but the game's CommonSession friend-search still yields 0 sessions. Prime suspect: CopyPresence hardcoded ProductId/ProductName= 'Satisfactory' (the emu's first target game), so StarRupture (ProductId 3e9825c4...) sees the friend as playing a DIFFERENT product and filters it out. Deep-copy ProductId/ProductName/ProductVersion at EOS_Platform_Create and report them for a peer's presence (a LAN clone runs the same product). Also dump the presence records + product/join_info on CopyPresence to see exactly what the game's friend-search reads. (cherry picked from commit 58d50e3)
UE copies every EOS presence data record verbatim into FOnlineUserPresence.Status.Properties (UserManagerEOS.cpp:3047-3051), and the game's own friend-join code reads those keys to decide joinable. A presence-enabled lobby host advertises ~14 attributes (incl. ALLOWEDPLATFORM, BUILDCL, SESSIONTEMPLATENAME, GameMode) but we capped presence at 8 records, silently dropping 6 — any of which the join check may gate on (the game binary references bJoinViaPresence + EOS_SessionModification_SetAllowedPlatformIds). Lift to 24 (beacon buffer is 64KB; prec_count is uint8_t). (cherry picked from commit e8645a0)
…untId_FromString
ROOT CAUSE of StarRupture friends-browse 'No sessions available' (RE'd against
UE source + live logs): the game's friend-search enqueue reads each friend's
session via UE FUserManagerEOS::GetExternalIdMapping, which treats EVERY external
id as an Epic id: EOS_EpicAccountId_FromString(id) -> IsValid -> registry Find.
The friend ids are STEAM ids, so FromString('76561198...') returned NULL (correct:
not 32-hex) -> IsValid false -> null mapping -> friend never enqueued -> friends
search completes with 0 results, FindFriendSession/RequestLobbyData never reached.
(The EOSPlus base Steam user interface that would handle steam ids is nullptr in
UE -- 'BaseUserInterface not valid'.)
Fix: when FromString gets a non-32-hex id, resolve it as a Steam id via the social
bridge (g_peers: steam->peer) and return that peer's REAL epic handle, so the
epic-keyed registry round-trips (FindOrAdd on the steam query and Find on the read
both land on the host's real epic). Returns the REMOTE peer's epic, never the local
user's, so it does not reintroduce the one-puid<->one-epic crash that returning the
local handle caused (397931e). Unknown steam ids still return NULL.
(cherry picked from commit 302ad7a)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Mainline the generic LAN-emu fixes that enable native friends-list browse→join for EOSPlus+Steam titles (validated end-to-end on StarRupture: friend appears in Join Game → join →
Welcomed by server→ travel into host world).Cherry-picked off
diag/session-config-loggingwith all diagnostic-only logging commits stripped:connect: map Steam external id → peer's real Epic handle in EpicAccountId_FromString— the load-bearing fix (UE friend-search is epic-keyed)presence: auto-derive local presence from a presence-enabled lobby(+ release announce-hold, real product identity,MAX_PRESENCE_RECORDS8→24)social: map Steam external accounts to PUIDs over the LAN beaconauth: EpicAccountId_FromString returns NULL for malformed ids(crash-fix)lobby_search/session_searchowner-match; immediate session propagationBuilds clean on CI (verified the bridge + presence-from-lobby symbols are present in the artifact).