diff --git a/client/CMT.cpp b/client/CMT.cpp index d23c15277..10c4ea893 100644 --- a/client/CMT.cpp +++ b/client/CMT.cpp @@ -55,7 +55,6 @@ namespace po = boost::program_options; namespace po_style = boost::program_options::command_line_style; -static std::atomic quitRequestedDuringOpeningPlayback = false; static std::atomic 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) diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index f7398d65e..12ff0c09a 100644 --- a/client/CPlayerInterface.cpp +++ b/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 diff --git a/client/CPlayerInterface.h b/client/CPlayerInterface.h index 11f9388b6..e07c5bcb0 100644 --- a/client/CPlayerInterface.h +++ b/client/CPlayerInterface.h @@ -226,7 +226,7 @@ private: void heroKilled(const CGHeroInstance* hero); void garrisonsChanged(std::vector 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); };