Explorar o código

Fixes and cleanup of game client network shutdown and restart

Ivan Savenko hai 1 ano
pai
achega
2c2bec791c

+ 42 - 66
client/CServerHandler.cpp

@@ -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)

+ 4 - 6
client/CServerHandler.h

@@ -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;
 

+ 1 - 1
client/LobbyClientNetPackVisitors.h

@@ -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;
 };

+ 4 - 7
client/NetPacksLobbyClient.cpp

@@ -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)

+ 1 - 1
lib/network/NetworkConnection.h

@@ -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

+ 1 - 1
lib/networkPacks/NetPackVisitor.h

@@ -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) {}

+ 2 - 2
lib/networkPacks/NetPacksLib.cpp

@@ -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)

+ 1 - 6
lib/networkPacks/PacksForLobby.h

@@ -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;
 	}
 };
 

+ 1 - 1
lib/registerTypes/RegisterTypesLobbyPacks.h

@@ -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

+ 1 - 0
lib/serializer/Connection.cpp

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

+ 4 - 1
server/CGameHandler.cpp

@@ -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

+ 27 - 29
server/CVCMIServer.cpp

@@ -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)
 		{

+ 1 - 5
server/CVCMIServer.h

@@ -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> &);
 

+ 4 - 3
server/GlobalLobbyProcessor.cpp

@@ -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)

+ 3 - 3
server/LobbyNetPackVisitors.h

@@ -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;

+ 4 - 13
server/NetPacksLobbyServer.cpp

@@ -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;
 }
 

+ 1 - 1
server/processors/TurnOrderProcessor.cpp

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