From dde3732383a00a8b11268b836b2f4c181b40c96a Mon Sep 17 00:00:00 2001 From: Yair Morgenstern Date: Thu, 11 May 2023 16:51:29 +0300 Subject: [PATCH] Convert 'camps' vectorhashmap to 'encampments' arraylist (#9374) --- .../com/unciv/logic/BackwardCompatibility.kt | 17 ++----- core/src/com/unciv/logic/GameInfo.kt | 6 +-- .../civilization/BarbarianAutomation.kt | 2 +- .../civilization/BarbarianManager.kt | 49 +++++++++---------- 4 files changed, 33 insertions(+), 41 deletions(-) diff --git a/core/src/com/unciv/logic/BackwardCompatibility.kt b/core/src/com/unciv/logic/BackwardCompatibility.kt index 99191fbf14..b3c52ae97a 100644 --- a/core/src/com/unciv/logic/BackwardCompatibility.kt +++ b/core/src/com/unciv/logic/BackwardCompatibility.kt @@ -1,14 +1,13 @@ package com.unciv.logic import com.unciv.Constants -import com.unciv.logic.automation.civilization.BarbarianManager import com.unciv.logic.city.CityConstructions -import com.unciv.models.ruleset.PerpetualConstruction import com.unciv.logic.civilization.diplomacy.DiplomacyFlags import com.unciv.logic.civilization.diplomacy.DiplomacyManager import com.unciv.logic.civilization.managers.TechManager import com.unciv.logic.map.tile.RoadStatus import com.unciv.models.ruleset.ModOptions +import com.unciv.models.ruleset.PerpetualConstruction import com.unciv.models.ruleset.Ruleset /** @@ -161,7 +160,6 @@ object BackwardCompatibility { fun ModOptions.updateDeprecations() { } - /** Convert from Fortify X to Fortify and save off X */ fun GameInfo.convertFortify() { val reg = Regex("""^Fortify\s+(\d+)([\w\s]*)""") @@ -176,16 +174,11 @@ object BackwardCompatibility { } } - private fun isOldFormat(manager: BarbarianManager): Boolean { - val keys = manager.camps.keys as Set - val iterator = keys.iterator() - while (iterator.hasNext()) { - val key = iterator.next() - if (key is String) { - return true - } + fun GameInfo.convertEncampmentData(){ + if (barbarians.camps.isNotEmpty()){ + barbarians.encampments.addAll(barbarians.camps.values) + barbarians.camps.clear() } - return false } fun GameInfo.migrateToTileHistory() { diff --git a/core/src/com/unciv/logic/GameInfo.kt b/core/src/com/unciv/logic/GameInfo.kt index df9eda67c1..bf0f29218e 100644 --- a/core/src/com/unciv/logic/GameInfo.kt +++ b/core/src/com/unciv/logic/GameInfo.kt @@ -3,6 +3,7 @@ package com.unciv.logic import com.unciv.Constants import com.unciv.UncivGame import com.unciv.UncivGame.Version +import com.unciv.logic.BackwardCompatibility.convertEncampmentData import com.unciv.logic.BackwardCompatibility.convertFortify import com.unciv.logic.BackwardCompatibility.guaranteeUnitPromotions import com.unciv.logic.BackwardCompatibility.migrateToTileHistory @@ -35,9 +36,7 @@ import com.unciv.ui.audio.MusicMood import com.unciv.ui.audio.MusicTrackChooserFlags import com.unciv.utils.DebugUtils import com.unciv.utils.debug -import java.util.UUID -import kotlin.collections.ArrayList -import kotlin.collections.HashMap +import java.util.* /** @@ -611,6 +610,7 @@ class GameInfo : IsPartOfGameInfoSerialization, HasGameInfoSerializationVersion .flatMap { it.getResourceRequirementsPerTurn().keys }) spaceResources.addAll(ruleset.victories.values.flatMap { it.requiredSpaceshipParts }) + convertEncampmentData() barbarians.setTransients(this) cityDistances.game = this diff --git a/core/src/com/unciv/logic/automation/civilization/BarbarianAutomation.kt b/core/src/com/unciv/logic/automation/civilization/BarbarianAutomation.kt index 5545b798ec..0ba836a333 100644 --- a/core/src/com/unciv/logic/automation/civilization/BarbarianAutomation.kt +++ b/core/src/com/unciv/logic/automation/civilization/BarbarianAutomation.kt @@ -25,7 +25,7 @@ class BarbarianAutomation(val civInfo: Civilization) { // 1 - Stay on current encampment if (unit.currentTile.improvement == Constants.barbarianEncampment) return - val campTiles = unit.civ.gameInfo.barbarians.camps.map { unit.civ.gameInfo.tileMap[it.key] } + val campTiles = unit.civ.gameInfo.barbarians.encampments.map { unit.civ.gameInfo.tileMap[it.position] } .sortedBy { unit.currentTile.aerialDistanceTo(it) } val bestCamp = campTiles.firstOrNull { it.civilianUnit == null && unit.movement.canReach(it)} if (bestCamp != null) diff --git a/core/src/com/unciv/logic/automation/civilization/BarbarianManager.kt b/core/src/com/unciv/logic/automation/civilization/BarbarianManager.kt index 0de9a6aa13..0d974abbde 100644 --- a/core/src/com/unciv/logic/automation/civilization/BarbarianManager.kt +++ b/core/src/com/unciv/logic/automation/civilization/BarbarianManager.kt @@ -7,8 +7,8 @@ import com.unciv.logic.GameInfo import com.unciv.logic.IsPartOfGameInfoSerialization import com.unciv.logic.civilization.NotificationCategory import com.unciv.logic.civilization.NotificationIcon -import com.unciv.logic.map.tile.Tile import com.unciv.logic.map.TileMap +import com.unciv.logic.map.tile.Tile import com.unciv.models.ruleset.unique.UniqueType import com.unciv.ui.components.extensions.randomWeighted import java.util.* @@ -17,8 +17,12 @@ import kotlin.math.min import kotlin.math.pow class BarbarianManager : IsPartOfGameInfoSerialization { + /** Deprecated */ + @Deprecated("by 4.6.12 due to serialization containing exact class location - replaced by encampments") val camps = HashMapVector2() + val encampments = ArrayList() + @Transient lateinit var gameInfo: GameInfo @@ -27,8 +31,7 @@ class BarbarianManager : IsPartOfGameInfoSerialization { fun clone(): BarbarianManager { val toReturn = BarbarianManager() - for (camp in camps.values.map { it.clone() }) - toReturn.camps[camp.position] = camp + toReturn.encampments.addAll(encampments.map { it.clone() }) return toReturn } @@ -37,44 +40,40 @@ class BarbarianManager : IsPartOfGameInfoSerialization { this.tileMap = gameInfo.tileMap // Add any preexisting camps as Encampment objects + + val existingEncampmentLocations = encampments.asSequence().map { it.position }.toHashSet() + for (tile in tileMap.values) { if (tile.improvement == Constants.barbarianEncampment - && camps[tile.position] == null) { - val newCamp = Encampment(tile.position) - camps[newCamp.position] = newCamp + && !existingEncampmentLocations.contains(tile.position)) { + encampments.add(Encampment(tile.position)) } } - for (camp in camps.values) + for (camp in encampments) camp.gameInfo = gameInfo } fun updateEncampments() { // Check if camps were destroyed - val positionsToRemove = ArrayList() - for ((position, camp) in camps) { - if (tileMap[position].improvement != Constants.barbarianEncampment) { - camp.wasDestroyed() + for (encampment in encampments.toList()) { // tolist to avoid concurrent modification + if (tileMap[encampment.position].improvement != Constants.barbarianEncampment) { + encampment.wasDestroyed() } // Check if the ghosts are ready to depart - if (camp.destroyed && camp.countdown == 0) - positionsToRemove.add(position) + if (encampment.destroyed && encampment.countdown == 0) + encampments.remove(encampment) } - for (position in positionsToRemove) - camps.remove(position) // Possibly place a new encampment placeBarbarianEncampment() - // Update all existing camps - for (camp in camps.values) { - camp.update() - } + for (encampment in encampments) encampment.update() } /** Called when an encampment was attacked, will speed up time to next spawn */ fun campAttacked(position: Vector2) { - camps[position]?.wasAttacked() + encampments.firstOrNull { it.position == position }?.wasAttacked() } fun placeBarbarianEncampment() { @@ -90,7 +89,7 @@ class BarbarianManager : IsPartOfGameInfoSerialization { val fogTilesPerCamp = (tileMap.values.size.toFloat().pow(0.4f)).toInt() // Approximately // Check if we have more room - var campsToAdd = (fogTiles.size / fogTilesPerCamp) - camps.count { !it.value.destroyed } + var campsToAdd = (fogTiles.size / fogTilesPerCamp) - encampments.count { !it.destroyed } // First turn of the game add 1/3 of all possible camps if (gameInfo.turns == 1) { @@ -104,9 +103,9 @@ class BarbarianManager : IsPartOfGameInfoSerialization { // Camps can't spawn within 7 tiles of each other or within 4 tiles of major civ capitals val tooCloseToCapitals = gameInfo.civilizations.filterNot { it.isBarbarian() || it.isSpectator() || it.cities.isEmpty() || it.isCityState() || it.getCapital() == null } .flatMap { it.getCapital()!!.getCenterTile().getTilesInDistance(4) }.toSet() - val tooCloseToCamps = camps - .flatMap { tileMap[it.key].getTilesInDistance( - if (it.value.destroyed) 4 else 7 + val tooCloseToCamps = encampments + .flatMap { tileMap[it.position].getTilesInDistance( + if (it.destroyed) 4 else 7 ) }.toSet() val viableTiles = fogTiles.filter { @@ -138,7 +137,7 @@ class BarbarianManager : IsPartOfGameInfoSerialization { tile.changeImprovement(Constants.barbarianEncampment) val newCamp = Encampment(tile.position) newCamp.gameInfo = gameInfo - camps[newCamp.position] = newCamp + encampments.add(newCamp) notifyCivsOfBarbarianEncampment(tile) addedCamps++