From 7330daff48b7b603f26f10a7f3dcb286aecd586a Mon Sep 17 00:00:00 2001 From: Yair Morgenstern Date: Mon, 18 May 2020 23:08:19 +0300 Subject: [PATCH] All UI changes in threads are now run in a postRunnable - should hopefully get rid of IndexOutOfBoundsExceptions --- core/src/com/unciv/MainMenuScreen.kt | 1 - core/src/com/unciv/logic/battle/Battle.kt | 2 +- core/src/com/unciv/ui/MultiplayerScreen.kt | 14 ++++++++------ .../unciv/ui/mapeditor/MapDownloadPopup.kt | 2 +- .../com/unciv/ui/mapeditor/NewMapScreen.kt | 16 +++++++++------- .../unciv/ui/newgamescreen/NewGameScreen.kt | 12 +++++++----- core/src/com/unciv/ui/saves/SaveGameScreen.kt | 4 ++-- .../com/unciv/ui/worldscreen/WorldScreen.kt | 12 +++++++----- .../mainmenu/WorldScreenOptionsPopup.kt | 19 ++++++++++++------- .../ui/worldscreen/unit/UnitContextMenu.kt | 15 ++++++++------- 10 files changed, 55 insertions(+), 42 deletions(-) diff --git a/core/src/com/unciv/MainMenuScreen.kt b/core/src/com/unciv/MainMenuScreen.kt index 36c3f81b15..546659c532 100644 --- a/core/src/com/unciv/MainMenuScreen.kt +++ b/core/src/com/unciv/MainMenuScreen.kt @@ -65,7 +65,6 @@ class MainMenuScreen: CameraStageBaseScreen() { Actions.fadeIn(0.3f) )) - } } diff --git a/core/src/com/unciv/logic/battle/Battle.kt b/core/src/com/unciv/logic/battle/Battle.kt index d1ad59da8a..e27d6d05eb 100644 --- a/core/src/com/unciv/logic/battle/Battle.kt +++ b/core/src/com/unciv/logic/battle/Battle.kt @@ -29,7 +29,7 @@ object Battle { attacker.unit.useMovementPoints(1f) } } - attack(attacker,getMapCombatantOfTile(attackableTile.tileToAttack)!!) + attack(attacker, getMapCombatantOfTile(attackableTile.tileToAttack)!!) } fun attack(attacker: ICombatant, defender: ICombatant) { diff --git a/core/src/com/unciv/ui/MultiplayerScreen.kt b/core/src/com/unciv/ui/MultiplayerScreen.kt index 7c11c4dbb8..8764902b88 100644 --- a/core/src/com/unciv/ui/MultiplayerScreen.kt +++ b/core/src/com/unciv/ui/MultiplayerScreen.kt @@ -143,13 +143,15 @@ class MultiplayerScreen(previousScreen: CameraStageBaseScreen) : PickerScreen() else GameSaver.saveGame(game, gameName, true) - reloadGameListUI() + Gdx.app.postRunnable { reloadGameListUI() } } catch (ex: Exception) { - val errorPopup = Popup(this) - errorPopup.addGoodSizedLabel("Could not download game!".tr()) - errorPopup.row() - errorPopup.addCloseButton() - errorPopup.open() + Gdx.app.postRunnable { + val errorPopup = Popup(this) + errorPopup.addGoodSizedLabel("Could not download game!".tr()) + errorPopup.row() + errorPopup.addCloseButton() + errorPopup.open() + } } addGameButton.setText(addGameText) addGameButton.enable() diff --git a/core/src/com/unciv/ui/mapeditor/MapDownloadPopup.kt b/core/src/com/unciv/ui/mapeditor/MapDownloadPopup.kt index d5342a2cf5..83d94e2a8a 100644 --- a/core/src/com/unciv/ui/mapeditor/MapDownloadPopup.kt +++ b/core/src/com/unciv/ui/mapeditor/MapDownloadPopup.kt @@ -67,7 +67,7 @@ class MapDownloadPopup(loadMapScreen: LoadMapScreen): Popup(loadMapScreen) { open() } } catch (ex: Exception) { - addGoodSizedLabel("Could not get list of maps!").row() + Gdx.app.postRunnable { addGoodSizedLabel("Could not get list of maps!").row() } } } diff --git a/core/src/com/unciv/ui/mapeditor/NewMapScreen.kt b/core/src/com/unciv/ui/mapeditor/NewMapScreen.kt index 9a889a7b54..aaee070bf2 100644 --- a/core/src/com/unciv/ui/mapeditor/NewMapScreen.kt +++ b/core/src/com/unciv/ui/mapeditor/NewMapScreen.kt @@ -54,13 +54,15 @@ class NewMapScreen : PickerScreen() { } } catch (exception: Exception) { - rightButtonSetEnabled(true) - val cantMakeThatMapPopup = Popup(this) - cantMakeThatMapPopup.addGoodSizedLabel("It looks like we can't make a map with the parameters you requested!".tr()) - .row() - cantMakeThatMapPopup.addCloseButton() - cantMakeThatMapPopup.open() - Gdx.input.inputProcessor = stage + Gdx.app.postRunnable { + rightButtonSetEnabled(true) + val cantMakeThatMapPopup = Popup(this) + cantMakeThatMapPopup.addGoodSizedLabel("It looks like we can't make a map with the parameters you requested!".tr()) + .row() + cantMakeThatMapPopup.addCloseButton() + cantMakeThatMapPopup.open() + Gdx.input.inputProcessor = stage + } } } diff --git a/core/src/com/unciv/ui/newgamescreen/NewGameScreen.kt b/core/src/com/unciv/ui/newgamescreen/NewGameScreen.kt index 3bbcef4e4f..6f114f9745 100644 --- a/core/src/com/unciv/ui/newgamescreen/NewGameScreen.kt +++ b/core/src/com/unciv/ui/newgamescreen/NewGameScreen.kt @@ -98,12 +98,14 @@ class NewGameScreen(previousScreen:CameraStageBaseScreen, _gameSetupInfo: GameSe //Save gameId to clipboard because you have to do it anyway. Gdx.app.clipboard.contents = newGame!!.gameId //Popup to notify the User that the gameID got copied to the clipboard - ResponsePopup("gameID copied to clipboard".tr(), UncivGame.Current.worldScreen, 2500) + Gdx.app.postRunnable { ResponsePopup("gameID copied to clipboard".tr(), UncivGame.Current.worldScreen, 2500) } } catch (ex: Exception) { - val cantUploadNewGamePopup = Popup(this) - cantUploadNewGamePopup.addGoodSizedLabel("Could not upload game!") - cantUploadNewGamePopup.addCloseButton() - cantUploadNewGamePopup.open() + Gdx.app.postRunnable { + val cantUploadNewGamePopup = Popup(this) + cantUploadNewGamePopup.addGoodSizedLabel("Could not upload game!") + cantUploadNewGamePopup.addCloseButton() + cantUploadNewGamePopup.open() + } newGame = null } } diff --git a/core/src/com/unciv/ui/saves/SaveGameScreen.kt b/core/src/com/unciv/ui/saves/SaveGameScreen.kt index ffedeff19c..fe59599f53 100644 --- a/core/src/com/unciv/ui/saves/SaveGameScreen.kt +++ b/core/src/com/unciv/ui/saves/SaveGameScreen.kt @@ -55,9 +55,9 @@ class SaveGameScreen : PickerScreen() { rightSideButton.setText("Save game".tr()) rightSideButton.onClick { rightSideButton.setText("Saving...".tr()) - thread(name="SaveGame"){ + thread(name="SaveGame") { GameSaver.saveGame(UncivGame.Current.gameInfo, textField.text) - UncivGame.Current.setWorldScreen() + Gdx.app.postRunnable { UncivGame.Current.setWorldScreen() } } } rightSideButton.enable() diff --git a/core/src/com/unciv/ui/worldscreen/WorldScreen.kt b/core/src/com/unciv/ui/worldscreen/WorldScreen.kt index 657d52a3f5..7f709da1bd 100644 --- a/core/src/com/unciv/ui/worldscreen/WorldScreen.kt +++ b/core/src/com/unciv/ui/worldscreen/WorldScreen.kt @@ -461,17 +461,19 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() { try { OnlineMultiplayer().tryUploadGame(gameInfoClone) } catch (ex: Exception) { - val cantUploadNewGamePopup = Popup(this) - cantUploadNewGamePopup.addGoodSizedLabel("Could not upload game!").row() - cantUploadNewGamePopup.addCloseButton() - cantUploadNewGamePopup.open() + Gdx.app.postRunnable { // Since we're changing the UI, that should be done on the main thread + val cantUploadNewGamePopup = Popup(this) + cantUploadNewGamePopup.addGoodSizedLabel("Could not upload game!").row() + cantUploadNewGamePopup.addCloseButton() + cantUploadNewGamePopup.open() + } isPlayersTurn = true // Since we couldn't push the new game clone, then it's like we never clicked the "next turn" button shouldUpdate = true return@thread } } } catch (ex: Exception) { - game.crashController.crashOccurred() + Gdx.app.postRunnable { game.crashController.crashOccurred() } throw ex } diff --git a/core/src/com/unciv/ui/worldscreen/mainmenu/WorldScreenOptionsPopup.kt b/core/src/com/unciv/ui/worldscreen/mainmenu/WorldScreenOptionsPopup.kt index ca8f601f7d..a8b76d94fb 100644 --- a/core/src/com/unciv/ui/worldscreen/mainmenu/WorldScreenOptionsPopup.kt +++ b/core/src/com/unciv/ui/worldscreen/mainmenu/WorldScreenOptionsPopup.kt @@ -220,19 +220,24 @@ class WorldScreenOptionsPopup(val worldScreen:WorldScreen) : Popup(worldScreen) innerTable.add(errorTable).colspan(2).row() downloadMusicButton.onClick { + downloadMusicButton.disable() + errorTable.clear() + errorTable.add("Downloading...".toLabel()) + // So the whole game doesn't get stuck while downloading the file thread(name = "Music") { try { - downloadMusicButton.disable() - errorTable.clear() - errorTable.add("Downloading...".toLabel()) val file = DropBox.downloadFile("/Music/thatched-villagers.mp3") musicLocation.write(file, false) - rebuildInnerTable() - worldScreen.game.startMusic() + Gdx.app.postRunnable { + rebuildInnerTable() + worldScreen.game.startMusic() + } } catch (ex: Exception) { - errorTable.clear() - errorTable.add("Could not download music!".toLabel(Color.RED)) + Gdx.app.postRunnable { + errorTable.clear() + errorTable.add("Could not download music!".toLabel(Color.RED)) + } } } } diff --git a/core/src/com/unciv/ui/worldscreen/unit/UnitContextMenu.kt b/core/src/com/unciv/ui/worldscreen/unit/UnitContextMenu.kt index 970bc307f9..2333fe6fe8 100644 --- a/core/src/com/unciv/ui/worldscreen/unit/UnitContextMenu.kt +++ b/core/src/com/unciv/ui/worldscreen/unit/UnitContextMenu.kt @@ -59,14 +59,16 @@ class UnitContextMenu(val tileMapHolder: WorldMapHolder, val selectedUnit: MapUn fun onMoveButtonClick() { // this can take a long time, because of the unit-to-tile calculation needed, so we put it in a different thread - thread(name="TileToMoveTo") { + thread(name = "TileToMoveTo") { // these are the heavy parts, finding where we want to go // Since this runs in a different thread, even if we check movement.canReach() // then it might change until we get to the getTileToMoveTo, so we just try/catch it - val tileToMoveTo:TileInfo - try{ + val tileToMoveTo: TileInfo + try { tileToMoveTo = selectedUnit.movement.getTileToMoveToThisTurn(targetTile) - }catch (ex:Exception){ return@thread } // can't move here + } catch (ex: Exception) { + return@thread + } // can't move here Gdx.app.postRunnable { try { @@ -76,7 +78,7 @@ class UnitContextMenu(val tileMapHolder: WorldMapHolder, val selectedUnit: MapUn // I can't think of any way to avoid this, // but it's so rare and edge-case-y that ignoring its failure is actually acceptable, hence the empty catch selectedUnit.movement.moveToTile(tileToMoveTo) - if(selectedUnit.action == Constants.unitActionExplore) selectedUnit.action = null // remove explore on manual move + if (selectedUnit.action == Constants.unitActionExplore) selectedUnit.action = null // remove explore on manual move Sounds.play(UncivSound.Whoosh) if (selectedUnit.currentTile != targetTile) selectedUnit.action = "moveTo " + targetTile.position.x.toInt() + "," + targetTile.position.y.toInt() @@ -86,8 +88,7 @@ class UnitContextMenu(val tileMapHolder: WorldMapHolder, val selectedUnit: MapUn tileMapHolder.worldScreen.shouldUpdate = true tileMapHolder.unitActionOverlay?.remove() - } catch (e: Exception) { - } + } catch (e: Exception) {} } }