What is the workflow that is taken when a player joins a server?

I’m certain this has been asked before but the wording is so finicky and a ton of unrelated posts come up whenever any multiplayer keywords are used.

I’m pretty comfortable with RPCs and have a good handle on multiplayer coding once the players are in the game. My difficulty has always been dealing with things getting set up when a player joins a game. Currently I am trying to accomplish the task of adding a widget for each player in the server. So when the Player1 joins, they see nothing (no widget for their own player). When Player2 joins, they get notified that Player1 is already in the game and Player1 gets notified that Player2 has joined.

My first instinct was to start in the GameMode with PostLogin. Here, I am getting the connecting player controller, creating a character for them and having them possess it. It made sense to me to handle the remainder of the connection stuff here. But it seems the majority of my issues stem from the fact that just because the SERVER has handled all of these things (Created the pawn, created the PlayerState, updated the GameState’s Player Array) doesn’t mean any of this stuff has been updated on the CLIENTS. So if I try to grab the connecting player’s PlayerState and send it to the already-connected player, it very well could be a null pointer as it simply hasn’t been updated clientside yet.

I’m looking for two things. Firstly, what is the order in which assets are created for a connecting player? This is my current assumption:

  1. GameMode
  2. GameState
  3. PlayerController
  4. Pawn (I create this manually in my GameMode’s PostLogin, not sure where pawn would fall in the order if it was created automatically by the GameMode)
  5. PlayerState

This order is done both serverside and clientside … but what I really need is a reliable way for the server to say “The player has finished connecting and has obtained all the assets”. I suppose I could run an RPC from the connecting player’s PlayerState to tell the server “I’m done!” but it seems really crude to rely on the client code for this to work.

I guess I could also just use the PostLogin and send a reference to the connecting player’s PlayerState to connected players and then … have the client keep trying to use the PlayerState reference until it’s not a nullptr. This seems just as crude as the previous solution though.

Unfortunately I don’t have a good answer to this. I have this “hacky” solution right now, where every 0.2 seconds, I recreate a player widget for each PlayerState in the GameState->PlayerArray.

Use on rep notify variables in PlayerState.
The Client create the widgets on Playerstate beginplay and update the Widget OnRep.

The first rule of Replication is that there is no order of operation. You should always code in a way where the order doesn’t matter.