1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-03-29 21:56:54 +02:00

Fixes and cleanup of game client network shutdown and restart

This commit is contained in:
Ivan Savenko 2024-02-03 19:08:45 +02:00
parent 6eef197cea
commit 2c2bec791c
17 changed files with 102 additions and 146 deletions

View File

@ -131,12 +131,12 @@ CServerHandler::~CServerHandler()
networkHandler->stop();
try
{
threadNetwork->join();
threadNetwork.join();
}
catch (const std::runtime_error & e)
{
logGlobal->error("Failed to shut down network thread! Reason: %s", e.what());
assert(false);
assert(0);
}
}
@ -144,17 +144,16 @@ CServerHandler::CServerHandler()
: applier(std::make_unique<CApplier<CBaseForLobbyApply>>())
, lobbyClient(std::make_unique<GlobalLobbyClient>())
, networkHandler(INetworkHandler::createHandler())
, threadNetwork(&CServerHandler::threadRunNetwork, this)
, state(EClientState::NONE)
, campaignStateToSend(nullptr)
, screenType(ESelectionScreen::unknown)
, serverMode(EServerMode::NONE)
, loadMode(ELoadMode::NONE)
, client(nullptr)
, campaignServerRestartLock(false)
{
uuid = boost::uuids::to_string(boost::uuids::random_generator()());
registerTypesLobbyPacks(*applier);
threadNetwork = std::make_unique<boost::thread>(&CServerHandler::threadRunNetwork, this);
}
void CServerHandler::threadRunNetwork()
@ -192,8 +191,8 @@ GlobalLobbyClient & CServerHandler::getGlobalLobby()
void CServerHandler::startLocalServerAndConnect(bool connectToLobby)
{
if(threadRunLocalServer)
threadRunLocalServer->join();
if(threadRunLocalServer.joinable())
threadRunLocalServer.join();
th->update();
@ -203,19 +202,17 @@ void CServerHandler::startLocalServerAndConnect(bool connectToLobby)
if(connectToLobby)
args.push_back("--lobby");
threadRunLocalServer = std::make_unique<boost::thread>([&cond, args, this] {
threadRunLocalServer = boost::thread([&cond, args] {
setThreadName("CVCMIServer");
CVCMIServer::create(&cond, args);
onServerFinished();
});
threadRunLocalServer->detach();
#elif defined(VCMI_ANDROID)
{
CAndroidVMHelper envHelper;
envHelper.callStaticVoidMethod(CAndroidVMHelper::NATIVE_METHODS_DEFAULT_CLASS, "startServer", true);
}
#else
threadRunLocalServer = std::make_unique<boost::thread>(&CServerHandler::threadRunServer, this, connectToLobby); //runs server executable;
threadRunLocalServer = boost::thread(&CServerHandler::threadRunServer, this, connectToLobby); //runs server executable;
#endif
logNetwork->trace("Setting up thread calling server: %d ms", th->getDiff());
@ -357,10 +354,7 @@ ui8 CServerHandler::myFirstId() const
bool CServerHandler::isServerLocal() const
{
if(threadRunLocalServer)
return true;
return false;
return threadRunLocalServer.joinable();
}
bool CServerHandler::isHost() const
@ -416,7 +410,10 @@ void CServerHandler::sendClientDisconnecting()
{
// FIXME: This is workaround needed to make sure client not trying to sent anything to non existed server
if(state == EClientState::DISCONNECTING)
{
assert(0);
return;
}
state = EClientState::DISCONNECTING;
mapToStart = nullptr;
@ -433,12 +430,8 @@ void CServerHandler::sendClientDisconnecting()
logNetwork->info("Sent leaving signal to the server");
}
sendLobbyPack(lcd);
{
// Network thread might be applying network pack at this moment
auto unlockInterface = vstd::makeUnlockGuard(GH.interfaceMutex);
c.reset();
}
c->getConnection()->close();
c.reset();
}
void CServerHandler::setCampaignState(std::shared_ptr<CampaignState> newCampaign)
@ -585,9 +578,7 @@ void CServerHandler::sendRestartGame() const
{
GH.windows().createAndPushWindow<CLoadingScreen>();
LobbyEndGame endGame;
endGame.closeConnection = false;
endGame.restart = true;
LobbyRestartGame endGame;
sendLobbyPack(endGame);
}
@ -676,40 +667,37 @@ void CServerHandler::startGameplay(VCMI_LIB_WRAP_NAMESPACE(CGameState) * gameSta
state = EClientState::GAMEPLAY;
}
void CServerHandler::endGameplay(bool closeConnection, bool restart)
void CServerHandler::endGameplay()
{
if(closeConnection)
{
// Game is ending
// Tell the network thread to reach a stable state
CSH->sendClientDisconnecting();
logNetwork->info("Closed connection.");
}
// Game is ending
// Tell the network thread to reach a stable state
CSH->sendClientDisconnecting();
logNetwork->info("Closed connection.");
client->endGame();
client.reset();
if(!restart)
if(CMM)
{
if(CMM)
{
GH.curInt = CMM.get();
CMM->enable();
}
else
{
GH.curInt = CMainMenu::create().get();
}
GH.curInt = CMM.get();
CMM->enable();
}
if(c)
else
{
nextClient = std::make_unique<CClient>();
c->setCallback(nextClient.get());
c->enterLobbyConnectionMode();
GH.curInt = CMainMenu::create().get();
}
}
void CServerHandler::restartGameplay()
{
client->endGame();
client.reset();
nextClient = std::make_unique<CClient>();
c->setCallback(nextClient.get());
c->enterLobbyConnectionMode();
}
void CServerHandler::startCampaignScenario(HighScoreParameter param, std::shared_ptr<CampaignState> cs)
{
std::shared_ptr<CampaignState> ourCampaign = cs;
@ -728,7 +716,6 @@ void CServerHandler::startCampaignScenario(HighScoreParameter param, std::shared
GH.dispatchMainThread([ourCampaign, this]()
{
CSH->campaignServerRestartLock.set(true);
CSH->endGameplay();
auto & epilogue = ourCampaign->scenario(*ourCampaign->lastScenario()).epilog;
@ -751,13 +738,14 @@ void CServerHandler::startCampaignScenario(HighScoreParameter param, std::shared
GH.windows().createAndPushWindow<CHighScoreInputScreen>(true, *highScoreCalc);
}
};
threadRunLocalServer.join();
if(epilogue.hasPrologEpilog)
{
GH.windows().createAndPushWindow<CPrologEpilogVideo>(epilogue, finisher);
}
else
{
CSH->campaignServerRestartLock.waitUntil(false);
finisher();
}
});
@ -877,23 +865,19 @@ public:
void CServerHandler::onPacketReceived(const std::shared_ptr<INetworkConnection> &, const std::vector<std::byte> & message)
{
CPack * pack = c->retrievePack(message);
if(state == EClientState::DISCONNECTING)
{
// FIXME: server shouldn't really send netpacks after it's tells client to disconnect
// Though currently they'll be delivered and might cause crash.
vstd::clear_pointer(pack);
}
else
{
ServerHandlerCPackVisitor visitor(*this);
pack->visit(visitor);
assert(0); //Should not be possible - socket must be closed at this point
return;
}
CPack * pack = c->retrievePack(message);
ServerHandlerCPackVisitor visitor(*this);
pack->visit(visitor);
}
void CServerHandler::onDisconnected(const std::shared_ptr<INetworkConnection> & connection, const std::string & errorMessage)
{
assert(networkConnection == connection);
networkConnection.reset();
if(state == EClientState::DISCONNECTING)
@ -987,17 +971,9 @@ void CServerHandler::threadRunServer(bool connectToLobby)
logNetwork->error("Error: server failed to close correctly or crashed!");
logNetwork->error("Check %s for more info", logName);
}
onServerFinished();
#endif
}
void CServerHandler::onServerFinished()
{
threadRunLocalServer.reset();
if (CSH)
CSH->campaignServerRestartLock.setn(false);
}
void CServerHandler::sendLobbyPack(const CPackForLobby & pack) const
{
if(state != EClientState::STARTING)

View File

@ -111,7 +111,6 @@ class CServerHandler final : public IServerAPI, public LobbyInfo, public INetwor
/// required to correctly deserialize gamestate using client-side game callback
std::unique_ptr<CClient> nextClient;
void onServerFinished();
void sendLobbyPack(const CPackForLobby & pack) const override;
void onPacketReceived(const NetworkConnectionPtr &, const std::vector<std::byte> & message) override;
@ -145,13 +144,11 @@ public:
////////////////////
std::unique_ptr<CStopWatch> th;
std::unique_ptr<boost::thread> threadRunLocalServer;
std::unique_ptr<boost::thread> threadNetwork;
boost::thread threadRunLocalServer;
boost::thread threadNetwork;
std::unique_ptr<CClient> client;
CondSh<bool> campaignServerRestartLock;
CServerHandler();
~CServerHandler();
@ -202,7 +199,8 @@ public:
void debugStartTest(std::string filename, bool save = false);
void startGameplay(VCMI_LIB_WRAP_NAMESPACE(CGameState) * gameState = nullptr);
void endGameplay(bool closeConnection = true, bool restart = false);
void endGameplay();
void restartGameplay();
void startCampaignScenario(HighScoreParameter param, std::shared_ptr<CampaignState> cs = {});
void showServerError(const std::string & txt) const;

View File

@ -34,7 +34,7 @@ public:
virtual void visitLobbyClientConnected(LobbyClientConnected & pack) override;
virtual void visitLobbyClientDisconnected(LobbyClientDisconnected & pack) override;
virtual void visitLobbyEndGame(LobbyEndGame & pack) override;
virtual void visitLobbyRestartGame(LobbyRestartGame & pack) override;
virtual void visitLobbyStartGame(LobbyStartGame & pack) override;
virtual void visitLobbyUpdateState(LobbyUpdateState & pack) override;
};

View File

@ -133,18 +133,15 @@ void ApplyOnLobbyScreenNetPackVisitor::visitLobbyGuiAction(LobbyGuiAction & pack
}
}
void ApplyOnLobbyHandlerNetPackVisitor::visitLobbyEndGame(LobbyEndGame & pack)
void ApplyOnLobbyHandlerNetPackVisitor::visitLobbyRestartGame(LobbyRestartGame & pack)
{
if(handler.state == EClientState::GAMEPLAY)
{
handler.endGameplay(pack.closeConnection, pack.restart);
handler.restartGameplay();
}
if(pack.restart)
{
if (handler.validateGameStart())
handler.sendStartGame();
}
if (handler.validateGameStart())
handler.sendStartGame();
}
void ApplyOnLobbyHandlerNetPackVisitor::visitLobbyStartGame(LobbyStartGame & pack)

View File

@ -13,7 +13,7 @@
VCMI_LIB_NAMESPACE_BEGIN
class NetworkConnection : public INetworkConnection, std::enable_shared_from_this<NetworkConnection>
class NetworkConnection : public INetworkConnection, public std::enable_shared_from_this<NetworkConnection>
{
static const int messageHeaderSize = sizeof(uint32_t);
static const int messageMaxSize = 64 * 1024 * 1024; // arbitrary size to prevent potential massive allocation if we receive garbage input

View File

@ -151,7 +151,7 @@ public:
virtual void visitLobbyChatMessage(LobbyChatMessage & pack) {}
virtual void visitLobbyGuiAction(LobbyGuiAction & pack) {}
virtual void visitLobbyLoadProgress(LobbyLoadProgress & pack) {}
virtual void visitLobbyEndGame(LobbyEndGame & pack) {}
virtual void visitLobbyRestartGame(LobbyRestartGame & pack) {}
virtual void visitLobbyStartGame(LobbyStartGame & pack) {}
virtual void visitLobbyChangeHost(LobbyChangeHost & pack) {}
virtual void visitLobbyUpdateState(LobbyUpdateState & pack) {}

View File

@ -708,9 +708,9 @@ void LobbyLoadProgress::visitTyped(ICPackVisitor & visitor)
visitor.visitLobbyLoadProgress(*this);
}
void LobbyEndGame::visitTyped(ICPackVisitor & visitor)
void LobbyRestartGame::visitTyped(ICPackVisitor & visitor)
{
visitor.visitLobbyEndGame(*this);
visitor.visitLobbyRestartGame(*this);
}
void LobbyStartGame::visitTyped(ICPackVisitor & visitor)

View File

@ -111,17 +111,12 @@ struct DLL_LINKAGE LobbyLoadProgress : public CLobbyPackToPropagate
}
};
struct DLL_LINKAGE LobbyEndGame : public CLobbyPackToPropagate
struct DLL_LINKAGE LobbyRestartGame : public CLobbyPackToPropagate
{
bool closeConnection = false;
bool restart = false;
void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler &h)
{
h & closeConnection;
h & restart;
}
};

