From 07a43f3f1a095f80832db21c4379af365decbffe Mon Sep 17 00:00:00 2001 From: SomeTroglodyte <63000004+SomeTroglodyte@users.noreply.github.com> Date: Mon, 14 Jun 2021 13:44:43 +0200 Subject: [PATCH] Fix crash caused by cascaded ruins unit gifts (#4133) * Fix d1f6c5ac breaking builds * Fix d1f6c5ac breaking builds - patch1 * Fix silent crash when ancient ruins cascade gifted units --- .../jsons/translations/Czech.properties | 2 +- .../jsons/translations/Dutch.properties | 2 +- .../jsons/translations/German.properties | 2 +- .../jsons/translations/Indonesian.properties | 2 +- .../jsons/translations/Italian.properties | 2 +- .../jsons/translations/Japanese.properties | 2 +- .../jsons/translations/Polish.properties | 2 +- .../jsons/translations/Russian.properties | 2 +- .../Simplified_Chinese.properties | 2 +- .../jsons/translations/Spanish.properties | 2 +- .../jsons/translations/Swedish.properties | 2 +- .../Traditional_Chinese.properties | 2 +- .../logic/civilization/CivilizationInfo.kt | 5 +++ core/src/com/unciv/logic/map/MapUnit.kt | 44 ++++++++++++------- core/src/com/unciv/logic/map/TileMap.kt | 4 +- .../translations/TranslationFileWriter.kt | 5 --- .../unciv/ui/worldscreen/WorldMapHolder.kt | 6 ++- 17 files changed, 52 insertions(+), 36 deletions(-) diff --git a/android/assets/jsons/translations/Czech.properties b/android/assets/jsons/translations/Czech.properties index c7fc4a9377..7073a10523 100644 --- a/android/assets/jsons/translations/Czech.properties +++ b/android/assets/jsons/translations/Czech.properties @@ -2882,7 +2882,7 @@ Professional Army = Profesionální armáda Gold cost of upgrading [unitType] units reduced by [amount]% = Honor Complete = Kompletní Čest Honor = Čest -+[amount]% Strength vs [param] = +[amount]% síly proti [unitType] ++[amount]% Strength vs [param] = +[amount]% síly proti [param] Notified of new Barbarian encampments = Upozornění na nový Barbarský tábor Organized Religion = Organizovaná víra diff --git a/android/assets/jsons/translations/Dutch.properties b/android/assets/jsons/translations/Dutch.properties index c056edb23b..ee4e19a958 100644 --- a/android/assets/jsons/translations/Dutch.properties +++ b/android/assets/jsons/translations/Dutch.properties @@ -4101,7 +4101,7 @@ Gold cost of upgrading [unitType] units reduced by [amount]% = # Requires translation! Honor Complete = Honor = Eer -+[amount]% Strength vs [param] = +[amount]% Kracht vs [unitType] ++[amount]% Strength vs [param] = +[amount]% Kracht vs [param] # Requires translation! Notified of new Barbarian encampments = diff --git a/android/assets/jsons/translations/German.properties b/android/assets/jsons/translations/German.properties index 88dfa06c63..8bff7eaa0a 100644 --- a/android/assets/jsons/translations/German.properties +++ b/android/assets/jsons/translations/German.properties @@ -2859,7 +2859,7 @@ Professional Army = Berufsarmee Gold cost of upgrading [unitType] units reduced by [amount]% = Honor Complete = Ehre vollständig Honor = Ehre -+[amount]% Strength vs [param] = +[amount]% Stärke gegen [unitType] ++[amount]% Strength vs [param] = +[amount]% Stärke gegen [param] Notified of new Barbarian encampments = Benachrichtigungen über neue Barbarenlager Organized Religion = Organisierte Religion diff --git a/android/assets/jsons/translations/Indonesian.properties b/android/assets/jsons/translations/Indonesian.properties index f77c9cdd51..5a457bf6b2 100644 --- a/android/assets/jsons/translations/Indonesian.properties +++ b/android/assets/jsons/translations/Indonesian.properties @@ -2885,7 +2885,7 @@ Professional Army = Prajurit Profesional Gold cost of upgrading [unitType] units reduced by [amount]% = Honor Complete = Kehormatan Lengkap Honor = Kehormatan -+[amount]% Strength vs [param] = +[amount]% Kekuatan vs [unitType] ++[amount]% Strength vs [param] = +[amount]% Kekuatan vs [param] Notified of new Barbarian encampments = Diberi tahu ketika muncul perkemahan orang Barbar baru Organized Religion = Agama Terorganisasi diff --git a/android/assets/jsons/translations/Italian.properties b/android/assets/jsons/translations/Italian.properties index 47ffd8f8df..8ded259ef4 100644 --- a/android/assets/jsons/translations/Italian.properties +++ b/android/assets/jsons/translations/Italian.properties @@ -2859,7 +2859,7 @@ Professional Army = Esercito professionale Gold cost of upgrading [unitType] units reduced by [amount]% = Honor Complete = Onore Completo Honor = Onore -+[amount]% Strength vs [param] = +[amount]% Strength contro [unitType] ++[amount]% Strength vs [param] = +[amount]% Strength contro [param] Notified of new Barbarian encampments = Sarai notificato dei nuovi accampamenti barbari Organized Religion = Religione Organizzata diff --git a/android/assets/jsons/translations/Japanese.properties b/android/assets/jsons/translations/Japanese.properties index abb781ea26..0a5d397315 100644 --- a/android/assets/jsons/translations/Japanese.properties +++ b/android/assets/jsons/translations/Japanese.properties @@ -2914,7 +2914,7 @@ Professional Army = 軍隊の常備 Gold cost of upgrading [unitType] units reduced by [amount]% = Honor Complete = 名誉コンプリート Honor = 名誉 -+[amount]% Strength vs [param] = [unitType]に対して戦闘力+[amount]% ++[amount]% Strength vs [param] = [param]に対して戦闘力+[amount]% Notified of new Barbarian encampments = 新たな蛮族の野営地が出現すると通知 Organized Religion = 宗教の組織化 diff --git a/android/assets/jsons/translations/Polish.properties b/android/assets/jsons/translations/Polish.properties index e2b9988eaf..4f3d3e357e 100644 --- a/android/assets/jsons/translations/Polish.properties +++ b/android/assets/jsons/translations/Polish.properties @@ -2954,7 +2954,7 @@ Professional Army = Armia Zawodowa Gold cost of upgrading [unitType] units reduced by [amount]% = Honor Complete = Ukończony Honor Honor = Honor -+[amount]% Strength vs [param] = +[amount]% Siły w wlace z [unitType] ++[amount]% Strength vs [param] = +[amount]% Siły w wlace z [param] Notified of new Barbarian encampments = Powiadomiono o nowych obozach Barbarzyńców Organized Religion = Hierarchia Kościelna diff --git a/android/assets/jsons/translations/Russian.properties b/android/assets/jsons/translations/Russian.properties index 3671e3a99e..a472c2f62e 100644 --- a/android/assets/jsons/translations/Russian.properties +++ b/android/assets/jsons/translations/Russian.properties @@ -2902,7 +2902,7 @@ Professional Army = Профессиональная армия Gold cost of upgrading [unitType] units reduced by [amount]% = Honor Complete = Честь завершена Honor = Честь -+[amount]% Strength vs [param] = +[amount]% Силы против [unitType] ++[amount]% Strength vs [param] = +[amount]% Силы против [param] Notified of new Barbarian encampments = Вы будете получать извещение всякий раз, когда варвары будут ставить новый лагерь Organized Religion = Организованная религия diff --git a/android/assets/jsons/translations/Simplified_Chinese.properties b/android/assets/jsons/translations/Simplified_Chinese.properties index 16234af6b5..89f1e81465 100644 --- a/android/assets/jsons/translations/Simplified_Chinese.properties +++ b/android/assets/jsons/translations/Simplified_Chinese.properties @@ -2897,7 +2897,7 @@ Professional Army = 职业军队 Gold cost of upgrading [unitType] units reduced by [amount]% = Honor Complete = 完整的荣誉政策 Honor = 荣誉政策 -+[amount]% Strength vs [param] = 对战[unitType]时+[amount]%战斗力 ++[amount]% Strength vs [param] = 对战[param]时+[amount]%战斗力 Notified of new Barbarian encampments = 新的蛮族营地出现时将会通知 Organized Religion = 教会组织 diff --git a/android/assets/jsons/translations/Spanish.properties b/android/assets/jsons/translations/Spanish.properties index c22968281d..c257febb5c 100644 --- a/android/assets/jsons/translations/Spanish.properties +++ b/android/assets/jsons/translations/Spanish.properties @@ -2859,7 +2859,7 @@ Professional Army = Ejercito Profesional Gold cost of upgrading [unitType] units reduced by [amount]% = Honor Complete = Honor Completado Honor = Honor -+[amount]% Strength vs [param] = +[amount]% de Fuerza vs [unitType] ++[amount]% Strength vs [param] = +[amount]% de Fuerza vs [param] Notified of new Barbarian encampments = Notificado de nuevos campamentos Bárbaros Organized Religion = Religión Organizada diff --git a/android/assets/jsons/translations/Swedish.properties b/android/assets/jsons/translations/Swedish.properties index 32fa879500..ae8463b398 100644 --- a/android/assets/jsons/translations/Swedish.properties +++ b/android/assets/jsons/translations/Swedish.properties @@ -2885,7 +2885,7 @@ Professional Army = Professionell Armé Gold cost of upgrading [unitType] units reduced by [amount]% = Honor Complete = Heder Fullbordat Honor = Heder -+[amount]% Strength vs [param] = +[amount]% Styrka mot [unitType] ++[amount]% Strength vs [param] = +[amount]% Styrka mot [param] Notified of new Barbarian encampments = Uppmärksammas på nya Barbarläger Organized Religion = Organiserad Religion diff --git a/android/assets/jsons/translations/Traditional_Chinese.properties b/android/assets/jsons/translations/Traditional_Chinese.properties index 3b25eebcb6..c402fa8069 100644 --- a/android/assets/jsons/translations/Traditional_Chinese.properties +++ b/android/assets/jsons/translations/Traditional_Chinese.properties @@ -2917,7 +2917,7 @@ Professional Army = 職業軍隊 Gold cost of upgrading [unitType] units reduced by [amount]% = Honor Complete = 完整的榮譽政策 Honor = 榮譽政策 -+[amount]% Strength vs [param] = 對戰[unitType]時+[amount]%戰鬥力 ++[amount]% Strength vs [param] = 對戰[param]時+[amount]%戰鬥力 Notified of new Barbarian encampments = 新的蠻族營地出現時將會通知 Organized Religion = 教會組織 diff --git a/core/src/com/unciv/logic/civilization/CivilizationInfo.kt b/core/src/com/unciv/logic/civilization/CivilizationInfo.kt index be791c179d..1294d30256 100644 --- a/core/src/com/unciv/logic/civilization/CivilizationInfo.kt +++ b/core/src/com/unciv/logic/civilization/CivilizationInfo.kt @@ -607,6 +607,11 @@ class CivilizationInfo { } } + /** Tries to place the a [unitName] unit into the [TileInfo] closest to the given the [position] + * @param location where to try to place the unit + * @param unitName name of the [BaseUnit] to create and place + * @return created [MapUnit] or null if no suitable location was found + * */ fun placeUnitNearTile(location: Vector2, unitName: String): MapUnit? { return gameInfo.tileMap.placeUnitNearTile(location, unitName, this) } diff --git a/core/src/com/unciv/logic/map/MapUnit.kt b/core/src/com/unciv/logic/map/MapUnit.kt index fe76008ba3..d336177863 100644 --- a/core/src/com/unciv/logic/map/MapUnit.kt +++ b/core/src/com/unciv/logic/map/MapUnit.kt @@ -596,14 +596,15 @@ class MapUnit { fun removeFromTile() = currentTile.removeUnit(this) fun moveThroughTile(tile: TileInfo) { + // addPromotion requires currentTile to be valid because it accesses ruleset through it + // getAncientRuinBonus, if it places a new unit, does too + currentTile = tile + if (tile.improvement == Constants.ancientRuins && civInfo.isMajorCiv()) getAncientRuinBonus(tile) if (tile.improvement == Constants.barbarianEncampment && !civInfo.isBarbarian()) clearEncampment(tile) - // addPromotion requires currentTile to be valid because it accesses ruleset through it - currentTile = tile - if (!hasUnique("All healing effects doubled") && type.isLandUnit() && type.isMilitary()) { val gainDoubleHealPromotion = tile.neighbors .any { it.hasUnique("Grants Rejuvenation (all healing effects doubled) to adjacent military land units for the rest of the game") } @@ -676,6 +677,17 @@ class MapUnit { tile.improvement = null val tileBasedRandom = Random(tile.position.toString().hashCode()) val actions: ArrayList<() -> Unit> = ArrayList() + + fun goldBonus() { + val amount = listOf(25, 60, 100).random(tileBasedRandom) + civInfo.addGold(amount) + civInfo.addNotification( + "We have found a stash of [$amount] gold in the ruins!", + tile.position, + NotificationIcon.Gold + ) + } + if (civInfo.cities.isNotEmpty()) actions.add { val city = civInfo.cities.random(tileBasedRandom) city.population.population++ @@ -687,6 +699,7 @@ class MapUnit { NotificationIcon.Growth ) } + val researchableAncientEraTechs = tile.tileMap.gameInfo.ruleSet.technologies.values .filter { !civInfo.tech.isResearched(it.name) @@ -705,14 +718,19 @@ class MapUnit { ) } - - val possibleUnits = listOf(Constants.settler, Constants.worker, "Warrior") - .filter { civInfo.gameInfo.ruleSet.units.containsKey(it) } + val possibleUnits = ( + //City-States and OCC don't get settler from ruins + listOf(Constants.settler).filterNot { civInfo.isCityState() || civInfo.isOneCityChallenger() } + + listOf(Constants.worker, "Warrior") + ).filter { civInfo.gameInfo.ruleSet.units.containsKey(it) } if (possibleUnits.isNotEmpty()) actions.add { val chosenUnit = possibleUnits.random(tileBasedRandom) - if (!(civInfo.isCityState() || civInfo.isOneCityChallenger()) || chosenUnit != Constants.settler) { //City-States and OCC don't get settler from ruins - civInfo.placeUnitNearTile(tile.position, chosenUnit) + // placeUnitNearTile _can_ fail, and since this code can run behind a try with empty + // catch inside nested thread switches - petter play it safe + if (civInfo.placeUnitNearTile(tile.position, chosenUnit) == null) { + goldBonus() + } else { civInfo.addNotification( "A [$chosenUnit] has joined us!", tile.position, @@ -731,15 +749,7 @@ class MapUnit { ) } - actions.add { - val amount = listOf(25, 60, 100).random(tileBasedRandom) - civInfo.addGold(amount) - civInfo.addNotification( - "We have found a stash of [$amount] gold in the ruins!", - tile.position, - NotificationIcon.Gold - ) - } + actions.add { goldBonus() } actions.add { civInfo.policies.addCulture(20) diff --git a/core/src/com/unciv/logic/map/TileMap.kt b/core/src/com/unciv/logic/map/TileMap.kt index 14bb70ecca..a5202d93fd 100644 --- a/core/src/com/unciv/logic/map/TileMap.kt +++ b/core/src/com/unciv/logic/map/TileMap.kt @@ -157,7 +157,9 @@ class TileMap { } - /** Tries to place the [unitName] into the [TileInfo] closest to the given the [position] + /** Tries to place the [unitName] into the [TileInfo] closest to the given [position] + * @param position where to try to place the unit (or close - max 10 tiles distance) + * @param unitName name of the [BaseUnit] to create and place * @param civInfo civilization to assign unit to * @return created [MapUnit] or null if no suitable location was found * */ diff --git a/core/src/com/unciv/models/translations/TranslationFileWriter.kt b/core/src/com/unciv/models/translations/TranslationFileWriter.kt index b2dcddfec6..90d7f028a9 100644 --- a/core/src/com/unciv/models/translations/TranslationFileWriter.kt +++ b/core/src/com/unciv/models/translations/TranslationFileWriter.kt @@ -4,7 +4,6 @@ import com.badlogic.gdx.Gdx import com.badlogic.gdx.files.FileHandle import com.badlogic.gdx.utils.Array import com.unciv.JsonParser -import com.unciv.logic.battle.BattleDamage import com.unciv.models.metadata.BaseRuleset import com.unciv.models.ruleset.* import com.unciv.models.ruleset.tech.TechColumn @@ -228,10 +227,6 @@ object TranslationFileWriter { stringToTranslate = stringToTranslate.replace(parameter, parameterName) } - } else { - // substitute the regex for "Bonus/Penalty vs ..." - val match = Regex(BattleDamage.BONUS_VS_UNIT_TYPE).matchEntire(string) - if (match != null) stringToTranslate = "${match.groupValues[1]} vs [unitType]" } resultStrings!!.add("$stringToTranslate = ") return diff --git a/core/src/com/unciv/ui/worldscreen/WorldMapHolder.kt b/core/src/com/unciv/ui/worldscreen/WorldMapHolder.kt index 0dcf759102..8a947b6591 100644 --- a/core/src/com/unciv/ui/worldscreen/WorldMapHolder.kt +++ b/core/src/com/unciv/ui/worldscreen/WorldMapHolder.kt @@ -202,6 +202,8 @@ class WorldMapHolder(internal val worldScreen: WorldScreen, internal val tileMap try { tileToMoveTo = selectedUnit.movement.getTileToMoveToThisTurn(targetTile) } catch (ex: Exception) { + println("Exception in getTileToMoveToThisTurn: ${ex.message}") + ex.printStackTrace() return@thread } // can't move here @@ -224,7 +226,9 @@ class WorldMapHolder(internal val worldScreen: WorldScreen, internal val tileMap if (selectedUnits.size > 1) { // We have more tiles to move moveUnitToTargetTile(selectedUnits.subList(1, selectedUnits.size), targetTile) } else removeUnitActionOverlay() //we're done here - } catch (e: Exception) { + } catch (ex: Exception) { + println("Exception in moveUnitToTargetTile: ${ex.message}") + ex.printStackTrace() } } }