Connect Players to the Server #

Goal: Allow players to connect to the game server hosting their game instance.

In this section we’ll be working with the following methods:

In the game mode base:

  • HandleGameStartDataReceived(): Receives game start data from the backend and attempts to connect players to the server.
  • PostLogin(): Handles functionality to execute after a player connects to the server. This is automatically called when a new player joins the server.

In the player controller:

  • HandleOnHostConnectionDetailsReceived(): Called when player client receives the onHostConnectionDetailsReceived event.
  • TellGameClientItIsConnected(): Called by the game server to tell the client they are connected.

Give player clients host connection information #

When the game server receives game start data from the Pragma backend, it can call ConnectPlayers() to let the Pragma Engine backend know that it is ready to accept players.

In MyGameModeBase.cpp, define HandleGameStartDataReceived():

void AMyGameModeBase::HandleGameStartDataReceived(FPragma_GameInstance_GameStart GameStartData)
{
	UE_LOG(LogTemp, Display, TEXT("MyGameServer -- Start game succeeded."));
	StoredGameStartData = GameStartData;
	
	const auto Hostname = "127.0.0.1";
	constexpr auto Port = 7777;
	
	TArray<FPragma_GameInstance_PlayerConnectionDetails> PlayerConnectionDetails;
	for (const auto& Player : GameStartData.Players)
	{
		auto i = PlayerConnectionDetails.Emplace();
		PlayerConnectionDetails[i].PlayerId = Player.PlayerId;
		// PlayerConnectionDetails[i].ExtPlayerConnectionDetails = TEXT("your player-specific data here");
	}

	UE_LOG(LogTemp, Display, TEXT("MyGameServer -- Attempting to connect players..."));
	Server->MatchApi().ConnectPlayers(
		GameStartData.GameInstanceId,
		PlayerConnectionDetails,
		Hostname,
		Port,
		UPragmaMatchApi::FOnCompleteDelegate::CreateLambda(
			[this](const TPragmaResult<>& Result)
			{
				if (Result.IsFailure())
				{
					UE_LOG(LogTemp, Error, TEXT("MyGameServer -- Connect players failed."));
					ShutdownServer();
				}
				else
				{
					UE_LOG(LogTemp, Display, TEXT("MyGameServer -- Connect players succeeded."));
				}
			})
	);
}

Connect players to the game server #

The player controller can listen for the OnHostConnectionDetailsReceived event and connect to the Unreal game server associated with the received host name.

  1. In MyPlayerController.h, declare a HandleOnHostConnectionDetailsReceived() method:

    private:
        void HandleOnHostConnectionDetailsReceived(const FPragmaGameInstance& GameInstance);
    
  2. In the MyPlayerController.cpp BeginPlay() method, register our HandleOnHostConnectionDetailsReceived() method with the OnHostConnectionDetailsReceived event. The event provides a FPragmaGameInstance object.

    Player->GameInstanceApi().OnHostConnectionDetailsReceived.AddUObject(
    	this, &AMyPlayerController::HandleOnHostConnectionDetailsReceived);
    
  3. In MyPlayerController.cpp, define HandleOnHostConnectionDetailsReceived() such that the player client connects to the Unreal server associated with the received host name and port:

    void AMyPlayerController::HandleOnHostConnectionDetailsReceived(const FPragmaGameInstance& GameInstance)
    {
        const FString ServerHostname = GameInstance.GetHostConnectionDetails()->GetHostName();
        const int ServerPort = GameInstance.GetHostConnectionDetails()->GetPort();
        const FString ServerAddress = ServerHostname + ":" + FString::FromInt(ServerPort);
        UE_LOG(LogTemp, Display, TEXT("MyGameClient -- Received host connection details, attempting to connect to %s"),
            *ServerAddress);
        UGameplayStatics::OpenLevel(GetWorld(), FName(*ServerAddress), true);
    }
    

Notify player that they are connected to the game server #

Now, we want to let players know they are connected to the game server.

  1. In MyPlayerController.h, declare the TellGameClientItIsConnected() UFunction, which will execute for the specific player client:

    public:
        UFUNCTION(Client, Reliable, Category="Pragma")
        void TellGameClientItIsConnected();
    
  2. In MyPlayerController.cpp, define TellGameClientItIsConnected(). When called by the game server (see steps 3 and 4), we’ll display a log to verify the player and server can connect.

    void AMyPlayerController::TellGameClientItIsConnected_Implementation()
    {
        UE_LOG(LogTemp, Display, TEXT("MyGameClient -- Game server told me we are connected!"));
    }
    
  3. In MyGameModeBase.h, declare the PostLogin() method:

    protected:
        virtual void PostLogin(APlayerController* NewPlayer) override;
    
  4. In MyGameModeBase.cpp, define PostLogin() such that the game server calls the MyPlayerController TellGameClientItIsConnected() method for the connected players:

    void AMyGameModeBase::PostLogin(APlayerController* NewPlayer)
    {
        Super::PostLogin(NewPlayer);
    
        UE_LOG(LogTemp, Display, TEXT("MyGameServer -- Player client connected."));
        Cast<AMyPlayerController>(NewPlayer)->TellGameClientItIsConnected();
    }