View File

@ -37,7 +37,7 @@ void registerTypesLobbyPacks(Serializer &s)
// Only host client send
s.template registerType<CLobbyPackToPropagate, LobbyGuiAction>();
s.template registerType<CLobbyPackToPropagate, LobbyLoadProgress>();
s.template registerType<CLobbyPackToPropagate, LobbyEndGame>();
s.template registerType<CLobbyPackToPropagate, LobbyRestartGame>();
s.template registerType<CLobbyPackToPropagate, LobbyStartGame>();
s.template registerType<CLobbyPackToPropagate, LobbyChangeHost>();
// Only server send

View File

@ -140,6 +140,7 @@ void CConnection::enterGameplayConnectionMode(CGameState * gs)
setCallback(gs->callback);
packWriter->addStdVecItems(gs);
packReader->addStdVecItems(gs);
}
void CConnection::disableSmartPointerSerialization()

View File

@ -445,7 +445,10 @@ void CGameHandler::changeSecSkill(const CGHeroInstance * hero, SecondarySkill wh
void CGameHandler::handleClientDisconnection(std::shared_ptr<CConnection> c)
{
if(lobby->getState() == EServerState::SHUTDOWN || !gs || !gs->scenarioOps)
{
assert(0); // game should have shut down before reaching this point!
return;
}
for(auto & playerConnections : connections)
{
@ -3609,7 +3612,7 @@ void CGameHandler::checkVictoryLossConditionsForPlayer(PlayerColor player)
if(p->human)
{
lobby->setState(EServerState::GAMEPLAY_ENDED);
lobby->setState(EServerState::SHUTDOWN);
}
}
else

View File

@ -117,9 +117,7 @@ public:
};
CVCMIServer::CVCMIServer(boost::program_options::variables_map & opts)
: restartGameplay(false)
, state(EServerState::LOBBY)
, currentClientId(1)
: currentClientId(1)
, currentPlayerId(1)
, cmdLineOptions(opts)
{
@ -153,13 +151,14 @@ void CVCMIServer::startAcceptingIncomingConnections()
void CVCMIServer::onNewConnection(const std::shared_ptr<INetworkConnection> & connection)
{
if(state == EServerState::LOBBY)
if(getState() == EServerState::LOBBY)
{
activeConnections.push_back(std::make_shared<CConnection>(connection));
activeConnections.back()->enterLobbyConnectionMode();
}
else
{
// TODO: reconnection support
connection->close();
}
}
@ -175,7 +174,11 @@ void CVCMIServer::onPacketReceived(const std::shared_ptr<INetworkConnection> & c
void CVCMIServer::setState(EServerState value)
{
assert(state != EServerState::SHUTDOWN); // do not attempt to restart dying server
state = value;
if (state == EServerState::SHUTDOWN)
networkHandler->stop();
}
EServerState CVCMIServer::getState() const
@ -208,7 +211,8 @@ void CVCMIServer::run()
void CVCMIServer::onTimer()
{
if (state != EServerState::GAMEPLAY)
// we might receive onTimer call after transitioning from GAMEPLAY to LOBBY state, e.g. on game restart
if (getState() != EServerState::GAMEPLAY)
return;
static const auto serverUpdateInterval = std::chrono::milliseconds(100);
@ -230,18 +234,20 @@ void CVCMIServer::onTimer()
void CVCMIServer::prepareToRestart()
{
if(state == EServerState::GAMEPLAY)
if(getState() != EServerState::GAMEPLAY)
{
restartGameplay = true;
* si = * gh->gs->initialOpts;
si->seedToBeUsed = si->seedPostInit = 0;
state = EServerState::LOBBY;
if (si->campState)
{
assert(si->campState->currentScenario().has_value());
campaignMap = si->campState->currentScenario().value_or(CampaignScenarioID(0));
campaignBonus = si->campState->getBonusID(campaignMap).value_or(-1);
}
assert(0);
return;
}
* si = * gh->gs->initialOpts;
si->seedToBeUsed = si->seedPostInit = 0;
setState(EServerState::LOBBY);
if (si->campState)
{
assert(si->campState->currentScenario().has_value());
campaignMap = si->campState->currentScenario().value_or(CampaignScenarioID(0));
campaignBonus = si->campState->getBonusID(campaignMap).value_or(-1);
}
for(auto c : activeConnections)
@ -319,7 +325,7 @@ void CVCMIServer::startGameImmediately()
c->enterGameplayConnectionMode(gh->gs);
gh->start(si->mode == EStartMode::LOAD_GAME);
state = EServerState::GAMEPLAY;
setState(EServerState::GAMEPLAY);
lastTimerUpdateTime = gameplayStartTime = std::chrono::steady_clock::now();
onTimer();
}
@ -333,12 +339,11 @@ void CVCMIServer::onDisconnected(const std::shared_ptr<INetworkConnection> & con
if(activeConnections.empty() || hostClientId == c->connectionID)
{
networkHandler->stop();
state = EServerState::SHUTDOWN;
setState(EServerState::SHUTDOWN);
return;
}
if(gh && state == EServerState::GAMEPLAY)
if(gh && getState() == EServerState::GAMEPLAY)
{
gh->handleClientDisconnection(c);
@ -406,7 +411,7 @@ bool CVCMIServer::passHost(int toConnectionId)
void CVCMIServer::clientConnected(std::shared_ptr<CConnection> c, std::vector<std::string> & names, const std::string & uuid, EStartMode mode)
{
assert(state == EServerState::LOBBY);
assert(getState() == EServerState::LOBBY);
c->connectionID = currentClientId++;
@ -446,13 +451,6 @@ void CVCMIServer::clientDisconnected(std::shared_ptr<CConnection> c)
c->getConnection()->close();
vstd::erase(activeConnections, c);
if(activeConnections.empty() || hostClientId == c->connectionID)
{
networkHandler->stop();
state = EServerState::SHUTDOWN;
return;
}
// PlayerReinitInterface startAiPack;
// startAiPack.playerConnectionId = PlayerSettings::PLAYER_AI;
//
@ -494,7 +492,7 @@ void CVCMIServer::reconnectPlayer(int connId)
PlayerReinitInterface startAiPack;
startAiPack.playerConnectionId = connId;
if(gh && si && state == EServerState::GAMEPLAY)
if(gh && si && getState() == EServerState::GAMEPLAY)
{
for(auto it = playerNames.begin(); it != playerNames.end(); ++it)
{

View File

@ -42,9 +42,7 @@ class GlobalLobbyProcessor;
enum class EServerState : ui8
{
LOBBY,
GAMEPLAY_STARTING,
GAMEPLAY,
GAMEPLAY_ENDED,
SHUTDOWN
};
@ -59,10 +57,8 @@ class CVCMIServer : public LobbyInfo, public INetworkServerListener, public INet
std::unique_ptr<INetworkHandler> networkHandler;
bool restartGameplay; // FIXME: this is just a hack
std::shared_ptr<CApplier<CBaseForServerApply>> applier;
EServerState state;
EServerState state = EServerState::LOBBY;
std::shared_ptr<CConnection> findConnection(const std::shared_ptr<INetworkConnection> &);

View File

@ -31,7 +31,8 @@ void GlobalLobbyProcessor::onDisconnected(const std::shared_ptr<INetworkConnecti
{
if (connection == controlConnection)
{
throw std::runtime_error("Lost connection to a lobby server!");
owner.setState(EServerState::SHUTDOWN);
return;
}
else
{
@ -68,7 +69,7 @@ void GlobalLobbyProcessor::receiveOperationFailed(const JsonNode & json)
{
logGlobal->info("Lobby: Failed to login into a lobby server!");
throw std::runtime_error("Failed to login into a lobby server!");
owner.setState(EServerState::SHUTDOWN);
}
void GlobalLobbyProcessor::receiveLoginSuccess(const JsonNode & json)
@ -91,7 +92,7 @@ void GlobalLobbyProcessor::receiveAccountJoinsRoom(const JsonNode & json)
void GlobalLobbyProcessor::onConnectionFailed(const std::string & errorMessage)
{
throw std::runtime_error("Failed to connect to a lobby server!");
owner.setState(EServerState::SHUTDOWN);
}
void GlobalLobbyProcessor::onConnectionEstablished(const std::shared_ptr<INetworkConnection> & connection)

View File

@ -31,7 +31,7 @@ public:
virtual void visitForLobby(CPackForLobby & pack) override;
virtual void visitLobbyClientConnected(LobbyClientConnected & pack) override;
virtual void visitLobbyClientDisconnected(LobbyClientDisconnected & pack) override;
virtual void visitLobbyEndGame(LobbyEndGame & pack) override;
virtual void visitLobbyRestartGame(LobbyRestartGame & pack) override;
virtual void visitLobbyStartGame(LobbyStartGame & pack) override;
virtual void visitLobbyChangeHost(LobbyChangeHost & pack) override;
virtual void visitLobbyChangePlayerOption(LobbyChangePlayerOption & pack) override;
@ -53,7 +53,7 @@ public:
virtual void visitForLobby(CPackForLobby & pack) override;
virtual void visitLobbyClientConnected(LobbyClientConnected & pack) override;
virtual void visitLobbyClientDisconnected(LobbyClientDisconnected & pack) override;
virtual void visitLobbyEndGame(LobbyEndGame & pack) override;
virtual void visitLobbyRestartGame(LobbyRestartGame & pack) override;
virtual void visitLobbyStartGame(LobbyStartGame & pack) override;
virtual void visitLobbyChangeHost(LobbyChangeHost & pack) override;
};
@ -81,7 +81,7 @@ public:
virtual void visitLobbySetCampaign(LobbySetCampaign & pack) override;
virtual void visitLobbySetCampaignMap(LobbySetCampaignMap & pack) override;
virtual void visitLobbySetCampaignBonus(LobbySetCampaignBonus & pack) override;
virtual void visitLobbyEndGame(LobbyEndGame & pack) override;
virtual void visitLobbyRestartGame(LobbyRestartGame & pack) override;
virtual void visitLobbyStartGame(LobbyStartGame & pack) override;
virtual void visitLobbyChangeHost(LobbyChangeHost & pack) override;
virtual void visitLobbyChangePlayerOption(LobbyChangePlayerOption & pack) override;

View File

@ -36,14 +36,7 @@ void ApplyOnServerAfterAnnounceNetPackVisitor::visitForLobby(CPackForLobby & pac
void ClientPermissionsCheckerNetPackVisitor::visitLobbyClientConnected(LobbyClientConnected & pack)
{
if(srv.getState() == EServerState::LOBBY)
{
result = true;
return;
}
result = false;
return;
result = srv.getState() == EServerState::LOBBY;
}
void ApplyOnServerNetPackVisitor::visitLobbyClientConnected(LobbyClientConnected & pack)
@ -197,19 +190,19 @@ void ClientPermissionsCheckerNetPackVisitor::visitLobbyGuiAction(LobbyGuiAction
result = srv.isClientHost(pack.c->connectionID);
}
void ClientPermissionsCheckerNetPackVisitor::visitLobbyEndGame(LobbyEndGame & pack)
void ClientPermissionsCheckerNetPackVisitor::visitLobbyRestartGame(LobbyRestartGame & pack)
{
result = srv.isClientHost(pack.c->connectionID);
}
void ApplyOnServerNetPackVisitor::visitLobbyEndGame(LobbyEndGame & pack)
void ApplyOnServerNetPackVisitor::visitLobbyRestartGame(LobbyRestartGame & pack)
{
srv.prepareToRestart();
result = true;
}
void ApplyOnServerAfterAnnounceNetPackVisitor::visitLobbyEndGame(LobbyEndGame & pack)
void ApplyOnServerAfterAnnounceNetPackVisitor::visitLobbyRestartGame(LobbyRestartGame & pack)
{
for(auto & c : srv.activeConnections)
c->enterLobbyConnectionMode();
@ -241,8 +234,6 @@ void ApplyOnServerNetPackVisitor::visitLobbyStartGame(LobbyStartGame & pack)
pack.initializedStartInfo = std::make_shared<StartInfo>(*srv.gh->getStartInfo(true));
pack.initializedGameState = srv.gh->gameState();
srv.setState(EServerState::GAMEPLAY_STARTING);
result = true;
}

View File

@ -233,7 +233,7 @@ void TurnOrderProcessor::doStartNewDay()
if(!activePlayer)
{
gameHandler->gameLobby()->setState(EServerState::GAMEPLAY_ENDED);
gameHandler->gameLobby()->setState(EServerState::SHUTDOWN);
return;
}