End a Game #

Goal: Allow a player client to tell the game server to shut down, and handle server shutdown processes.

In this section we will work with the following methods:

In the player controller:

  • TellGameServerToEndGame(): Allows player client to tell the game server to end the game.

In the game mode base:

  • EndGame(): Handles game end data and calls ShutdownServer().
  • ShutdownServer(): Shuts down the game server.

Allow player to request game end #

We want to allow player clients to end the game from the game interface. To do so, we’ll create a BlueprintCallable function that tells the server to end the game. You can connect this function to a button in the GameServerLevel to allow players to end the game instance when they click it.

  1. In MyPlayerController.h, declare the TellGameServerToEndGame() UFunction, which will execute on the server:

    public:
    	UFUNCTION(BlueprintCallable, Server, Reliable, Category="Pragma")
    	void TellGameServerToEndGame();
    
  2. In MyPlayerController.cpp, define TellGameServerToEndGame(). When used the method will call our MyGameModeBase EndGame() function, which we will define in the next step.

    void AMyPlayerController::TellGameServerToEndGame_Implementation()
    {
        UE_LOG(LogTemp, Display, TEXT("MyGameClient -- Telling game server to end the game..."));
        Cast<AMyGameModeBase>(GetWorld()->GetAuthGameMode())->EndGame();
    }
    

Define EndGame #

  1. In MyGameModeBase.h, declare the EndGame() method:

    public:
        void EndGame();
    
  2. In MyGameModeBase.cpp, define EndGame() such that it handles player game results, calls MatchApi.EndGame() to end the game, and calls our ShutdownServer() method as a result. We’ll define ShutdownServer() in the next step.

    void AMyGameModeBase::EndGame()
    {
        if (!StoredGameStartData.IsSet())
        {
            UE_LOG(LogTemp, Error, TEXT("MyGameServer -- No match data when trying to end game."))
            ShutdownServer();
            return;
        }
    
        TArray<FPragma_GameInstance_PlayerGameResult> PlayerGameResults;
        for (const auto& Player : StoredGameStartData->Players)
        {
            auto i = PlayerGameResults.Emplace();
            PlayerGameResults[i].PlayerId = Player.PlayerId;
            // PlayerGameResults[i].Ext = TEXT("your player-specific data here");
        }
    
        UE_LOG(LogTemp, Display, TEXT("MyGameServer -- Attempting to end game..."));
        Server->MatchApi().EndGame(
            StoredGameStartData->GameInstanceId,
            PlayerGameResults,
            FPragma_GameInstance_ExtEndGameRequest{},
            UPragmaMatchApi::FOnCompleteDelegate::CreateLambda(
                [this](const TPragmaResult<>& Result)
                {
                    if (Result.IsSuccessful())
                    {
                        UE_LOG(LogTemp, Display, TEXT("MyGameServer -- End game succeeded."));
                    }
                    else
                    {
                        UE_LOG(LogTemp, Error, TEXT("MyGameServer -- End game failed."));
                    }
                    ShutdownServer();
                })
        );
    }
    

Shut down the server #

  1. In MyGameModeBase.h, declare a ShutdownServer() method:

    private:
        static void ShutdownServer();
    
  2. In MyGameModeBase.cpp, define the ShutdownServer() method such that it uses the Unreal FGenericPlatformMisc interface to exit the game server:

    void AMyGameModeBase::ShutdownServer()
    {
        FGenericPlatformMisc::RequestExit(false);
    }