forked from cafeberry/cafeberry
feat: add smartcmd dedicated server
major bug: when connecting to the server a second time, it gets softlocked and keeps repeating ticking connection A\n in debug logs until it times out.
This commit is contained in:
@@ -358,12 +358,24 @@ bool CGameNetworkManager::StartNetworkGame(Minecraft *minecraft, LPVOID lpParame
|
||||
// PRIMARY PLAYER
|
||||
|
||||
vector<ClientConnection *> createdConnections;
|
||||
ClientConnection *connection;
|
||||
ClientConnection *connection = NULL;
|
||||
|
||||
if( g_NetworkManager.IsHost() )
|
||||
#ifdef MINECRAFT_SERVER_BUILD
|
||||
{
|
||||
app.DebugPrintf("Dedicated server mode: skipping local host client connection\n");
|
||||
|
||||
// Keep telemetry behavior consistent with the host path.
|
||||
INT multiplayerInstanceId = TelemetryManager->GenerateMultiplayerInstanceId();
|
||||
TelemetryManager->SetMultiplayerInstanceId(multiplayerInstanceId);
|
||||
|
||||
app.SetGameMode( eMode_Multiplayer );
|
||||
}
|
||||
#else
|
||||
{
|
||||
connection = new ClientConnection(minecraft, NULL);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
INetworkPlayer *pNetworkPlayer = g_NetworkManager.GetLocalPlayerByUserIndex(ProfileManager.GetLockedProfile());
|
||||
@@ -389,155 +401,159 @@ bool CGameNetworkManager::StartNetworkGame(Minecraft *minecraft, LPVOID lpParame
|
||||
connection = new ClientConnection(minecraft, socket);
|
||||
}
|
||||
|
||||
if( !connection->createdOk )
|
||||
if (connection != NULL)
|
||||
{
|
||||
assert(false);
|
||||
delete connection;
|
||||
connection = NULL;
|
||||
MinecraftServer::HaltServer();
|
||||
return false;
|
||||
}
|
||||
|
||||
connection->send( shared_ptr<PreLoginPacket>( new PreLoginPacket(minecraft->user->name) ) );
|
||||
|
||||
// Tick connection until we're ready to go. The stages involved in this are:
|
||||
// (1) Creating the ClientConnection sends a prelogin packet to the server
|
||||
// (2) the server sends a prelogin back, which is handled by the clientConnection, and returns a login packet
|
||||
// (3) the server sends a login back, which is handled by the client connection to start the game
|
||||
if( !g_NetworkManager.IsHost() )
|
||||
{
|
||||
Minecraft::GetInstance()->progressRenderer->progressStart(IDS_PROGRESS_CONNECTING);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 4J Stu - Host needs to generate a unique multiplayer id for sentient telemetry reporting
|
||||
INT multiplayerInstanceId = TelemetryManager->GenerateMultiplayerInstanceId();
|
||||
TelemetryManager->SetMultiplayerInstanceId(multiplayerInstanceId);
|
||||
}
|
||||
TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected();
|
||||
do
|
||||
{
|
||||
app.DebugPrintf("ticking connection A\n");
|
||||
connection->tick();
|
||||
|
||||
// 4J Stu - We were ticking this way too fast which could cause the connection to time out
|
||||
// The connections should tick at 20 per second
|
||||
Sleep(50);
|
||||
} while ( (IsInSession() && !connection->isStarted() && !connection->isClosed() && !g_NetworkManager.IsLeavingGame()) || tPack->isLoadingData() || (Minecraft::GetInstance()->skins->needsUIUpdate() || ui.IsReloadingSkin()) );
|
||||
ui.CleanUpSkinReload();
|
||||
|
||||
// 4J Stu - Fix for #11279 - CRASH: TCR 001: BAS Game Stability: Signing out of game will cause title to crash
|
||||
// We need to break out of the above loop if m_bLeavingGame is set, and close the connection
|
||||
if( g_NetworkManager.IsLeavingGame() || !IsInSession() )
|
||||
{
|
||||
connection->close();
|
||||
}
|
||||
|
||||
if( connection->isStarted() && !connection->isClosed() )
|
||||
{
|
||||
createdConnections.push_back( connection );
|
||||
|
||||
int primaryPad = ProfileManager.GetPrimaryPad();
|
||||
app.SetRichPresenceContext(primaryPad,CONTEXT_GAME_STATE_BLANK);
|
||||
if (GetPlayerCount() > 1) // Are we offline or online, and how many players are there
|
||||
if( !connection->createdOk )
|
||||
{
|
||||
if (IsLocalGame()) ProfileManager.SetCurrentGameActivity(primaryPad,CONTEXT_PRESENCE_MULTIPLAYEROFFLINE,false);
|
||||
else ProfileManager.SetCurrentGameActivity(primaryPad,CONTEXT_PRESENCE_MULTIPLAYER,false);
|
||||
assert(false);
|
||||
delete connection;
|
||||
connection = NULL;
|
||||
MinecraftServer::HaltServer();
|
||||
return false;
|
||||
}
|
||||
|
||||
connection->send( shared_ptr<PreLoginPacket>( new PreLoginPacket(minecraft->user->name) ) );
|
||||
|
||||
// Tick connection until we're ready to go. The stages involved in this are:
|
||||
// (1) Creating the ClientConnection sends a prelogin packet to the server
|
||||
// (2) the server sends a prelogin back, which is handled by the clientConnection, and returns a login packet
|
||||
// (3) the server sends a login back, which is handled by the client connection to start the game
|
||||
if( !g_NetworkManager.IsHost() )
|
||||
{
|
||||
Minecraft::GetInstance()->progressRenderer->progressStart(IDS_PROGRESS_CONNECTING);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(IsLocalGame()) ProfileManager.SetCurrentGameActivity(primaryPad,CONTEXT_PRESENCE_MULTIPLAYER_1POFFLINE,false);
|
||||
else ProfileManager.SetCurrentGameActivity(primaryPad,CONTEXT_PRESENCE_MULTIPLAYER_1P,false);
|
||||
// 4J Stu - Host needs to generate a unique multiplayer id for sentient telemetry reporting
|
||||
INT multiplayerInstanceId = TelemetryManager->GenerateMultiplayerInstanceId();
|
||||
TelemetryManager->SetMultiplayerInstanceId(multiplayerInstanceId);
|
||||
}
|
||||
TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected();
|
||||
do
|
||||
{
|
||||
app.DebugPrintf("ticking connection A\n");
|
||||
connection->tick();
|
||||
|
||||
// 4J Stu - We were ticking this way too fast which could cause the connection to time out
|
||||
// The connections should tick at 20 per second
|
||||
Sleep(50);
|
||||
} while ( (IsInSession() && !connection->isStarted() && !connection->isClosed() && !g_NetworkManager.IsLeavingGame()) || tPack->isLoadingData() || (Minecraft::GetInstance()->skins->needsUIUpdate() || ui.IsReloadingSkin()) );
|
||||
ui.CleanUpSkinReload();
|
||||
|
||||
// 4J Stu - Fix for #11279 - CRASH: TCR 001: BAS Game Stability: Signing out of game will cause title to crash
|
||||
// We need to break out of the above loop if m_bLeavingGame is set, and close the connection
|
||||
if( g_NetworkManager.IsLeavingGame() || !IsInSession() )
|
||||
{
|
||||
connection->close();
|
||||
}
|
||||
|
||||
|
||||
// ALL OTHER LOCAL PLAYERS
|
||||
for(int idx = 0; idx < XUSER_MAX_COUNT; ++idx)
|
||||
if( connection->isStarted() && !connection->isClosed() )
|
||||
{
|
||||
// Already have setup the primary pad
|
||||
if(idx == ProfileManager.GetPrimaryPad() ) continue;
|
||||
|
||||
if( GetLocalPlayerByUserIndex(idx) != NULL && !ProfileManager.IsSignedIn(idx) )
|
||||
{
|
||||
INetworkPlayer *pNetworkPlayer = g_NetworkManager.GetLocalPlayerByUserIndex(idx);
|
||||
Socket *socket = pNetworkPlayer->GetSocket();
|
||||
app.DebugPrintf("Closing socket due to player %d not being signed in any more\n");
|
||||
if( !socket->close(false) ) socket->close(true);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// By default when we host we only have the local player, but currently allow multiple local players to join
|
||||
// when joining any other way, so just because they are signed in doesn't mean they are in the session
|
||||
// 4J Stu - If they are in the session, then we should add them to the game. Otherwise we won't be able to add them later
|
||||
INetworkPlayer *pNetworkPlayer = g_NetworkManager.GetLocalPlayerByUserIndex(idx);
|
||||
if( pNetworkPlayer == NULL )
|
||||
continue;
|
||||
|
||||
ClientConnection *connection;
|
||||
|
||||
Socket *socket = pNetworkPlayer->GetSocket();
|
||||
connection = new ClientConnection(minecraft, socket, idx);
|
||||
|
||||
minecraft->addPendingLocalConnection(idx, connection);
|
||||
//minecraft->createExtraLocalPlayer(idx, (convStringToWstring( ProfileManager.GetGamertag(idx) )).c_str(), idx, connection);
|
||||
|
||||
// Open the socket on the server end to accept incoming data
|
||||
Socket::addIncomingSocket(socket);
|
||||
|
||||
connection->send( shared_ptr<PreLoginPacket>( new PreLoginPacket(convStringToWstring( ProfileManager.GetGamertag(idx) )) ) );
|
||||
|
||||
createdConnections.push_back( connection );
|
||||
|
||||
// Tick connection until we're ready to go. The stages involved in this are:
|
||||
// (1) Creating the ClientConnection sends a prelogin packet to the server
|
||||
// (2) the server sends a prelogin back, which is handled by the clientConnection, and returns a login packet
|
||||
// (3) the server sends a login back, which is handled by the client connection to start the game
|
||||
do
|
||||
int primaryPad = ProfileManager.GetPrimaryPad();
|
||||
app.SetRichPresenceContext(primaryPad,CONTEXT_GAME_STATE_BLANK);
|
||||
if (GetPlayerCount() > 1) // Are we offline or online, and how many players are there
|
||||
{
|
||||
// We need to keep ticking the connections for players that already logged in
|
||||
for(AUTO_VAR(it, createdConnections.begin()); it < createdConnections.end(); ++it)
|
||||
{
|
||||
(*it)->tick();
|
||||
}
|
||||
|
||||
// 4J Stu - We were ticking this way too fast which could cause the connection to time out
|
||||
// The connections should tick at 20 per second
|
||||
Sleep(50);
|
||||
app.DebugPrintf("<***> %d %d %d %d %d\n",IsInSession(), !connection->isStarted(),!connection->isClosed(),ProfileManager.IsSignedIn(idx),!g_NetworkManager.IsLeavingGame());
|
||||
#if defined _XBOX || defined __PS3__ && !defined DISABLE_PSN
|
||||
} while (IsInSession() && !connection->isStarted() && !connection->isClosed() && ProfileManager.IsSignedIn(idx) && !g_NetworkManager.IsLeavingGame() );
|
||||
#else
|
||||
// TODO - This SHOULD be something just like the code above but temporarily changing here so that we don't have to depend on the profilemanager behaviour
|
||||
} while (IsInSession() && !connection->isStarted() && !connection->isClosed() && !g_NetworkManager.IsLeavingGame() );
|
||||
#endif
|
||||
|
||||
// 4J Stu - Fix for #11279 - CRASH: TCR 001: BAS Game Stability: Signing out of game will cause title to crash
|
||||
// We need to break out of the above loop if m_bLeavingGame is set, and stop creating new connections
|
||||
// The connections in the createdConnections vector get closed at the end of the thread
|
||||
if( g_NetworkManager.IsLeavingGame() || !IsInSession() ) break;
|
||||
|
||||
if( ProfileManager.IsSignedIn(idx) && !connection->isClosed() )
|
||||
{
|
||||
app.SetRichPresenceContext(idx,CONTEXT_GAME_STATE_BLANK);
|
||||
if (IsLocalGame()) ProfileManager.SetCurrentGameActivity(idx,CONTEXT_PRESENCE_MULTIPLAYEROFFLINE,false);
|
||||
else ProfileManager.SetCurrentGameActivity(idx,CONTEXT_PRESENCE_MULTIPLAYER,false);
|
||||
if (IsLocalGame()) ProfileManager.SetCurrentGameActivity(primaryPad,CONTEXT_PRESENCE_MULTIPLAYEROFFLINE,false);
|
||||
else ProfileManager.SetCurrentGameActivity(primaryPad,CONTEXT_PRESENCE_MULTIPLAYER,false);
|
||||
}
|
||||
else
|
||||
{
|
||||
connection->close();
|
||||
AUTO_VAR(it, find( createdConnections.begin(), createdConnections.end(), connection ));
|
||||
if(it != createdConnections.end() ) createdConnections.erase( it );
|
||||
if(IsLocalGame()) ProfileManager.SetCurrentGameActivity(primaryPad,CONTEXT_PRESENCE_MULTIPLAYER_1POFFLINE,false);
|
||||
else ProfileManager.SetCurrentGameActivity(primaryPad,CONTEXT_PRESENCE_MULTIPLAYER_1P,false);
|
||||
}
|
||||
}
|
||||
|
||||
app.SetGameMode( eMode_Multiplayer );
|
||||
}
|
||||
else if ( connection->isClosed() || !IsInSession())
|
||||
{
|
||||
// assert(false);
|
||||
MinecraftServer::HaltServer();
|
||||
return false;
|
||||
|
||||
// ALL OTHER LOCAL PLAYERS
|
||||
for(int idx = 0; idx < XUSER_MAX_COUNT; ++idx)
|
||||
{
|
||||
// Already have setup the primary pad
|
||||
if(idx == ProfileManager.GetPrimaryPad() ) continue;
|
||||
|
||||
if( GetLocalPlayerByUserIndex(idx) != NULL && !ProfileManager.IsSignedIn(idx) )
|
||||
{
|
||||
INetworkPlayer *pNetworkPlayer = g_NetworkManager.GetLocalPlayerByUserIndex(idx);
|
||||
Socket *socket = pNetworkPlayer->GetSocket();
|
||||
app.DebugPrintf("Closing socket due to player %d not being signed in any more\n");
|
||||
if( !socket->close(false) ) socket->close(true);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// By default when we host we only have the local player, but currently allow multiple local players to join
|
||||
// when joining any other way, so just because they are signed in doesn't mean they are in the session
|
||||
// 4J Stu - If they are in the session, then we should add them to the game. Otherwise we won't be able to add them later
|
||||
INetworkPlayer *pNetworkPlayer = g_NetworkManager.GetLocalPlayerByUserIndex(idx);
|
||||
if( pNetworkPlayer == NULL )
|
||||
continue;
|
||||
|
||||
ClientConnection *connection;
|
||||
|
||||
Socket *socket = pNetworkPlayer->GetSocket();
|
||||
connection = new ClientConnection(minecraft, socket, idx);
|
||||
|
||||
minecraft->addPendingLocalConnection(idx, connection);
|
||||
//minecraft->createExtraLocalPlayer(idx, (convStringToWstring( ProfileManager.GetGamertag(idx) )).c_str(), idx, connection);
|
||||
|
||||
// Open the socket on the server end to accept incoming data
|
||||
Socket::addIncomingSocket(socket);
|
||||
|
||||
connection->send( shared_ptr<PreLoginPacket>( new PreLoginPacket(convStringToWstring( ProfileManager.GetGamertag(idx) )) ) );
|
||||
|
||||
createdConnections.push_back( connection );
|
||||
|
||||
// Tick connection until we're ready to go. The stages involved in this are:
|
||||
// (1) Creating the ClientConnection sends a prelogin packet to the server
|
||||
// (2) the server sends a prelogin back, which is handled by the clientConnection, and returns a login packet
|
||||
// (3) the server sends a login back, which is handled by the client connection to start the game
|
||||
do
|
||||
{
|
||||
// We need to keep ticking the connections for players that already logged in
|
||||
for(AUTO_VAR(it, createdConnections.begin()); it < createdConnections.end(); ++it)
|
||||
{
|
||||
(*it)->tick();
|
||||
}
|
||||
|
||||
// 4J Stu - We were ticking this way too fast which could cause the connection to time out
|
||||
// The connections should tick at 20 per second
|
||||
Sleep(50);
|
||||
app.DebugPrintf("<***> %d %d %d %d %d\n",IsInSession(), !connection->isStarted(),!connection->isClosed(),ProfileManager.IsSignedIn(idx),!g_NetworkManager.IsLeavingGame());
|
||||
#if defined _XBOX || defined __PS3__ && !defined DISABLE_PSN
|
||||
} while (IsInSession() && !connection->isStarted() && !connection->isClosed() && ProfileManager.IsSignedIn(idx) && !g_NetworkManager.IsLeavingGame() );
|
||||
#else
|
||||
// TODO - This SHOULD be something just like the code above but temporarily changing here so that we don't have to depend on the profilemanager behaviour
|
||||
} while (IsInSession() && !connection->isStarted() && !connection->isClosed() && !g_NetworkManager.IsLeavingGame() );
|
||||
#endif
|
||||
|
||||
// 4J Stu - Fix for #11279 - CRASH: TCR 001: BAS Game Stability: Signing out of game will cause title to crash
|
||||
// We need to break out of the above loop if m_bLeavingGame is set, and stop creating new connections
|
||||
// The connections in the createdConnections vector get closed at the end of the thread
|
||||
if( g_NetworkManager.IsLeavingGame() || !IsInSession() ) break;
|
||||
|
||||
if( ProfileManager.IsSignedIn(idx) && !connection->isClosed() )
|
||||
{
|
||||
app.SetRichPresenceContext(idx,CONTEXT_GAME_STATE_BLANK);
|
||||
if (IsLocalGame()) ProfileManager.SetCurrentGameActivity(idx,CONTEXT_PRESENCE_MULTIPLAYEROFFLINE,false);
|
||||
else ProfileManager.SetCurrentGameActivity(idx,CONTEXT_PRESENCE_MULTIPLAYER,false);
|
||||
}
|
||||
else
|
||||
{
|
||||
connection->close();
|
||||
AUTO_VAR(it, find( createdConnections.begin(), createdConnections.end(), connection ));
|
||||
if(it != createdConnections.end() ) createdConnections.erase( it );
|
||||
}
|
||||
}
|
||||
|
||||
app.SetGameMode( eMode_Multiplayer );
|
||||
}
|
||||
else if ( connection->isClosed() || !IsInSession())
|
||||
{
|
||||
// assert(false);
|
||||
|
||||
MinecraftServer::HaltServer();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -547,7 +563,7 @@ bool CGameNetworkManager::StartNetworkGame(Minecraft *minecraft, LPVOID lpParame
|
||||
{
|
||||
(*it)->close();
|
||||
}
|
||||
// assert(false);
|
||||
//assert(false);
|
||||
MinecraftServer::HaltServer();
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user