Fix 'new game' error message thread handling

This commit is contained in:
yairm210
2024-11-19 09:32:06 +02:00
parent b4f9c95caf
commit c5a8753cf7

View File

@ -113,125 +113,108 @@ class NewGameScreen(
private fun startGameAvoidANRs(){
// Don't allow players to click the game while we're checking if it's ok
Gdx.input.inputProcessor = null
Concurrency.run { // even just *checking* can take time
val success = startGame()
// if it is successful, the player should wait for the new screen, not touch the old one
if (!success) Gdx.input.inputProcessor = stage
mapOptionsTable.cancelBackgroundJobs()
Concurrency.run { // even just *checking* can take time
val errorMessage = getErrorMessage()
if (errorMessage != null){
Concurrency.runOnGLThread {
val errorPopup = Popup(this@NewGameScreen)
errorPopup.addGoodSizedLabel(errorMessage).row()
errorPopup.addCloseButton()
errorPopup.open()
Gdx.input.inputProcessor = stage
}
return@run
}
// Requires a custom popup so can't be folded into getErrorMessage
val modCheckResult = newGameOptionsTable.modCheckboxes.savedModcheckResult
newGameOptionsTable.modCheckboxes.savedModcheckResult = null
if (modCheckResult != null) {
Concurrency.runOnGLThread {
AcceptModErrorsPopup(
this@NewGameScreen, modCheckResult,
restoreDefault = { newGameOptionsTable.resetRuleset() },
action = {
gameSetupInfo.gameParameters.acceptedModCheckErrors = modCheckResult
startGameAvoidANRs()
}
)
Gdx.input.inputProcessor = stage
}
return@run
}
startGame()
}
}
private fun startGame(): Boolean {
mapOptionsTable.cancelBackgroundJobs()
// Should be run NOT on main thread because it contacts MP server and loads maps etc
fun getErrorMessage(): String? {
if (gameSetupInfo.gameParameters.isOnlineMultiplayer) {
if (!checkConnectionToMultiplayerServer()) {
val noInternetConnectionPopup = Popup(this)
val label = if (Multiplayer.usesCustomServer()) "Couldn't connect to Multiplayer Server!" else "Couldn't connect to Dropbox!"
noInternetConnectionPopup.addGoodSizedLabel(label.tr()).row()
noInternetConnectionPopup.addCloseButton()
noInternetConnectionPopup.open()
return false
}
if (!checkConnectionToMultiplayerServer())
return if (Multiplayer.usesCustomServer()) "Couldn't connect to Multiplayer Server!"
else "Couldn't connect to Dropbox!"
for (player in gameSetupInfo.gameParameters.players.filter { it.playerType == PlayerType.Human }) {
try {
UUID.fromString(IdChecker.checkAndReturnPlayerUuid(player.playerId))
} catch (_: Exception) {
val invalidPlayerIdPopup = Popup(this)
invalidPlayerIdPopup.addGoodSizedLabel("Invalid player ID!".tr()).row()
invalidPlayerIdPopup.addCloseButton()
invalidPlayerIdPopup.open()
return false
return "Invalid player ID!"
}
}
if (!gameSetupInfo.gameParameters.anyoneCanSpectate) {
if (gameSetupInfo.gameParameters.players.none { it.playerId == UncivGame.Current.settings.multiplayer.userId }) {
val notAllowedToSpectate = Popup(this)
notAllowedToSpectate.addGoodSizedLabel("You are not allowed to spectate!".tr()).row()
notAllowedToSpectate.addCloseButton()
notAllowedToSpectate.open()
return false
}
if (gameSetupInfo.gameParameters.players.none { it.playerId == UncivGame.Current.settings.multiplayer.userId })
return "You are not allowed to spectate!"
}
}
if (gameSetupInfo.gameParameters.players.none {
it.playerType == PlayerType.Human &&
// do not allow multiplayer with only spectator(s) and AI(s) - non-MP that works
!(it.chosenCiv == Constants.spectator && gameSetupInfo.gameParameters.isOnlineMultiplayer)
}) {
val noHumanPlayersPopup = Popup(this)
noHumanPlayersPopup.addGoodSizedLabel("No human players selected!".tr()).row()
noHumanPlayersPopup.addCloseButton()
noHumanPlayersPopup.open()
return false
}
if (gameSetupInfo.gameParameters.victoryTypes.isEmpty()) {
val noVictoryTypesPopup = Popup(this)
noVictoryTypesPopup.addGoodSizedLabel("No victory conditions were selected!".tr()).row()
noVictoryTypesPopup.addCloseButton()
noVictoryTypesPopup.open()
return false
}
val modCheckResult = newGameOptionsTable.modCheckboxes.savedModcheckResult
newGameOptionsTable.modCheckboxes.savedModcheckResult = null
if (modCheckResult != null) {
AcceptModErrorsPopup(
this, modCheckResult,
restoreDefault = { newGameOptionsTable.resetRuleset() },
action = {
gameSetupInfo.gameParameters.acceptedModCheckErrors = modCheckResult
startGameAvoidANRs()
}
)
return false
}
it.playerType == PlayerType.Human &&
// do not allow multiplayer with only spectator(s) and AI(s) - non-MP that works
!(it.chosenCiv == Constants.spectator && gameSetupInfo.gameParameters.isOnlineMultiplayer)
}) return "No human players selected!"
if (gameSetupInfo.gameParameters.victoryTypes.isEmpty()) return "No victory conditions were selected!"
if (mapOptionsTable.mapTypeSelectBox.selected.value == MapGeneratedMainType.custom) {
val map = try {
MapSaver.loadMap(gameSetupInfo.mapFile!!)
} catch (ex: Throwable) {
Log.error("Could not load map", ex)
ToastPopup("Could not load map!", this)
return false
return "Could not load map"
}
val rulesetIncompatibilities = map.getRulesetIncompatibility(ruleset)
if (rulesetIncompatibilities.isNotEmpty()) {
val incompatibleMap = Popup(this)
incompatibleMap.addGoodSizedLabel("Map is incompatible with the chosen ruleset!".tr()).row()
for(incompatibility in rulesetIncompatibilities)
incompatibleMap.addGoodSizedLabel(incompatibility).row()
incompatibleMap.addCloseButton()
incompatibleMap.open()
return false
}
if (rulesetIncompatibilities.isNotEmpty())
return "Map is incompatible with the chosen ruleset!".tr() + "\n" + rulesetIncompatibilities.joinToString("\n"){it.tr()}
} else {
// Generated map - check for sensible dimensions and if exceeded correct them and notify user
val mapSize = gameSetupInfo.mapParameters.mapSize
val message = mapSize.fixUndesiredSizes(gameSetupInfo.mapParameters.worldWrap)
if (message != null) {
ToastPopup( message, UncivGame.Current.screen!!, 4000 )
with (mapOptionsTable.generatedMapOptionsTable) {
customMapSizeRadius.text = mapSize.radius.tr()
customMapWidth.text = mapSize.width.tr()
customMapHeight.text = mapSize.height.tr()
}
return false
return message
}
}
return null
}
private fun startGame() {
rightSideButton.disable()
rightSideButton.setText(Constants.working.tr())
setSkin()
// Creating a new game can take a while and we don't want ANRs
Concurrency.runOnNonDaemonThreadPool("NewGame") {
startNewGame()
Concurrency.runOnGLThread {
rightSideButton.disable()
rightSideButton.setText(Constants.working.tr())
setSkin()
// Creating a new game can take a while and we don't want ANRs
Concurrency.runOnNonDaemonThreadPool("NewGame") {
startNewGame()
}
}
return true
}
/** Subtables may need an upper limit to their width - they can ask this function. */