Răsfoiți Sursa

Merge pull request #3860 from IvanSavenko/bugfixing

Fix freezes (multiplayer and game loading)
Ivan Savenko 1 an în urmă
părinte
comite
a5361abe16
3 a modificat fișierele cu 33 adăugiri și 32 ștergeri
  1. 19 20
      client/CMT.cpp
  2. 13 11
      client/CPlayerInterface.cpp
  3. 1 1
      client/CPlayerInterface.h

+ 19 - 20
client/CMT.cpp

@@ -55,7 +55,6 @@
 namespace po = boost::program_options;
 namespace po_style = boost::program_options::command_line_style;
 
-static std::atomic<bool> quitRequestedDuringOpeningPlayback = false;
 static std::atomic<bool> headlessQuit = false;
 
 #ifndef VCMI_IOS
@@ -323,9 +322,6 @@ int main(int argc, char * argv[])
 	#endif // ANDROID
 #endif // THREADED
 
-	if (quitRequestedDuringOpeningPlayback)
-		quitApplication();
-
 	if(!settings["session"]["headless"].Bool())
 	{
 		pomtime.getDiff();
@@ -416,6 +412,20 @@ static void mainLoop()
 	}
 }
 
+[[noreturn]] static void quitApplicationImmediately()
+{
+	// Perform quick exit without executing static destructors and let OS cleanup anything that we did not
+	// We generally don't care about them and this leads to numerous issues, e.g.
+	// destruction of locked mutexes (fails an assertion), even in third-party libraries (as well as native libs on Android)
+	// Android - std::quick_exit is available only starting from API level 21
+	// Mingw, macOS and iOS - std::quick_exit is unavailable (at least in current version of CI)
+#if (defined(__ANDROID_API__) && __ANDROID_API__ < 21) || (defined(__MINGW32__)) || defined(VCMI_APPLE)
+	::exit(0);
+#else
+	std::quick_exit(0);
+#endif
+}
+
 [[noreturn]] static void quitApplication()
 {
 	if(!settings["session"]["headless"].Bool())
@@ -466,24 +476,11 @@ static void mainLoop()
 	}
 
 	std::cout << "Ending...\n";
-
-	// Perform quick exit without executing static destructors and let OS cleanup anything that we did not
-	// We generally don't care about them and this leads to numerous issues, e.g.
-	// destruction of locked mutexes (fails an assertion), even in third-party libraries (as well as native libs on Android)
-	// Android - std::quick_exit is available only starting from API level 21
-	// Mingw, macOS and iOS - std::quick_exit is unavailable (at least in current version of CI)
-#if (defined(__ANDROID_API__) && __ANDROID_API__ < 21) || (defined(__MINGW32__)) || defined(VCMI_APPLE)
-	::exit(0);
-#else
-	std::quick_exit(0);
-#endif
+	quitApplicationImmediately();
 }
 
 void handleQuit(bool ask)
 {
-	// FIXME: avoids crash if player attempts to close game while opening is still playing
-	// use cursor handler as indicator that loading is not done yet
-	// proper solution would be to abort init thread (or wait for it to finish)
 	if(!ask)
 	{
 		if(settings["session"]["headless"].Bool())
@@ -498,10 +495,12 @@ void handleQuit(bool ask)
 		return;
 	}
 
+	// FIXME: avoids crash if player attempts to close game while opening is still playing
+	// use cursor handler as indicator that loading is not done yet
+	// proper solution would be to abort init thread (or wait for it to finish)
 	if (!CCS->curh)
 	{
-		quitRequestedDuringOpeningPlayback = true;
-		return;
+		quitApplicationImmediately();
 	}
 
 	if (LOCPLINT)

+ 13 - 11
client/CPlayerInterface.cpp

@@ -279,7 +279,14 @@ void CPlayerInterface::yourTurn(QueryID queryID)
 	CTutorialWindow::openWindowFirstTime(TutorialMode::TOUCH_ADVENTUREMAP);
 
 	EVENT_HANDLER_CALLED_BY_CLIENT;
-	{
+
+	int humanPlayersCount = 0;
+	for(const auto & info : cb->getStartInfo()->playerInfos)
+		if (info.second.isControlledByHuman())
+			humanPlayersCount++;
+
+	bool hotseatWait = humanPlayersCount > 1;
+
 		LOCPLINT = this;
 		GH.curInt = this;
 
@@ -289,12 +296,7 @@ void CPlayerInterface::yourTurn(QueryID queryID)
 			performAutosave();
 		}
 
-		int humanPlayersCount = 0;
-		for(const auto & info : cb->getStartInfo()->playerInfos)
-			if (info.second.isControlledByHuman())
-				humanPlayersCount++;
-
-		if (humanPlayersCount > 1) //hot seat or MP message
+		if (hotseatWait) //hot seat or MP message
 		{
 			adventureInt->onHotseatWaitStarted(playerID);
 
@@ -310,11 +312,11 @@ void CPlayerInterface::yourTurn(QueryID queryID)
 			makingTurn = true;
 			adventureInt->onPlayerTurnStarted(playerID);
 		}
-	}
-	acceptTurn(queryID);
+
+	acceptTurn(queryID, hotseatWait);
 }
 
-void CPlayerInterface::acceptTurn(QueryID queryID)
+void CPlayerInterface::acceptTurn(QueryID queryID, bool hotseatWait)
 {
 	if (settings["session"]["autoSkip"].Bool())
 	{
@@ -322,7 +324,7 @@ void CPlayerInterface::acceptTurn(QueryID queryID)
 			iw->close();
 	}
 
-	if(CSH->howManyPlayerInterfaces() > 1)
+	if(hotseatWait)
 	{
 		waitWhileDialog(); // wait for player to accept turn in hot-seat mode
 

+ 1 - 1
client/CPlayerInterface.h

@@ -226,7 +226,7 @@ private:
 	void heroKilled(const CGHeroInstance* hero);
 	void garrisonsChanged(std::vector<const CArmedInstance *> objs);
 	void requestReturningToMainMenu(bool won);
-	void acceptTurn(QueryID queryID); //used during hot seat after your turn message is close
+	void acceptTurn(QueryID queryID, bool hotseatWait); //used during hot seat after your turn message is close
 	void initializeHeroTownList();
 	int getLastIndex(std::string namePrefix);
 };