1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-12 02:28:11 +02:00

Fixes for player disconnection handling

- Fixed lack of notification if player disconnects via connection loss,
e.g. app crash / network going down
- Replaced notification via chat message with notification via info window
This commit is contained in:
Ivan Savenko 2024-10-04 12:48:50 +00:00
parent b79897f598
commit 371eac070f
4 changed files with 46 additions and 20 deletions

View File

@ -143,6 +143,7 @@
"vcmi.client.errors.invalidMap" : "{Invalid map or campaign}\n\nFailed to start game! Selected map or campaign might be invalid or corrupted. Reason:\n%s",
"vcmi.client.errors.missingCampaigns" : "{Missing data files}\n\nCampaigns data files were not found! You may be using incomplete or corrupted Heroes 3 data files. Please reinstall game data.",
"vcmi.server.errors.disconnected" : "{Network Error}\n\nConnection to game server has been lost!",
"vcmi.server.errors.playerLeft" : "{Player Left}\n\n%s player have disconnected from the game!", //%s -> player color
"vcmi.server.errors.existingProcess" : "Another VCMI server process is running. Please terminate it before starting a new game.",
"vcmi.server.errors.modsToEnable" : "{Following mods are required}",
"vcmi.server.errors.modsToDisable" : "{Following mods must be disabled}",

View File

@ -431,10 +431,28 @@ void CGameHandler::handleClientDisconnection(std::shared_ptr<CConnection> c)
continue;
auto playerConnection = vstd::find(playerConnections.second, c);
if(playerConnection != playerConnections.second.end())
if(playerConnection == playerConnections.second.end())
continue;
logGlobal->trace("Player %s disconnected. Notifying remaining players", playerId.toString());
// this player have left the game - broadcast infowindow to all in-game players
for (auto i = gs->players.cbegin(); i!=gs->players.cend(); i++)
{
std::string messageText = boost::str(boost::format("%s (cid %d) was disconnected") % playerSettings->name % c->connectionID);
playerMessages->broadcastMessage(playerId, messageText);
if (i->first == playerId)
continue;
if (getPlayerState(i->first)->status != EPlayerStatus::INGAME)
continue;
logGlobal->trace("Notifying player %s", i->first);
InfoWindow out;
out.player = i->first;
out.text.appendTextID("vcmi.server.errors.playerLeft");
out.text.replaceName(playerId);
out.components.emplace_back(ComponentType::FLAG, playerId);
sendAndApply(&out);
}
}
}

View File

@ -297,25 +297,19 @@ void CVCMIServer::onDisconnected(const std::shared_ptr<INetworkConnection> & con
logNetwork->error("Network error receiving a pack. Connection has been closed");
std::shared_ptr<CConnection> c = findConnection(connection);
if (!c)
return; // player have already disconnected via clientDisconnected call
vstd::erase(activeConnections, c);
if(activeConnections.empty() || hostClientId == c->connectionID)
// player may have already disconnected via clientDisconnected call
if (c)
{
setState(EServerState::SHUTDOWN);
return;
}
//clientDisconnected(c);
if(gh && getState() == EServerState::GAMEPLAY)
{
gh->handleClientDisconnection(c);
auto lcd = std::make_unique<LobbyClientDisconnected>();
lcd->c = c;
lcd->clientId = c->connectionID;
handleReceivedPack(std::move(lcd));
if(gh && getState() == EServerState::GAMEPLAY)
{
auto lcd = std::make_unique<LobbyClientDisconnected>();
lcd->c = c;
lcd->clientId = c->connectionID;
handleReceivedPack(std::move(lcd));
}
}
}
@ -434,9 +428,21 @@ void CVCMIServer::clientConnected(std::shared_ptr<CConnection> c, std::vector<st
void CVCMIServer::clientDisconnected(std::shared_ptr<CConnection> connection)
{
connection->getConnection()->close();
assert(vstd::contains(activeConnections, connection));
logGlobal->trace("Received disconnection request");
vstd::erase(activeConnections, connection);
if(activeConnections.empty() || hostClientId == connection->connectionID)
{
setState(EServerState::SHUTDOWN);
return;
}
if(gh && getState() == EServerState::GAMEPLAY)
{
gh->handleClientDisconnection(connection);
}
// PlayerReinitInterface startAiPack;
// startAiPack.playerConnectionId = PlayerSettings::PLAYER_AI;
//

View File

@ -108,6 +108,7 @@ void ClientPermissionsCheckerNetPackVisitor::visitLobbyClientDisconnected(LobbyC
void ApplyOnServerNetPackVisitor::visitLobbyClientDisconnected(LobbyClientDisconnected & pack)
{
pack.c->getConnection()->close();
srv.clientDisconnected(pack.c);
result = true;
}