This seems to have been an issue for some time now without being resolved.
If a listen server disconnects, the connected client in the session will get a Network Error event and is then loaded into Entry, regardless if that Network Error event is connected to a Open Level or console command (open mapname) these will be ignored and the client will end up on the Entry map.
I can’t find any way of fixing this and it is a problem. Any advice is appreciated!
Not really, I did some hacky fix by setting a bool when the network error occurs, and if that bool is set when the entry map loads, it instantly loads the menu map, error messages etc. It works tho.
yeah, I actually did similar, not happy about it though. I have it that on network error, I quickly load the main menu (from the entry map Splash screen), and show an error message. Not so pretty.
guys, seems like this is the only solution, even if we don’t like it. i checked ShooterGame example, and they do the same, after disconnect they change GameState to ErrorMessage, and game opens default level, then this game state value is applied
The function can be implemented as shown above. Running multiple instances via commandline with log reveiled the FailureType to be FailureReceived and ConnectionLost so do a check - eventually it’ll be caught and you can do a client travel to the main menu.
Lastly, add a delegate with the function to the OnNetworkFailure event in the Init function of your GameInstance, or where you prefer, and it should be working.
I’ve also implemented your solution, but I still cannot control clientTraveling to the EntryMap. I don’t want the client to travel anywhere.
How do you choose whether/where the client will travel to post-NetworkError?
void UEngine::HandleDisconnect( UWorld *InWorld, UNetDriver *NetDriver )
{
// There must be some context for this disconnect
check(InWorld || NetDriver);
// InWorld might be null. It might also not map to any valid world context (for example, a pending net game disconnect)
// If there is a context for this world, setup client travel.
if (FWorldContext* WorldContext = GetWorldContextFromWorld(InWorld))
{
// Remove ?Listen parameter, if it exists
WorldContext->LastURL.RemoveOption( TEXT("Listen") );
WorldContext->LastURL.RemoveOption( TEXT("LAN") );
// Net driver destruction will occur during LoadMap (prevents GetNetMode from changing output for the remainder of the frame)
// The ?closed option will also make sure any PendingNetGame is cancelled in Browse
SetClientTravel( InWorld, TEXT("?closed"), TRAVEL_Absolute );
}
else if (NetDriver)
{
// If the NetDriver that failed was a pending netgame driver, cancel the PendingNetGame
CancelPending(NetDriver);
// Shut down any existing game connections
if (InWorld)
{
// Call this to remove the NetDriver from the world context's ActiveNetDriver list
DestroyNamedNetDriver(InWorld, NetDriver->NetDriverName);
}
else
{
NetDriver->Shutdown();
NetDriver->LowLevelDestroy();
// In this case, the world is null and something went wrong, so we should travel back to the default world so that we
// can get back to a good state.
for (FWorldContext& PotentialWorldContext : WorldList)
{
if (PotentialWorldContext.WorldType == EWorldType::Game)
{
FURL DefaultURL;
DefaultURL.LoadURLConfig(TEXT("DefaultPlayer"), GGameIni);
const UGameMapsSettings* GameMapsSettings = GetDefault<UGameMapsSettings>();
if (GameMapsSettings)
{
PotentialWorldContext.TravelURL = FURL(&DefaultURL, *(GameMapsSettings->GetGameDefaultMap() + GameMapsSettings->LocalMapOptions), TRAVEL_Partial).ToString();
PotentialWorldContext.TravelType = TRAVEL_Partial;
}
}
}
}
}
}
You need to change this function has you need.
Mostly this line PotentialWorldContext.TravelURL = FURL(&DefaultURL, *(GameMapsSettings->GetGameDefaultMap() + GameMapsSettings->LocalMapOptions), TRAVEL_Partial).ToString();