Server and client unsync-ed on postlogin?

Hello. First of all HAPPY NEW YEAR!

On a less happy note I’ve been having some issues with game sessions and getting the data correctly replicated to all the clients. Let me show you some code.

This is what I’ve got on my GameMode’s PostLogin:

void ALobbyGM::PostLogin(APlayerController * NewPlayer)
{
	UE_LOG(IntruderDebug, Verbose, TEXT("PostLogin - Begin"));
	Super::PostLogin(NewPlayer);

	if (!HasAuthority()) { // Authority Only
		return;
	}

	ALobbyPC* lobbyPC = Cast<ALobbyPC>(NewPlayer);
	if (!lobbyPC) {
		return;
	}
	
	// init the lobby PC widgets
	lobbyPC->InitialSetup();
	lobbyPC->SetupLobbyMenu(ServerName);
	
	RespawnPlayer(NewPlayer);
	
	UE_LOG(IntruderDebug, Verbose, TEXT("PostLogin - End"));
}

And here’s what I get on the Server’s log when a client joins :

[2017.12.31-17.04.14:668][ 72]IntruderDebug: Verbose: PostLogin - Begin
[2017.12.31-17.04.14:669][ 72]IntruderDebug: Verbose: RespawnPlayer_Implementation - Begin
[2017.12.31-17.04.14:670][ 72]IntruderDebug: Verbose: RespawnPlayer_Implementation - End
[2017.12.31-17.04.14:670][ 72]IntruderDebug: Verbose: PostLogin - End
[2017.12.31-17.04.14:670][ 72]LogNet: Join succeeded: DESKTOP-2MMA877-4230
[2017.12.31-17.04.14:700][ 74]IntruderDebug: Verbose: CallUpdate_Implementation - Begin
[2017.12.31-17.04.14:700][ 74]IntruderDebug: Verbose: SwapCharacters_Implementation - Begin
[2017.12.31-17.04.14:700][ 74]IntruderDebug: Verbose: CallUpdate_Implementation - End

The issue here is that all those calls that are logged after the LogNet: Join succeeded line are made inside InitialSetup. Therefore they should be called before the RespawnPlayer, not way after.

It’s not just the logger that has the info on the wrong order. The RespawnPlayer call is doing all kinds of wrong stuff because the NewPlayer has not been initialized when it gets called.

Why are the calls being made in the wrong order?
Is PostLogin not the correct function to call here?
Is the fact that InitialSetup is a UFUNCTION(Client, Reliable) making it wait? But why is RespawnPlayer not waiting for InitialSetup to be over before executing?

I think the issue you have might be related to how those functions are declared. Did you set them to run on the client as reliable? if they are not reliable maybe the parent function will not wait until those calls are finished and run on a separate thread.

/**
	 *	Initial Setup - Check for Save Game info and tell server to update
	 */
	UFUNCTION(Client, Reliable, WithValidation, Category = "Lobby Events")
	void InitialSetup(int32 PlayerID);
	virtual bool InitialSetup_Validate(int32 PlayerID) { return true; };
	virtual void InitialSetup_Implementation(int32 PlayerID);

	/**
	 *	Set up and display the Lobby Menu
	 */
	UFUNCTION(Client, Reliable, WithValidation, Category = "Lobby Events")
	void SetupLobbyMenu(const FText& ServerName);
	virtual bool SetupLobbyMenu_Validate(const FText& ServerName) { return true; };
	virtual void SetupLobbyMenu_Implementation(const FText& ServerName);

Please let me know if this was the issue :slight_smile:

They are both Client and Reliable functions. But InitialSetup does indeed call some functions that are not Reliable. They’re not even UFUNCTIONs.

I have tried changing all the function calls made inside InitialSetup but it did not solve the problem.

So far I have found a workaround by calling the RespawnPlayer from inside the InitialSetup function, but I would still like to know why the Client functions are getting called after PostLogin’s end.

This is really weird, I have a very similar code running. You are sure no one else is calling RespawnPlayer from somewhere else? I’m out of ideas.

I’m all out of ideas. I guess I’m gonna stick to my workaround fix then.
Atleast it works now. Weirdly, but it works.

Thanks a lot for your help though!