x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

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);
             }
         }
   }
Product Version: UE 4.16
Tags:
more ▼

asked Oct 30 '17 at 07:30 AM in C++ Programming

avatar image

carlosasb
1 1 5

(comments are locked)
10|2000 characters needed characters left

0 answers: sort voted first
Be the first one to answer this question
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question