From 925e09262927fe5315538ef57781a920f40e3d2c Mon Sep 17 00:00:00 2001 From: Yair Morgenstern Date: Wed, 16 Dec 2020 12:27:01 +0200 Subject: [PATCH] Solved ANR when loading large games from the load screen --- core/src/com/unciv/ui/saves/LoadGameScreen.kt | 42 ++++++----- .../unciv/ui/victoryscreen/VictoryScreen.kt | 74 +++++++++---------- 2 files changed, 61 insertions(+), 55 deletions(-) diff --git a/core/src/com/unciv/ui/saves/LoadGameScreen.kt b/core/src/com/unciv/ui/saves/LoadGameScreen.kt index 2341ee618f..407681ab86 100644 --- a/core/src/com/unciv/ui/saves/LoadGameScreen.kt +++ b/core/src/com/unciv/ui/saves/LoadGameScreen.kt @@ -38,24 +38,30 @@ class LoadGameScreen(previousScreen:CameraStageBaseScreen) : PickerScreen() { topTable.add(rightSideTable) rightSideButton.onClick { - try { - UncivGame.Current.loadGame(selectedSave) - } - catch (ex:Exception){ - val cantLoadGamePopup = Popup(this) - cantLoadGamePopup.addGoodSizedLabel("It looks like your saved game can't be loaded!").row() - if (ex is UncivShowableException && ex.localizedMessage != null) { - // thrown exceptions are our own tests and can be shown to the user - cantLoadGamePopup.addGoodSizedLabel(ex.localizedMessage).row() - cantLoadGamePopup.addCloseButton() - cantLoadGamePopup.open() - } else { - cantLoadGamePopup.addGoodSizedLabel("If you could copy your game data (\"Copy saved game to clipboard\" - ").row() - cantLoadGamePopup.addGoodSizedLabel(" paste into an email to yairm210@hotmail.com)").row() - cantLoadGamePopup.addGoodSizedLabel("I could maybe help you figure out what went wrong, since this isn't supposed to happen!").row() - cantLoadGamePopup.addCloseButton() - cantLoadGamePopup.open() - ex.printStackTrace() + ToastPopup("Loading...", this) + thread { + try { + // This is what can lead to ANRs - reading the file and setting the transients, that's why this is in another thread + val loadedGame = GameSaver.loadGameByName(selectedSave) + Gdx.app.postRunnable { UncivGame.Current.loadGame(loadedGame) } + } catch (ex: Exception) { + Gdx.app.postRunnable { + val cantLoadGamePopup = Popup(this) + cantLoadGamePopup.addGoodSizedLabel("It looks like your saved game can't be loaded!").row() + if (ex is UncivShowableException && ex.localizedMessage != null) { + // thrown exceptions are our own tests and can be shown to the user + cantLoadGamePopup.addGoodSizedLabel(ex.localizedMessage).row() + cantLoadGamePopup.addCloseButton() + cantLoadGamePopup.open() + } else { + cantLoadGamePopup.addGoodSizedLabel("If you could copy your game data (\"Copy saved game to clipboard\" - ").row() + cantLoadGamePopup.addGoodSizedLabel(" paste into an email to yairm210@hotmail.com)").row() + cantLoadGamePopup.addGoodSizedLabel("I could maybe help you figure out what went wrong, since this isn't supposed to happen!").row() + cantLoadGamePopup.addCloseButton() + cantLoadGamePopup.open() + ex.printStackTrace() + } + } } } } diff --git a/core/src/com/unciv/ui/victoryscreen/VictoryScreen.kt b/core/src/com/unciv/ui/victoryscreen/VictoryScreen.kt index 18b56ff949..739d6b24c7 100644 --- a/core/src/com/unciv/ui/victoryscreen/VictoryScreen.kt +++ b/core/src/com/unciv/ui/victoryscreen/VictoryScreen.kt @@ -28,7 +28,7 @@ class VictoryScreen(val worldScreen: WorldScreen) : PickerScreen() { init { val difficultyLabel = ("{Difficulty}: {${worldScreen.gameInfo.difficulty}}").toLabel() - difficultyLabel.setPosition(10f, stage.height-10, Align.topLeft) + difficultyLabel.setPosition(10f, stage.height - 10, Align.topLeft) stage.addActor(difficultyLabel) val tabsTable = Table().apply { defaults().pad(10f) } @@ -47,25 +47,25 @@ class VictoryScreen(val worldScreen: WorldScreen) : PickerScreen() { else setMyVictoryTable() - rightSideButton.isVisible=false + rightSideButton.isVisible = false var someoneHasWon = false val playerVictoryType = playerCivInfo.victoryManager.hasWonVictoryType() - if(playerVictoryType!=null){ - someoneHasWon=true - when(playerVictoryType){ + if (playerVictoryType != null) { + someoneHasWon = true + when (playerVictoryType) { VictoryType.Cultural -> wonOrLost("You have won a cultural victory!") VictoryType.Domination -> wonOrLost("You have won a domination victory!") // todo change translation VictoryType.Scientific -> wonOrLost("You have won a scientific victory!") } } - for(civ in game.gameInfo.civilizations.filter { it.isMajorCiv() && it!=playerCivInfo }){ + for (civ in game.gameInfo.civilizations.filter { it.isMajorCiv() && it != playerCivInfo }) { val civVictoryType = civ.victoryManager.hasWonVictoryType() - if(civVictoryType!=null){ - someoneHasWon=true + if (civVictoryType != null) { + someoneHasWon = true val winningCivName = civ.civName - when(civVictoryType){ + when (civVictoryType) { VictoryType.Cultural -> wonOrLost("[$winningCivName] has won a cultural victory!") VictoryType.Domination -> wonOrLost("[$winningCivName] has won a domination victory!") VictoryType.Scientific -> wonOrLost("[$winningCivName] has won a scientific victory!") @@ -75,7 +75,7 @@ class VictoryScreen(val worldScreen: WorldScreen) : PickerScreen() { if (playerCivInfo.isDefeated()) { wonOrLost("") - } else if(!someoneHasWon) { + } else if (!someoneHasWon) { setDefaultCloseAction() onBackButtonClicked { game.setWorldScreen() } } @@ -84,14 +84,14 @@ class VictoryScreen(val worldScreen: WorldScreen) : PickerScreen() { private fun wonOrLost(description: String) { - val endGameMessage = when(description){ + val endGameMessage = when (description) { "You have won a cultural victory!" -> "You have achieved victory through the awesome power of your Culture. Your civilization's greatness - the magnificence of its monuments and the power of its artists - have astounded the world! Poets will honor you as long as beauty brings gladness to a weary heart." "You have won a domination victory!" -> "The world has been convulsed by war. Many great and powerful civilizations have fallen, but you have survived - and emerged victorious! The world will long remember your glorious triumph!" "You have won a scientific victory!" -> "You have achieved victory through mastery of Science! You have conquered the mysteries of nature and led your people on a voyage to a brave new world! Your triumph will be remembered as long as the stars burn in the night sky!" else -> "You have been defeated. Your civilization has been overwhelmed by its many foes. But your people do not despair, for they know that one day you shall return - and lead them forward to victory!" } - descriptionLabel.setText(description.tr()+"\n"+endGameMessage.tr() ) + descriptionLabel.setText(description.tr() + "\n" + endGameMessage.tr()) rightSideButton.setText("Start new game".tr()) rightSideButton.isVisible = true @@ -111,29 +111,29 @@ class VictoryScreen(val worldScreen: WorldScreen) : PickerScreen() { private fun setMyVictoryTable() { val myVictoryStatusTable = Table() myVictoryStatusTable.defaults().pad(10f) - if(scientificVictoryEnabled) myVictoryStatusTable.add("Science victory".toLabel()) - if(culturalVictoryEnabled) myVictoryStatusTable.add("Cultural victory".toLabel()) - if(dominationVictoryEnabled) myVictoryStatusTable.add("Conquest victory".toLabel()) + if (scientificVictoryEnabled) myVictoryStatusTable.add("Science victory".toLabel()) + if (culturalVictoryEnabled) myVictoryStatusTable.add("Cultural victory".toLabel()) + if (dominationVictoryEnabled) myVictoryStatusTable.add("Conquest victory".toLabel()) myVictoryStatusTable.row() - if(scientificVictoryEnabled) myVictoryStatusTable.add(scienceVictoryColumn()) - if(culturalVictoryEnabled) myVictoryStatusTable.add(culturalVictoryColumn()) - if(dominationVictoryEnabled) myVictoryStatusTable.add(conquestVictoryColumn()) + if (scientificVictoryEnabled) myVictoryStatusTable.add(scienceVictoryColumn()) + if (culturalVictoryEnabled) myVictoryStatusTable.add(culturalVictoryColumn()) + if (dominationVictoryEnabled) myVictoryStatusTable.add(conquestVictoryColumn()) myVictoryStatusTable.row() - if(scientificVictoryEnabled) myVictoryStatusTable.add("Complete all the spaceship parts\n to win!".toLabel()) - if(culturalVictoryEnabled) myVictoryStatusTable.add("Complete 5 policy branches\n to win!".toLabel()) - if(dominationVictoryEnabled) myVictoryStatusTable.add("Destroy all enemies\n to win!".toLabel()) + if (scientificVictoryEnabled) myVictoryStatusTable.add("Complete all the spaceship parts\n to win!".toLabel()) + if (culturalVictoryEnabled) myVictoryStatusTable.add("Complete 5 policy branches\n to win!".toLabel()) + if (dominationVictoryEnabled) myVictoryStatusTable.add("Destroy all enemies\n to win!".toLabel()) contentsTable.clear() contentsTable.add(myVictoryStatusTable) } - private fun scienceVictoryColumn():Table { + private fun scienceVictoryColumn(): Table { val t = Table() t.defaults().pad(5f) t.add(getMilestone("Built Apollo Program", playerCivInfo.hasUnique("Enables construction of Spaceship parts"))).row() - val victoryManager= playerCivInfo.victoryManager + val victoryManager = playerCivInfo.victoryManager for (key in victoryManager.requiredSpaceshipParts.keys) for (i in 0 until victoryManager.requiredSpaceshipParts[key]!!) @@ -142,18 +142,18 @@ class VictoryScreen(val worldScreen: WorldScreen) : PickerScreen() { return t } - private fun culturalVictoryColumn():Table { - val t=Table() + private fun culturalVictoryColumn(): Table { + val t = Table() t.defaults().pad(5f) - for(branch in playerCivInfo.gameInfo.ruleSet.policyBranches.values) { + for (branch in playerCivInfo.gameInfo.ruleSet.policyBranches.values) { val finisher = branch.policies.last().name t.add(getMilestone(finisher, playerCivInfo.policies.isAdopted(finisher))).row() } return t } - private fun conquestVictoryColumn():Table { - val table=Table() + private fun conquestVictoryColumn(): Table { + val table = Table() table.defaults().pad(5f) for (civ in playerCivInfo.gameInfo.civilizations) { if (civ.isCurrentPlayer() || !civ.isMajorCiv()) continue @@ -165,9 +165,9 @@ class VictoryScreen(val worldScreen: WorldScreen) : PickerScreen() { return table } - fun getMilestone(text:String, achieved:Boolean): TextButton { + fun getMilestone(text: String, achieved: Boolean): TextButton { val textButton = text.toTextButton() - if(achieved) textButton.color = Color.GREEN + if (achieved) textButton.color = Color.GREEN else textButton.color = Color.GRAY return textButton } @@ -177,9 +177,9 @@ class VictoryScreen(val worldScreen: WorldScreen) : PickerScreen() { val majorCivs = game.gameInfo.civilizations.filter { it.isMajorCiv() } val globalVictoryTable = Table().apply { defaults().pad(10f) } - if(scientificVictoryEnabled) globalVictoryTable.add(getGlobalScientificVictoryColumn(majorCivs)) - if(culturalVictoryEnabled) globalVictoryTable.add(getGlobalCulturalVictoryColumn(majorCivs)) - if(dominationVictoryEnabled) globalVictoryTable.add(getGlobalDominationVictoryColumn(majorCivs)) + if (scientificVictoryEnabled) globalVictoryTable.add(getGlobalScientificVictoryColumn(majorCivs)) + if (culturalVictoryEnabled) globalVictoryTable.add(getGlobalCulturalVictoryColumn(majorCivs)) + if (dominationVictoryEnabled) globalVictoryTable.add(getGlobalDominationVictoryColumn(majorCivs)) contentsTable.clear() contentsTable.add(globalVictoryTable) @@ -212,7 +212,7 @@ class VictoryScreen(val worldScreen: WorldScreen) : PickerScreen() { .sortedByDescending { it.branchesCompleted } for (entry in civsToBranchesCompleted) { - val civToBranchesHaveCompleted= EmpireOverviewScreen.getCivGroup(entry.civ, " - " + entry.branchesCompleted, playerCivInfo) + val civToBranchesHaveCompleted = EmpireOverviewScreen.getCivGroup(entry.civ, " - " + entry.branchesCompleted, playerCivInfo) policyVictoryColumn.add(civToBranchesHaveCompleted).fillX().row() } return policyVictoryColumn @@ -231,7 +231,7 @@ class VictoryScreen(val worldScreen: WorldScreen) : PickerScreen() { } for (entry in civsToPartsRemaining) { - val civToPartsBeRemaining=(EmpireOverviewScreen.getCivGroup(entry.civ, " - " + entry.partsRemaining, playerCivInfo)) + val civToPartsBeRemaining = (EmpireOverviewScreen.getCivGroup(entry.civ, " - " + entry.partsRemaining, playerCivInfo)) scientificVictoryColumn.add(civToPartsBeRemaining).fillX().row() } return scientificVictoryColumn @@ -241,7 +241,7 @@ class VictoryScreen(val worldScreen: WorldScreen) : PickerScreen() { val majorCivs = game.gameInfo.civilizations.filter { it.isMajorCiv() } val civRankingsTable = Table().apply { defaults().pad(5f) } - for( category in RankingType.values()) { + for (category in RankingType.values()) { val column = Table().apply { defaults().pad(5f) } column.add(category.value.toLabel()).row() column.addSeparator() @@ -257,4 +257,4 @@ class VictoryScreen(val worldScreen: WorldScreen) : PickerScreen() { contentsTable.add(civRankingsTable) } -} +} \ No newline at end of file