mirror of
https://github.com/yairm210/Unciv.git
synced 2025-02-13 12:27:40 +07:00
Performance: Save civ tiles and neighbors in cache to update visible tiles faster
This commit is contained in:
parent
3db03a78d2
commit
f50b88c9a5
@ -551,8 +551,10 @@ class GameInfo : IsPartOfGameInfoSerialization, HasGameInfoSerializationVersion
|
||||
) {
|
||||
for (unit in civInfo.units.getCivUnits())
|
||||
unit.updateVisibleTiles(false) // this needs to be done after all the units are assigned to their civs and all other transients are set
|
||||
if(civInfo.playerType == PlayerType.Human)
|
||||
if (civInfo.playerType == PlayerType.Human)
|
||||
civInfo.exploredRegion.setMapParameters(tileMap.mapParameters) // Required for the correct calculation of the explored region on world wrap maps
|
||||
|
||||
civInfo.cache.updateOurTiles()
|
||||
civInfo.cache.updateSightAndResources() // only run ONCE and not for each unit - this is a huge performance saver!
|
||||
|
||||
// Since this depends on the cities of ALL civilizations,
|
||||
|
@ -17,6 +17,7 @@ import com.unciv.logic.map.tile.RoadStatus
|
||||
import com.unciv.logic.map.tile.Tile
|
||||
import com.unciv.models.ruleset.tile.Terrain
|
||||
import com.unciv.models.ruleset.tile.TileImprovement
|
||||
import com.unciv.models.ruleset.unique.LocalUniqueCache
|
||||
import com.unciv.models.ruleset.unique.UniqueType
|
||||
import com.unciv.ui.screens.worldscreen.unit.actions.UnitActions
|
||||
import com.unciv.utils.Log
|
||||
@ -370,9 +371,14 @@ class WorkerAutomation(
|
||||
}
|
||||
if (potentialTileImprovements.isEmpty()) return null
|
||||
|
||||
val cityUniqueCaches = HashMap<City, LocalUniqueCache>()
|
||||
fun getRankingWithImprovement(improvementName: String): Float {
|
||||
val improvement = ruleSet.tileImprovements[improvementName]!!
|
||||
val stats = tile.stats.getImprovementStats(improvement, civInfo, tile.getCity())
|
||||
val city = tile.getCity()
|
||||
val cache =
|
||||
if (city == null) LocalUniqueCache(false)
|
||||
else cityUniqueCaches.getOrPut(city) { LocalUniqueCache() }
|
||||
val stats = tile.stats.getImprovementStats(improvement, civInfo, tile.getCity(), cache)
|
||||
return Automation.rankStatsValue(stats, unit.civ)
|
||||
}
|
||||
|
||||
|
@ -147,7 +147,7 @@ class CityExpansionManager : IsPartOfGameInfoSerialization {
|
||||
|
||||
tile.setOwningCity(null)
|
||||
|
||||
city.civ.cache.updateCivResources()
|
||||
city.civ.cache.updateOurTiles()
|
||||
city.cityStats.update()
|
||||
|
||||
tile.history.recordRelinquishOwnership(tile)
|
||||
@ -169,14 +169,13 @@ class CityExpansionManager : IsPartOfGameInfoSerialization {
|
||||
city.tiles = city.tiles.withItem(tile.position)
|
||||
tile.setOwningCity(city)
|
||||
city.population.autoAssignPopulation()
|
||||
city.civ.cache.updateCivResources()
|
||||
city.civ.cache.updateOurTiles()
|
||||
city.cityStats.update()
|
||||
|
||||
for (unit in tile.getUnits().toList()) // toListed because we're modifying
|
||||
if (!unit.civ.diplomacyFunctions.canPassThroughTiles(city.civ))
|
||||
unit.movement.teleportToClosestMoveableTile()
|
||||
|
||||
city.civ.cache.updateViewableTiles()
|
||||
|
||||
tile.history.recordTakeOwnership(tile)
|
||||
}
|
||||
@ -187,7 +186,8 @@ class CityExpansionManager : IsPartOfGameInfoSerialization {
|
||||
val location = addNewTileWithCulture()
|
||||
if (location != null) {
|
||||
val locations = LocationAction(location, city.location)
|
||||
city.civ.addNotification("[" + city.name + "] has expanded its borders!", locations, NotificationCategory.Cities, NotificationIcon.Culture)
|
||||
city.civ.addNotification("[${city.name}] has expanded its borders!", locations,
|
||||
NotificationCategory.Cities, NotificationIcon.Culture)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -126,7 +126,6 @@ class CityInfoConquestFunctions(val city: City){
|
||||
}
|
||||
|
||||
}
|
||||
conqueringCiv.cache.updateViewableTiles() // Might see new tiles from this city
|
||||
}
|
||||
|
||||
|
||||
@ -266,18 +265,16 @@ class CityInfoConquestFunctions(val city: City){
|
||||
}
|
||||
|
||||
|
||||
fun moveToCiv(newCivInfo: Civilization) {
|
||||
fun moveToCiv(newCiv: Civilization) {
|
||||
val oldCiv = city.civ
|
||||
city.apply {
|
||||
val oldCiv = civ
|
||||
|
||||
|
||||
// Remove/relocate palace for old Civ - need to do this BEFORE we move the cities between
|
||||
// civs so the capitalCityIndicator recognizes the unique buildings of the conquered civ
|
||||
if (oldCiv.getCapital() == this) oldCiv.moveCapitalToNextLargest()
|
||||
|
||||
oldCiv.cities = oldCiv.cities.toMutableList().apply { remove(city) }
|
||||
newCivInfo.cities = newCivInfo.cities.toMutableList().apply { add(city) }
|
||||
civ = newCivInfo
|
||||
newCiv.cities = newCiv.cities.toMutableList().apply { add(city) }
|
||||
civ = newCiv
|
||||
hasJustBeenConquered = false
|
||||
turnAcquired = civ.gameInfo.turns
|
||||
previousOwner = oldCiv.civName
|
||||
@ -297,8 +294,8 @@ class CityInfoConquestFunctions(val city: City){
|
||||
// Place palace for newCiv if this is the only city they have
|
||||
// This needs to happen _before_ free buildings are added, as sometimes these should
|
||||
// only be placed in the capital, and then there needs to be a capital.
|
||||
if (newCivInfo.cities.size == 1) {
|
||||
newCivInfo.moveCapitalTo(this)
|
||||
if (newCiv.cities.size == 1) {
|
||||
newCiv.moveCapitalTo(this)
|
||||
}
|
||||
|
||||
// Add our free buildings to this city and add free buildings provided by the city to other cities
|
||||
@ -308,7 +305,7 @@ class CityInfoConquestFunctions(val city: City){
|
||||
|
||||
// Transfer unique buildings
|
||||
for (building in cityConstructions.getBuiltBuildings()) {
|
||||
val civEquivalentBuilding = newCivInfo.getEquivalentBuilding(building.name)
|
||||
val civEquivalentBuilding = newCiv.getEquivalentBuilding(building.name)
|
||||
if (building != civEquivalentBuilding) {
|
||||
cityConstructions.removeBuilding(building.name)
|
||||
cityConstructions.addBuilding(civEquivalentBuilding.name)
|
||||
@ -329,6 +326,8 @@ class CityInfoConquestFunctions(val city: City){
|
||||
tile.history.recordTakeOwnership(tile)
|
||||
}
|
||||
}
|
||||
newCiv.cache.updateOurTiles()
|
||||
oldCiv.cache.updateOurTiles()
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -138,8 +138,24 @@ class CivInfoTransientCache(val civInfo: Civilization) {
|
||||
civInfo.viewableInvisibleUnitsTiles = newViewableInvisibleTiles
|
||||
}
|
||||
|
||||
private var ourTilesAndNeighboringTiles: Set<Tile> = HashSet()
|
||||
|
||||
/** Our tiles update pretty infrequently - most 'viewable tile' changes are due to unit movements,
|
||||
* which means we can store this separately and use it 'as is' so we don't need to find the neighboring tiles every time
|
||||
* a unit moves */
|
||||
fun updateOurTiles(){
|
||||
val newOurTilesAndNeighboring = HashSet<Tile>()
|
||||
val ownedTiles = civInfo.cities.asSequence().flatMap { it.getTiles() }
|
||||
newOurTilesAndNeighboring.addAll(ownedTiles)
|
||||
val neighboringUnownedTiles = ownedTiles.flatMap { tile -> tile.neighbors.filter { it.getOwner() != civInfo } }
|
||||
newOurTilesAndNeighboring.addAll(neighboringUnownedTiles)
|
||||
ourTilesAndNeighboringTiles = newOurTilesAndNeighboring
|
||||
|
||||
updateViewableTiles()
|
||||
updateCivResources()
|
||||
}
|
||||
|
||||
private fun setNewViewableTiles() {
|
||||
val newViewableTiles = HashSet<Tile>()
|
||||
|
||||
// while spectating all map is visible
|
||||
if (civInfo.isSpectator() || DebugUtils.VISIBLE_MAP) {
|
||||
@ -149,13 +165,7 @@ class CivInfoTransientCache(val civInfo: Civilization) {
|
||||
return
|
||||
}
|
||||
|
||||
// There are a LOT of tiles usually.
|
||||
// And making large lists of them just as intermediaries before we shove them into the hashset is very space-inefficient.
|
||||
// And so, sequences to the rescue!
|
||||
val ownedTiles = civInfo.cities.asSequence().flatMap { it.getTiles() }
|
||||
newViewableTiles.addAll(ownedTiles)
|
||||
val neighboringUnownedTiles = ownedTiles.flatMap { tile -> tile.neighbors.filter { it.getOwner() != civInfo } }
|
||||
newViewableTiles.addAll(neighboringUnownedTiles)
|
||||
val newViewableTiles = HashSet<Tile>(ourTilesAndNeighboringTiles)
|
||||
newViewableTiles.addAll(civInfo.units.getCivUnits().flatMap { unit -> unit.viewableTiles.asSequence().filter { it.getOwner() != civInfo } })
|
||||
|
||||
for (otherCiv in civInfo.getKnownCivs()) {
|
||||
|
@ -105,8 +105,8 @@ class TradeLogic(val ourCivilization:Civilization, val otherCivilization: Civili
|
||||
unit.movement.teleportToClosestMoveableTile()
|
||||
}
|
||||
}
|
||||
to.cache.updateViewableTiles()
|
||||
from.cache.updateViewableTiles()
|
||||
to.cache.updateOurTiles()
|
||||
from.cache.updateOurTiles()
|
||||
|
||||
// suggest an option to liberate the city
|
||||
if (to.isHuman()
|
||||
|
Loading…
Reference in New Issue
Block a user