Browse Source

Fix "Start game" blocking status:

- Start game is now initially blocked
- Receiving valid startInfo from server will unlock button
Ivan Savenko 2 years ago
parent
commit
538665fe42

+ 22 - 4
client/CServerHandler.cpp

@@ -573,18 +573,36 @@ void CServerHandler::sendRestartGame() const
 	sendLobbyPack(endGame);
 }
 
-void CServerHandler::sendStartGame(bool allowOnlyAI) const
+bool CServerHandler::validateGameStart(bool allowOnlyAI) const
 {
 	try
 	{
 		verifyStateBeforeStart(allowOnlyAI ? true : settings["session"]["onlyai"].Bool());
 	}
-	catch (const std::exception & e)
+	catch(CModHandler::Incompatibility & e)
 	{
+		logGlobal->warn("Incompatibility exception during start scenario: %s", e.what());
+
+		auto errorMsg = CGI->generaltexth->translate("vcmi.server.errors.modsIncompatibility") + '\n';
+		errorMsg += e.what();
+
+		showServerError(errorMsg);
+		return false;
+	}
+	catch(std::exception & e)
+	{
+		logGlobal->error("Exception during startScenario: %s", e.what());
 		showServerError( std::string("Unable to start map! Reason: ") + e.what());
-		return;
+		return false;
 	}
 
+	return true;
+}
+
+void CServerHandler::sendStartGame(bool allowOnlyAI) const
+{
+	verifyStateBeforeStart(allowOnlyAI ? true : settings["session"]["onlyai"].Bool());
+
 	LobbyStartGame lsg;
 	if(client)
 	{
@@ -708,7 +726,7 @@ void CServerHandler::startCampaignScenario(std::shared_ptr<CampaignState> cs)
 	});
 }
 
-void CServerHandler::showServerError(std::string txt) const
+void CServerHandler::showServerError(const std::string & txt) const
 {
 	CInfoWindow::showInfoDialog(txt, {});
 }

+ 3 - 2
client/CServerHandler.h

@@ -148,16 +148,17 @@ public:
 	void sendRestartGame() const override;
 	void sendStartGame(bool allowOnlyAI = false) const override;
 
+	bool validateGameStart(bool allowOnlyAI = false) const;
+
 	void startGameplay(VCMI_LIB_WRAP_NAMESPACE(CGameState) * gameState = nullptr);
 	void endGameplay(bool closeConnection = true, bool restart = false);
 	void startCampaignScenario(std::shared_ptr<CampaignState> cs = {});
-	void showServerError(std::string txt) const;
+	void showServerError(const std::string & txt) const;
 
 	// TODO: LobbyState must be updated within game so we should always know how many player interfaces our client handle
 	int howManyPlayerInterfaces();
 	ui8 getLoadMode();
 
-	void debugStartTest(std::string filename, bool save = false);
 	void restoreLastSession();
 
 	void visitForLobby(CPackForLobby & lobbyPack);

+ 4 - 1
client/NetPacksLobbyClient.cpp

@@ -102,7 +102,10 @@ void ApplyOnLobbyHandlerNetPackVisitor::visitLobbyEndGame(LobbyEndGame & pack)
 	}
 	
 	if(pack.restart)
-		handler.sendStartGame();
+	{
+		if (handler.validateGameStart())
+			handler.sendStartGame();
+	}
 }
 
 void ApplyOnLobbyHandlerNetPackVisitor::visitLobbyStartGame(LobbyStartGame & pack)

+ 4 - 1
client/lobby/CBonusSelection.cpp

@@ -343,7 +343,7 @@ void CBonusSelection::updateAfterStateChange()
 	{
 		buttonStart->block(getCampaign()->scenario(CSH->campaignMap).travelOptions.bonusesToChoose.size());
 	}
-	else if(buttonStart->isBlocked())
+	else
 	{
 		buttonStart->block(false);
 	}
@@ -390,6 +390,9 @@ void CBonusSelection::goBack()
 
 void CBonusSelection::startMap()
 {
+	if (!CSH->validateGameStart())
+		return;
+
 	auto showPrologVideo = [=]()
 	{
 		auto exitCb = [=]()

+ 5 - 24
client/lobby/CLobbyScreen.cpp

@@ -88,6 +88,8 @@ CLobbyScreen::CLobbyScreen(ESelectionScreen screenType)
 		break;
 	}
 
+	buttonStart->block(true); // to be unblocked after map list is ready
+
 	buttonBack = std::make_shared<CButton>(Point(581, 535), "SCNRBACK.DEF", CGI->generaltexth->zelp[105], [&]()
 	{
 		CSH->sendClientDisconnecting();
@@ -126,34 +128,11 @@ void CLobbyScreen::startCampaign()
 
 void CLobbyScreen::startScenario(bool allowOnlyAI)
 {
-	try
+	if (CSH->validateGameStart(allowOnlyAI))
 	{
 		CSH->sendStartGame(allowOnlyAI);
 		buttonStart->block(true);
 	}
-	catch(CModHandler::Incompatibility & e)
-	{
-		logGlobal->warn("Incompatibility exception during start scenario: %s", e.what());
-		
-		auto errorMsg = CGI->generaltexth->translate("vcmi.server.errors.modsIncompatibility") + '\n';
-		errorMsg += e.what();
-		
-		CInfoWindow::showInfoDialog(errorMsg, CInfoWindow::TCompsInfo(), PlayerColor(1));
-	}
-	catch(std::exception & e)
-	{
-		logGlobal->error("Exception during startScenario: %s", e.what());
-		
-		if(std::string(e.what()) == "ExceptionNoHuman")
-			CInfoWindow::showInfoDialog(CGI->generaltexth->allTexts[530], CInfoWindow::TCompsInfo(), PlayerColor(1));
-		
-		if(std::string(e.what()) == "ExceptionNoTemplate")
-			CInfoWindow::showInfoDialog(CGI->generaltexth->allTexts[751], CInfoWindow::TCompsInfo(), PlayerColor(1));
-	}
-	catch(...)
-	{
-		logGlobal->error("Unknown exception");
-	}
 }
 
 void CLobbyScreen::toggleMode(bool host)
@@ -192,6 +171,8 @@ void CLobbyScreen::updateAfterStateChange()
 	if(CSH->mi && tabOpt)
 		tabOpt->recreate();
 
+	buttonStart->block(CSH->mi == nullptr || CSH->isGuest());
+
 	card->changeSelection();
 	if (card->iconDifficulty)
 	{