(continued)
Now using the logging messages I added and comparing the logs between succesful and failed seamless travels, the key difference seems this: the seamless travel fails when a client calls ServerNotifyLoadedWorld before the server is done loading the map, more specifically before the server has ran AGameMode::PostSeamlessTravel(). Since ServerNotifyLoadedWorld has been ran before the server has finished loading the map, it doesn’t execute HandleSeamlessTravelPlayer.
Now it seems to me that in this case AGameMode::PostSeamlessTravel is supposed to detect this case, this is the only other location in code where HandleSeamlessTravelPlayer is called. In fact it iterates over all player controllers and executes HandleSeamlessTravelPlayer if this check succeeds: PlayerController->HasClientLoadedCurrentWorld().
The problem is that the check fails even for player controllers that have previously already have reported to have loaded the correct world.
ServerNotifyLoadedWorld stores the name of the client-side loaded map and HasClientLoadedCurrentWorld checks this name but what I’m seeing is somewhere between the client initiated RPC ServerNotifyLoadedWorld and PostSeamlessTravel the player controllers are re-instantiated server-side: using only two clients, somewhere along the way PlayerController_0 became PlayerController_2 and PlayerController_1 became PlayerController_3. But with the reinstantiating, the reported map name doesn’t copy over. This makes the server incorrectly think that player is still loading.
Its a long post and I hope I’m onto something. Perhaps this helps your case as well. And maybe can tell me if I’m on the right path.