From 6b9d2809b175bd7e5f12021f716d25eb3f0c16c3 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Mon, 17 Jun 2024 13:23:44 +0000 Subject: [PATCH 1/7] Fix crash on Android OS shutdown request --- client/Client.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/client/Client.cpp b/client/Client.cpp index 9312e228b..817fdd410 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -738,6 +738,13 @@ extern "C" JNIEXPORT jboolean JNICALL Java_eu_vcmi_vcmi_NativeMethods_tryToSaveT logGlobal->info("Received emergency save game request"); if(!LOCPLINT || !LOCPLINT->cb) { + logGlobal->info("... but no active player interface found!"); + return false; + } + + if (!CSH || !CSH->logicConnection) + { + logGlobal->info("... but no active connection found!"); return false; } From 4f64b1f7e6e7abfcb54e22d4141f298c4767fd31 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Mon, 17 Jun 2024 13:24:07 +0000 Subject: [PATCH 2/7] Try to localize crash on missing combat animation --- client/widgets/MiscWidgets.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/widgets/MiscWidgets.cpp b/client/widgets/MiscWidgets.cpp index 20ff09686..00b1f1824 100644 --- a/client/widgets/MiscWidgets.cpp +++ b/client/widgets/MiscWidgets.cpp @@ -637,6 +637,9 @@ CCreaturePic::CCreaturePic(int x, int y, const CCreature * cre, bool Big, bool A assert(CGI->townh->size() > faction); + if (cre->animDefName.empty()) + throw std::runtime_error("Creature " + cre->getJsonKey() + " has no valid combat animation!"); + if(Big) bg = std::make_shared((*CGI->townh)[faction]->creatureBg130); else From e08f76ddf0c365f7abad57378ab58a1207c25501 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Mon, 17 Jun 2024 16:17:01 +0000 Subject: [PATCH 3/7] Add missing lock to Android shutdown logic --- client/Client.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/Client.cpp b/client/Client.cpp index 817fdd410..238297fee 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -735,6 +735,8 @@ void CClient::removeGUI() const #ifdef VCMI_ANDROID extern "C" JNIEXPORT jboolean JNICALL Java_eu_vcmi_vcmi_NativeMethods_tryToSaveTheGame(JNIEnv * env, jclass cls) { + boost::mutex::scoped_lock interfaceLock(GH.interfaceMutex); + logGlobal->info("Received emergency save game request"); if(!LOCPLINT || !LOCPLINT->cb) { From ffa5c03515fe9da242ca021cb2adf1a796c9de9f Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Mon, 17 Jun 2024 17:08:41 +0000 Subject: [PATCH 4/7] Load & decode high score creatures on first access --- client/mainmenu/CHighScoreScreen.cpp | 36 ++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/client/mainmenu/CHighScoreScreen.cpp b/client/mainmenu/CHighScoreScreen.cpp index 1b209bb37..f8a48945c 100644 --- a/client/mainmenu/CHighScoreScreen.cpp +++ b/client/mainmenu/CHighScoreScreen.cpp @@ -62,17 +62,43 @@ auto HighScoreCalculation::calculate() return summary; } +struct HighScoreCreature +{ + CreatureID creature; + int min; + int max; +}; + +static std::vector getHighscoreCreaturesList() +{ + JsonNode configCreatures(JsonPath::builtin("CONFIG/highscoreCreatures.json")); + + std::vector ret; + + for(auto & json : configCreatures["creatures"].Vector()) + { + HighScoreCreature entry; + entry.creature = CreatureID::decode(json["creature"].String()); + entry.max = json["max"].isNull() ? std::numeric_limits::max() : json["max"].Integer(); + entry.min = json["min"].isNull() ? std::numeric_limits::min() : json["min"].Integer(); + + ret.push_back(entry); + } + + return ret; +} + CreatureID HighScoreCalculation::getCreatureForPoints(int points, bool campaign) { - static const JsonNode configCreatures(JsonPath::builtin("CONFIG/highscoreCreatures.json")); - auto creatures = configCreatures["creatures"].Vector(); + static const std::vector creatures = getHighscoreCreaturesList(); + int divide = campaign ? 5 : 1; for(auto & creature : creatures) - if(points / divide <= creature["max"].Integer() && points / divide >= creature["min"].Integer()) - return CreatureID::decode(creature["creature"].String()); + if(points / divide <= creature.max && points / divide >= creature.min) + return creature.creature; - return -1; + throw std::runtime_error("Unable to find creature for score " + std::to_string(points)); } CHighScoreScreen::CHighScoreScreen(HighScorePage highscorepage, int highlighted) From 9917db71ccf51b22baa504309b1fb84471304813 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Mon, 17 Jun 2024 17:08:52 +0000 Subject: [PATCH 5/7] fix crash on score outside 0...500 range --- config/highscoreCreatures.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/highscoreCreatures.json b/config/highscoreCreatures.json index b0feda288..17d6e4349 100644 --- a/config/highscoreCreatures.json +++ b/config/highscoreCreatures.json @@ -1,6 +1,6 @@ { "creatures": [ - { "min" : 1, "max" : 4, "creature": "imp" }, + { "max" : 4, "creature": "imp" }, { "min" : 5, "max" : 8, "creature": "gremlin" }, { "min" : 9, "max" : 12, "creature": "gnoll" }, { "min" : 13, "max" : 16, "creature": "troglodyte" }, @@ -117,6 +117,6 @@ { "min" : 389, "max" : 391, "creature": "titan" }, { "min" : 392, "max" : 394, "creature": "goldDragon" }, { "min" : 395, "max" : 397, "creature": "blackDragon" }, - { "min" : 398, "max" : 500, "creature": "archangel" } + { "min" : 398, "creature": "archangel" } ] } \ No newline at end of file From dd045e2dc7205e3c0f9c145e4eb735369859b246 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Mon, 17 Jun 2024 17:09:19 +0000 Subject: [PATCH 6/7] Fix crash on transparency test on null surface --- client/renderSDL/SDLImage.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/renderSDL/SDLImage.cpp b/client/renderSDL/SDLImage.cpp index 465597b63..6dbe8db94 100644 --- a/client/renderSDL/SDLImage.cpp +++ b/client/renderSDL/SDLImage.cpp @@ -235,7 +235,10 @@ void SDLImage::setFlagColor(PlayerColor player) bool SDLImage::isTransparent(const Point & coords) const { - return CSDL_Ext::isTransparent(surf, coords.x, coords.y); + if (surf) + return CSDL_Ext::isTransparent(surf, coords.x, coords.y); + else + return true; } Point SDLImage::dimensions() const From 0af2f6d8dc73ea56f418f462c625319dc43e8cb9 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Mon, 17 Jun 2024 17:09:42 +0000 Subject: [PATCH 7/7] Fix crash on opening tavern window on some localizations --- client/windows/GUIClasses.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/client/windows/GUIClasses.cpp b/client/windows/GUIClasses.cpp index 60b4caef7..6747df0ad 100644 --- a/client/windows/GUIClasses.cpp +++ b/client/windows/GUIClasses.cpp @@ -491,14 +491,21 @@ CTavernWindow::CTavernWindow(const CGObjectInstance * TavernObj, const std::func } else if(LOCPLINT->cb->howManyHeroes(true) >= CGI->settings()->getInteger(EGameSettings::HEROES_PER_PLAYER_TOTAL_CAP)) { + MetaString message; + message.appendTextID("core.tvrninfo.1"); + message.replaceNumber(LOCPLINT->cb->howManyHeroes(true)); + //Cannot recruit. You already have %d Heroes. - recruit->addHoverText(EButtonState::NORMAL, boost::str(boost::format(CGI->generaltexth->tavernInfo[1]) % LOCPLINT->cb->howManyHeroes(true))); + recruit->addHoverText(EButtonState::NORMAL, message.toString()); recruit->block(true); } else if(LOCPLINT->cb->howManyHeroes(false) >= CGI->settings()->getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP)) { - //Cannot recruit. You already have %d Heroes. - recruit->addHoverText(EButtonState::NORMAL, boost::str(boost::format(CGI->generaltexth->tavernInfo[1]) % LOCPLINT->cb->howManyHeroes(false))); + MetaString message; + message.appendTextID("core.tvrninfo.1"); + message.replaceNumber(LOCPLINT->cb->howManyHeroes(false)); + + recruit->addHoverText(EButtonState::NORMAL, message.toString()); recruit->block(true); } else if(dynamic_cast(TavernObj) && dynamic_cast(TavernObj)->visitingHero)