How to update the server that a client connected?

Hello,

I have been experimenting with the OSS in c++. While following eXi’s Wiki allowed me to host and find sessions, I am trying to create a matchmaking system that automates the process of finding and hosting sessions. At the moment, looking for a session lets me join it (without travelling with APlayerController::ClientTravel()) when a session is found, or creates one (without starting it). This way I can keep both players in a lobby screen (or map) and when the server learns that the client connected it can start the session and go to a map. The client then tests the state of the session and if it is InProgress, calls APlayerController::ClientTravel() with the right URL and everything.

Problem is, I have tried using RegisterPlayer and UpdateSession. These functions end up causing crashes when right after their delegates are called, or before they are called, or they simply affect calls to GetNamedSession, making it fail and breaking when destroying the sessions.

My question: Is there a way to tell the server (listen or dedicated, although I am using a listen server setup) that a client joined without using these? If not, how am I supposed to use them?

Thanks!

ps: Some code.
My wrapper for the RegisterPlayer:

bool USteamGameInstance::RegisterPlayerInternal(FName SessionName, TSharedPtr<const FUniqueNetId>PlayerId, bool bWasInvited)
{
    	/// I am calling destroy for some reason
    	//WhoCalled = "RegisterPlayerInternal";

    	/// Return bool
    	bool bSuccessful = false;

    	/// Get SessionInterface from the OnlineSubsystem
       IOnlineSessionPtr Sessions = GetSessionInterface();

    	if (Sessions.IsValid() && PlayerId.IsValid())
       {
        	/// Set the Handle for registering all players since there is no OnRegisterPlayerComplete delegate
        	OnRegisterPlayersCompleteDelegateHandle = Sessions->AddOnRegisterPlayersCompleteDelegate_Handle(OnRegisterPlayersCompleteDelegate);

        	/// Here the call has to be to RegisterPlayer
        	bSuccessful = Sessions->RegisterPlayer(SessionName, *PlayerId, bWasInvited);
       }

       return bSuccessful;
  }

My OnRegisterPlayersComplete delegate:

void USteamGameInstance::OnRegisterPlayersComplete(FName SessionName, const TArray<TSharedRef<const FUniqueNetId>>& Players, bool bWasSuccessful)
{
    	FString BoolValue = BoolToFString(bWasSuccessful);
        UE_LOG(LogTemp, Warning, TEXT("OnRegisterPlayersComplete %s, %s, %d"), *SessionName.ToString(), *BoolValue, Players.Num())
        GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Yellow, FString::Printf(TEXT("OnRegisterPlayersComplete %s, %s, %d"), *SessionName.ToString(), *BoolValue, Players.Num()));

    	/// Who is calling
        UE_LOG(LogTemp, Warning, TEXT("Calling function: %s"), *WhoCalled)
    	GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Yellow, FString::Printf(TEXT("Calling function: %s"), *WhoCalled));

    	/// Get SessionInterface from the OnlineSubsystem
    	IOnlineSessionPtr Sessions = GetSessionInterface();

    	if (Sessions.IsValid())
     	{
    		/// Clear the Delegate again
        	Sessions->ClearOnRegisterPlayersCompleteDelegate_Handle(OnRegisterPlayersCompleteDelegateHandle);

     		/// When matchmaking let BP code be run to decide when to start the match
        	OnCreateSessionSuccessfulDelegate.Broadcast();

        	/// When in the client, update the settings and broadcast it
	        if (bWasSuccessful && !GIsServer)
    		{
         		/// Set the UpdateSession delegate handle and call UpdateSession
         		//OnUpdateSessionCompleteDelegateHandle = Sessions->AddOnUpdateSessionCompleteDelegate_Handle(OnUpdateSessionCompleteDelegate);
	        	TSharedPtr<FOnlineSessionSettings> NewSettings = MakeShareable(&Sessions->GetNamedSession(SessionName)->SessionSettings);
	         	//Sessions->UpdateSession(SessionName, *NewSettings, true);
	       }
    	}
   }

My OnJoinSessionComplete (where I call UpdateSession now):

    void USteamGameInstance::OnJoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result)
    {
    	FString test = ToString(Result);
    	UE_LOG(LogTemp, Warning, TEXT("OnDestroySessionComplete %s, %s"), *SessionName.ToString(), *test)
    	GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Yellow, FString::Printf(TEXT("OnJoinSessionComplete %s, %s"), *SessionName.ToString(), *test));

     	/// Get SessionInterface from the OnlineSubsystem
    	IOnlineSessionPtr Sessions = GetSessionInterface();

     	if (Sessions.IsValid())
    	{
        	/// Clear the Delegate again
     		Sessions->ClearOnJoinSessionCompleteDelegate_Handle(OnJoinSessionCompleteDelegateHandle);

     		/// Register the joining player here
     		//RegisterPlayerInternal(SessionName, GetLocalPlayer()->GetPreferredUniqueNetId(), false);

     		/// Get the first local PlayerController, so we can call "ClientTravel" to get to the Server Map
        	/// This is something the Blueprint Node "Join Session" does automatically!
     		APlayerController * const PlayerController = GetFirstLocalPlayerController();

     		/// We need a FString to use ClientTravel and we can let the SessionInterface contruct such a
     		/// String for us by giving him the SessionName and an empty String. We want to do this, because
     		/// Every OnlineSubsystem uses different TravelURLs
     		FString TravelURL;

     		if (bIsMatchMaking)
    		{
     			/// When matchmaking, allow BP code to deal with joining and traveling
     			//OnJoinSessionSuccessfulDelegate.Broadcast(TravelURL, ETravelType::TRAVEL_Absolute);

     			/// Add a new setting telling the server we connected to it
     			TSharedPtr<FOnlineSessionSettings> NewSettings = MakeShareable(&Sessions->GetNamedSession(SessionName)->SessionSettings);
      		        NewSettings->Set(FName("ClientConnected"), true, EOnlineDataAdvertisementType::ViaOnlineService);

	        	/// When matchmaking, update the session to let the server now we are connected to this session
         		OnUpdateSessionCompleteDelegateHandle = Sessions->AddOnUpdateSessionCompleteDelegate_Handle(OnUpdateSessionCompleteDelegate);
		Sessions->UpdateSession(SessionName, *NewSettings, true);
    		}
    		else
    		{
	        	/// Finally call the ClienTravel. If you want, you could print the TravelURL to see
         		/// how it really looks like
        		PlayerController->ClientTravel(TravelURL, ETravelType::TRAVEL_Absolute);
        	}
    	}
  }

Hey did you ever figure this issue out? I’m having a similar problem. I use CreateSession/JoinSession to host and join a session which works fine. Once my clients are all in the lobby the server calls ServerTravel to load the game map. When I do this, everything appears to work fine but if someone else were to then search for a match, it would show that this match is joinable because it thinks it only has 1 person in it. It’s like when I call ServerTravel, the session gets reset to 1 person (the host) but when the other clients load the map they never rejoin the session.