OSS Steam: unable to exchange SteamIds after joining a session

Hi Epicfolk,

I’m working on an OSS Steam integration in UE4.27, and I’m hitting a snag:

I set up the online subsystem using the info here, and it seemed to be going smoothly. I’m able to create a session, search for it, and join the session using another Steam account on a different PC.

Once two players are in the session, I have a problem: session->RegisteredPlayers isn’t being updated. My understanding is that this array should contain a list of the SteamIds for all players in the session, but session->RegisteredPlayers.Num() returns 0, and I don’t see any other way to get the SteamIds of players in the session.

Also, I’ve set up delegates for these callbacks, but neither of the delegates fires for the session host when another player joins the session:

  • OnSessionParticipantsChange
  • OnRegisterPlayersComplete

Other pieces of information about the session like session->OwningUserId and session->GetSessionIdStr() return the correct value for all players, so I think the players have joined the session successfully. But I haven’t found a way to exchange the SteamIds! :thinking:

Why I need the SteamIds: I’m trying to set up a P2P connection using SteamSockets, which requires the SteamIds for NAT punchthrough and starting the connection.

Any ideas I can try?


Abridged code snippets, in case they’re relevant:

//Called when clicking a button in the UI to create a new session
void UMultiplayerSessionsSubsystem::CreateSession(int32 NumPublicConnections, FString SessionName)
{
        //Create a new session settings object
	TSharedPtr<FOnlineSessionSettings> SessionSettings = MakeShareable(new FOnlineSessionSettings());

        //Standard settings (creating as a lobby, with presence)
	SessionSettings->bIsDedicated = false;
	SessionSettings->NumPublicConnections = NumPublicConnections;
	SessionSettings->bAllowJoinInProgress = true;
	SessionSettings->bAllowJoinViaPresence = true; 
	SessionSettings->bIsLANMatch = false; 
	SessionSettings->bShouldAdvertise = true;
	SessionSettings->bUsesPresence = true; 
	SessionSettings->Set(FName("SessionName"), SessionName, EOnlineDataAdvertisementType::ViaOnlineServiceAndPing);
	SessionSettings->bUseLobbiesIfAvailable = true;

        //Create the session
        SessionInterface->CreateSession(*NetId, NAME_GameSession, *LastSessionSettings);
}

//Called when selecting a session to join (after doing a search for sessions)
void UMultiplayerSessionsSubsystem::JoinSession(const FOnlineSessionSearchResult& SessionResult)
{
        //Note: after joining the session, the OnJoinSessionComplete callback is called for the joining player. But no callbacks are called for the session host, so the host doesn't know about the new player.
       SessionInterface->JoinSession(*NetId, NAME_GameSession, SessionResult);
}

void UMultiplayerSessionSubsystem::PrintSessionData()
{
        //Get the named session object (the session name is stored when joining, for lookup)
	FNamedOnlineSession* session = SessionInterface->GetNamedSession(CurrentSessionName);
	
        //Print info. This correctly prints GetSessionIdStr(), but shows 0 for RegisteredPlayers.Num()
	GEngine->AddOnScreenDebugMessage(
		-1,
		15.f,
		FColor::Green,
		FString::Printf(TEXT("UMultiplayerSessionMenu::Tick --- net ids in session %s: %d), *session->GetSessionIdStr(), session->RegisteredPlayers.Num())
	);
}

Hello, I’ve been trying to get OnSessionParticipantsChange delegate to work. Did you finally solve that?

Oops, this fell off my radar. I’ll post my solution in case it helps someone in the future:

In order for other players to get a callback when a new player joins the lobby, I had to make engine modifications in order to add an OnEnterLobby/OnLobbyMemberStateChanged delegate to the online session interface.

These changes are made in the Unreal Engine source file: Engine\Plugins\Online\OnlineSubsystem\Source\Public\Interfaces\OnlineSessionInterface.h:

//add at line 168:
/**
* Custom delegate fired when a player enters or leaves a lobby session.
* Triggered in OnlineAsyncTaskManagerSteam.cpp
*
* @param LobbyId The unique identifier used to label the lobby. This id is used in Steam APIs to send chat messages to the lobby and check for received chat messages.
* @param uint64 SteamId unique identifier for the player that joined or left
* @param bool true if joined, false if left
*/
DECLARE_MULTICAST_DELEGATE_ThreeParams(FOnLobbyMemberStateChanged, uint64, uint64, bool);
typedef FOnLobbyMemberStateChanged::FDelegate FOnLobbyMemberStateChangedDelegate;

//~Add at line 735:
/**
* Custom delegate fired when a player enters or leaves a lobby session.
* Triggered in OnlineAsyncTaskManagerSteam.cpp
*
* @param LobbyId The unique identifier used to label the lobby. This id is used in Steam APIs to send chat messages to the lobby and check for received chat messages.
* @param uint64 SteamId unique identifier for the player that joined or left
* @param bool true if joined, false if left
*/
DEFINE_ONLINE_DELEGATE_THREE_PARAM(OnLobbyMemberStateChanged, uint64, uint64, bool);

I also had to make a copy of the OnlineSubsystemSteam module and put it into my project’s Plugins folder in order to edit OnlineAsyncTaskManagerSteam.cpp and .h in order to bind to the delegates. These are a bit lengthy, so I’ll just throw the edited files in here- see attached.
OnlineAsyncTaskManagerSteam_cpp.txt (46.4 KB)
OnlineAsyncTaskManagerSteam_h.txt (10.3 KB)

You need to register the players (both on server and client side) using the RegisterPlayer function of the Online Subsystem.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.