Hello folks,
I have a question regarding the logical flow of events as they pertain to a multiplayer game. Specifically I would like to find out what is the sequence of events when a session is created / joined.
Let me first describe what I am currently doing
Server Creation:
- The user starts the game and initiates the creation of a server which allows them to input a handful of properties like servername, max number of players, game mode, etc
- Once the user triggers “create server” my custom NetworkGameSession object takes over and does the following
- UMG button click binding calls
HostSession(Player->GetPreferredUniqueNetId(), GameSessionName, ServerName, bIsLAN, bIsPresence, MaxNumPlayers, bIsPasswordProtected, SessionPassword);
- This in turn calls
bool bCreateSession = Sessions->CreateSession(*UserId, SessionName, *SessionSettings);
- The outcome of CreateSession triggers my OnCreateSessionCompleteDelegate
void UNWGameInstance::OnCreateSessionComplete(FName SessionName, bool bWasSuccessful)
- The outcome of the OnCreateSessionCompleteDelegate triggers OnStartSessionCompleteDelegate
void UNWGameInstance::OnStartSessionComplete(FName SessionName, bool bWasSuccessful)
- This finally ( if successful ) handles the opening of a Lobby level and the transition of the player to said level
UGameplayStatics::OpenLevel((), FName(*FString("Lobby")), true, "listen");
Client Joining:
- Going to skip the finding of the servers but needless to say there is a server browser that lists the games of which a user can select one and proceed to join that server
- The server selection triggers the following Join call
JoinASession(Player->GetPreferredUniqueNetId(), GameSessionName, SearchResult);
- Which in turn has the following callback if successful OnJoinSessionCompleteDelegate
void UNWGameInstance::OnJoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result)
- Which again if successful triggers the joining of said server and the travel to the correct Lobby map
PlayerController->ClientTravel(TravelURL, ETravelType::TRAVEL_Absolute);
So now at this point I have two players 1 of which is the server sitting in the same map and they can see each other.
Now my issue is that the Lobby level has a custom LobbyGameMode associated with it
UCLASS()
class TESTMPGAME_API ALobbyGameMode : public AGameModeBase
Inside of the game mode I have the following methods over written
ALobbyGameMode();
/**
* Initialize the game.
* The GameMode's InitGame() event is called before any other functions (including PreInitializeComponents() )
* and is used by the GameMode to initialize parameters and spawn its helper classes.
* @warning: this is called before actors' PreInitializeComponents.
*/
virtual void InitGame(const FString& MapName, const FString& Options, FString& ErrorMessage) override;
/** start match, or let player enter, immediately */
virtual void BeginPlay() override;
virtual APawn* SpawnDefaultPawnFor_Implementation(AController* NewPlayer, class AActor* StartSpot) override;
virtual void PostLogin(APlayerController* NewPlayer) override;
virtual void GenericPlayerInitialization(AController* Controller) override;
virtual void InitSeamlessTravelPlayer(AController* NewController) override;
virtual void StartPlay() override;
void HandleSeamlessTravelPlayer(AController *& C) override;
void HandleStartingNewPlayer(APlayerController * NewPlayer);
virtual FString InitNewPlayer
(
APlayerController * NewPlayerController,
const FUniqueNetIdRepl & UniqueId,
const FString & Options,
const FString & Portal
) override;
virtual void PreLogin
(
const FString & Options,
const FString & Address,
const FUniqueNetIdRepl & UniqueId,
FString & ErrorMessage
) override;
Now with all this in place, none of my GameMode functions are being called. I haven’t implemented them yet so all I am doing is just printing the method name as the Player would be accessing it. Example)
void ALobbyGameMode::HandleSeamlessTravelPlayer(AController *& C)
{
Logger->Debug(__FUNCTION__);
}
But again nothing gets printed to screen and it appears like none of the GameMode functions that should be called are being initalized
Further to that I also have a MainMenuGameMode and that one, for example, has PostLogin overwritten and gets called when the game starts up. I presume this is because a default GameInstance is being created and UE4 is just going through the motions of creating a baby server.
Both my MainMenu and Lobby level are created the same way where I have a Level Blueprint and a Level C++ class that overwrites the default behaviour. Also each level specifies their own custom game modes.
What I can see is when the players join and I try to print out which GameMode is being used I can see that it’s correctly setting up my LobbyGameMode just not initiating any of the functions one would expect to be triggered.
I thought perhaps the reason was becase I was trying to do OpenLevel instead of another travel method but when I switched my logic to
()->ServerTravel("/Game/Level/Lobby/Lobby?listen");
The same result comes up where nothing on my LobbyGameMode is triggered.
Looking for advice how I can make this behave as expected.
My suspicion is that when the new Level is loaded the GameMode is not re-initialized but rather attached to the Level. Which makes me think I either need to trigger the re-initialization or there is a parameter somewhere I am not passing to either OpenLevel or ServerTravel.
The reason I need to get at the GameMode methods is pretty straight forward, I wanted to intercept Pre and PostLogin calls such that I can manipulate the PlayerController accordingly from changing the HUD to loading the appropriate user settings, etc etc
I appreciate any advice you guys can provide, Thanks.