Cache civ uniques while refreshing world map tiles. (#9284)

* Cache civ uniques while refreshing world map tiles.

This should have a pretty significant performance improvement of about 10% next rount time.

* Forgot to add stateForConditionals to cache key.

* Make cache keys depend on function

* Restrict LocalUniqueCache API to avoid using it the wrong way.

* Use default values instead of two methods
This commit is contained in:
WhoIsJohannes 2023-04-26 09:17:58 +02:00 committed by GitHub
parent 0b0a400f65
commit cccaa88456
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 137 additions and 76 deletions

View File

@ -46,13 +46,11 @@ object Automation {
if (specialist) {
// If you have the Food Bonus, count as 1 extra food production (base is 2food)
for (unique in localUniqueCache.get(UniqueType.FoodConsumptionBySpecialists.name,
city.getMatchingUniques(UniqueType.FoodConsumptionBySpecialists)))
for (unique in localUniqueCache.forCityGetMatchingUniques(city, UniqueType.FoodConsumptionBySpecialists))
if (city.matchesFilter(unique.params[1]))
yieldStats.food -= (unique.params[0].toFloat() / 100f) * 2f // base 2 food per Pop
// Specialist Happiness Percentage Change 0f-1f
for (unique in localUniqueCache.get(UniqueType.UnhappinessFromPopulationTypePercentageChange.name,
city.getMatchingUniques(UniqueType.UnhappinessFromPopulationTypePercentageChange)))
for (unique in localUniqueCache.forCityGetMatchingUniques(city, UniqueType.UnhappinessFromPopulationTypePercentageChange))
if (city.matchesFilter(unique.params[2]) && unique.params[1] == "Specialists")
yieldStats.happiness -= (unique.params[0].toFloat() / 100f) // relative val is negative, make positive
if (city.civ.getHappiness() < 0) yieldStats.happiness *= 2 // double weight for unhappy civilization

View File

@ -182,10 +182,10 @@ class CityStats(val city: City) {
val specialist = city.getRuleset().specialists[specialistName]
?: return Stats()
val stats = specialist.cloneStats()
for (unique in localUniqueCache.get(UniqueType.StatsFromSpecialist.name, city.getMatchingUniques(UniqueType.StatsFromSpecialist)))
for (unique in localUniqueCache.forCityGetMatchingUniques(city, UniqueType.StatsFromSpecialist))
if (city.matchesFilter(unique.params[1]))
stats.add(unique.stats)
for (unique in localUniqueCache.get(UniqueType.StatsFromObject.name, city.civ.getMatchingUniques(UniqueType.StatsFromObject)))
for (unique in localUniqueCache.forCityGetMatchingUniques(city, UniqueType.StatsFromObject))
if (unique.params[1] == specialistName)
stats.add(unique.stats)
return stats

View File

@ -13,7 +13,10 @@ import com.unciv.ui.components.extensions.toPercent
class TileStatFunctions(val tile: Tile) {
fun getTileStats(observingCiv: Civilization?): Stats = getTileStats(tile.getCity(), observingCiv)
fun getTileStats(
observingCiv: Civilization?,
localUniqueCache: LocalUniqueCache = LocalUniqueCache(false)
): Stats = getTileStats(tile.getCity(), observingCiv, localUniqueCache)
fun getTileStats(city: City?, observingCiv: Civilization?,
localUniqueCache: LocalUniqueCache = LocalUniqueCache(false)
@ -24,19 +27,21 @@ class TileStatFunctions(val tile: Tile) {
val stateForConditionals = StateForConditionals(civInfo = observingCiv, city = city, tile = tile)
if (city != null) {
var tileUniques = city.getMatchingUniques(UniqueType.StatsFromTiles, StateForConditionals.IgnoreConditionals)
.filter { city.matchesFilter(it.params[2]) }
tileUniques += city.getMatchingUniques(UniqueType.StatsFromObject, StateForConditionals.IgnoreConditionals)
for (unique in localUniqueCache.get("StatsFromTilesAndObjects", tileUniques)) {
var tileUniques =
localUniqueCache.forCityGetMatchingUniques(
city, UniqueType.StatsFromTiles, StateForConditionals.IgnoreConditionals)
.filter { city.matchesFilter(it.params[2]) }
tileUniques += localUniqueCache.forCityGetMatchingUniques(
city, UniqueType.StatsFromObject, StateForConditionals.IgnoreConditionals)
for (unique in tileUniques) {
if (!unique.conditionalsApply(stateForConditionals)) continue
val tileType = unique.params[1]
if (!tile.matchesTerrainFilter(tileType, observingCiv)) continue
stats.add(unique.stats)
}
for (unique in localUniqueCache.get("StatsFromTilesWithout",
city.getMatchingUniques(UniqueType.StatsFromTilesWithout, StateForConditionals.IgnoreConditionals))
) {
for (unique in localUniqueCache.forCityGetMatchingUniques(
city, UniqueType.StatsFromTilesWithout, StateForConditionals.IgnoreConditionals)) {
if (
unique.conditionalsApply(stateForConditionals) &&
tile.matchesTerrainFilter(unique.params[1]) &&
@ -109,19 +114,19 @@ class TileStatFunctions(val tile: Tile) {
if (city != null) {
// Since the tile changes every time, we cache all uniques, and filter by conditional state only when iterating
val cachedStatPercentFromObjectUniques = uniqueCache.get(UniqueType.StatPercentFromObject.name,
city.getMatchingUniques(UniqueType.StatPercentFromObject, StateForConditionals.IgnoreConditionals))
val cachedStatPercentFromObjectCityUniques = uniqueCache.forCityGetMatchingUniques(
city, UniqueType.StatPercentFromObject, StateForConditionals.IgnoreConditionals)
for (unique in cachedStatPercentFromObjectUniques) {
for (unique in cachedStatPercentFromObjectCityUniques) {
if (!unique.conditionalsApply(stateForConditionals)) continue
val tileFilter = unique.params[2]
if (tile.matchesTerrainFilter(tileFilter, observingCiv))
stats[Stat.valueOf(unique.params[1])] += unique.params[0].toFloat()
}
val cachedAllStatPercentFromObjectUniques = uniqueCache.get(UniqueType.AllStatsPercentFromObject.name,
city.getMatchingUniques(UniqueType.AllStatsPercentFromObject, StateForConditionals.IgnoreConditionals))
for (unique in cachedAllStatPercentFromObjectUniques) {
val cachedAllStatPercentFromObjectCityUniques = uniqueCache.forCityGetMatchingUniques(
city, UniqueType.AllStatsPercentFromObject, StateForConditionals.IgnoreConditionals)
for (unique in cachedAllStatPercentFromObjectCityUniques) {
if (!unique.conditionalsApply(stateForConditionals)) continue
val tileFilter = unique.params[1]
if (!tile.matchesTerrainFilter(tileFilter, observingCiv)) continue
@ -131,13 +136,17 @@ class TileStatFunctions(val tile: Tile) {
}
} else if (observingCiv != null) {
for (unique in observingCiv.getMatchingUniques(UniqueType.StatPercentFromObject, stateForConditionals)) {
val cachedStatPercentFromObjectCivUniques = uniqueCache.forCivGetMatchingUniques(
observingCiv, UniqueType.StatPercentFromObject, stateForConditionals)
for (unique in cachedStatPercentFromObjectCivUniques) {
val tileFilter = unique.params[2]
if (tile.matchesTerrainFilter(tileFilter, observingCiv))
stats[Stat.valueOf(unique.params[1])] += unique.params[0].toFloat()
}
for (unique in observingCiv.getMatchingUniques(UniqueType.AllStatsPercentFromObject, stateForConditionals)) {
val cachedAllStatPercentFromObjectCivUniques = uniqueCache.forCivGetMatchingUniques(
observingCiv, UniqueType.AllStatsPercentFromObject, stateForConditionals)
for (unique in cachedAllStatPercentFromObjectCivUniques) {
val tileFilter = unique.params[1]
if (!tile.matchesTerrainFilter(tileFilter, observingCiv)) continue
val statPercentage = unique.params[0].toFloat()
@ -222,7 +231,7 @@ class TileStatFunctions(val tile: Tile) {
improvement: TileImprovement,
city: City,
conditionalState: StateForConditionals,
cityUniqueCache: LocalUniqueCache
uniqueCache: LocalUniqueCache
): Stats {
val stats = Stats()
@ -231,9 +240,8 @@ class TileStatFunctions(val tile: Tile) {
// therefore if we want the cache to be useful it needs to hold the pre-filtered uniques,
// and then for each improvement we'll filter the uniques locally.
// This is still a MASSIVE save of RAM!
val tileUniques = cityUniqueCache.get(UniqueType.StatsFromTiles.name,
city.getMatchingUniques(UniqueType.StatsFromTiles, StateForConditionals.IgnoreConditionals)
.filter { city.matchesFilter(it.params[2]) }) // These are the uniques for all improvements for this city,
val tileUniques = uniqueCache.forCityGetMatchingUniques(city, UniqueType.StatsFromTiles, StateForConditionals.IgnoreConditionals)
.filter { city.matchesFilter(it.params[2]) } // These are the uniques for all improvements for this city,
.filter { it.conditionalsApply(conditionalState) } // ...and this is those with applicable conditions
val improvementUniques =
improvement.getMatchingUniques(UniqueType.ImprovementStatsOnTile, conditionalState)
@ -250,9 +258,11 @@ class TileStatFunctions(val tile: Tile) {
fun statsFromObject() {
// Same as above - cache holds unfiltered uniques for the city, while we use only the filtered ones
val uniques = cityUniqueCache.get(UniqueType.StatsFromObject.name,
city.getMatchingUniques(UniqueType.StatsFromObject, StateForConditionals.IgnoreConditionals))
.filter { it.conditionalsApply(conditionalState) }
val uniques = uniqueCache.forCityGetMatchingUniques(
city,
UniqueType.StatsFromObject,
StateForConditionals.IgnoreConditionals
).filter { it.conditionalsApply(conditionalState) }
for (unique in uniques) {
if (improvement.matchesFilter(unique.params[1])) {
stats.add(unique.stats)
@ -280,9 +290,11 @@ class TileStatFunctions(val tile: Tile) {
if (city != null) {
// As above, since the conditional is tile-dependant,
// we save uniques in the cache without conditional filtering, and use only filtered ones
val allStatPercentUniques = cityUniqueCache.get(UniqueType.AllStatsPercentFromObject.name,
city.getMatchingUniques(UniqueType.AllStatsPercentFromObject, StateForConditionals.IgnoreConditionals))
.filter { it.conditionalsApply(conditionalState) }
val allStatPercentUniques = cityUniqueCache.forCityGetMatchingUniques(
city,
UniqueType.AllStatsPercentFromObject,
StateForConditionals.IgnoreConditionals
).filter { it.conditionalsApply(conditionalState) }
for (unique in allStatPercentUniques) {
if (!improvement.matchesFilter(unique.params[1])) continue
for (stat in Stat.values()) {
@ -291,9 +303,11 @@ class TileStatFunctions(val tile: Tile) {
}
// Same trick different unique - not sure if worth generalizing this 'late apply' of conditions?
val statPercentUniques = cityUniqueCache.get(UniqueType.StatPercentFromObject.name,
city.getMatchingUniques(UniqueType.StatPercentFromObject, StateForConditionals.IgnoreConditionals))
.filter { it.conditionalsApply(conditionalState) }
val statPercentUniques = cityUniqueCache.forCityGetMatchingUniques(
city,
UniqueType.StatPercentFromObject,
StateForConditionals.IgnoreConditionals
).filter { it.conditionalsApply(conditionalState) }
for (unique in statPercentUniques) {
if (!improvement.matchesFilter(unique.params[2])) continue

View File

@ -184,7 +184,7 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
// Calls the clone function of the NamedStats this class is derived from, not a clone function of this class
val stats = cloneStats()
for (unique in localUniqueCache.get("StatsFromObject", city.getMatchingUniques(UniqueType.StatsFromObject))) {
for (unique in localUniqueCache.forCityGetMatchingUniques(city, UniqueType.StatsFromObject)) {
if (!matchesFilter(unique.params[1])) continue
stats.add(unique.stats)
}
@ -193,7 +193,7 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
stats.add(unique.stats)
if (!isWonder)
for (unique in localUniqueCache.get("StatsFromBuildings", city.getMatchingUniques(UniqueType.StatsFromBuildings))) {
for (unique in localUniqueCache.forCityGetMatchingUniques(city, UniqueType.StatsFromBuildings)) {
if (matchesFilter(unique.params[1]))
stats.add(unique.stats)
}
@ -204,12 +204,12 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
val stats = percentStatBonus?.clone() ?: Stats()
val civInfo = city?.civ ?: return stats // initial stats
for (unique in localUniqueCache.get("StatPercentFromObject", civInfo.getMatchingUniques(UniqueType.StatPercentFromObject))) {
for (unique in localUniqueCache.forCivGetMatchingUniques(civInfo, UniqueType.StatPercentFromObject)) {
if (matchesFilter(unique.params[2]))
stats.add(Stat.valueOf(unique.params[1]), unique.params[0].toFloat())
}
for (unique in localUniqueCache.get("AllStatsPercentFromObject", civInfo.getMatchingUniques(UniqueType.AllStatsPercentFromObject))) {
for (unique in localUniqueCache.forCivGetMatchingUniques(civInfo, UniqueType.AllStatsPercentFromObject)) {
if (!matchesFilter(unique.params[1])) continue
for (stat in Stat.values()) {
stats.add(stat, unique.params[0].toFloat())

View File

@ -301,8 +301,35 @@ class LocalUniqueCache(val cache:Boolean = true) {
// This stores sequences *that iterate directly on a list* - that is, pre-resolved
private val keyToUniques = HashMap<String, Sequence<Unique>>()
fun forCityGetMatchingUniques(
city: City,
uniqueType: UniqueType,
stateForConditionals: StateForConditionals = StateForConditionals(
city.civ,
city
)
): Sequence<Unique> {
return get(
"city-${city.id}-${uniqueType.name}-${stateForConditionals}",
city.getMatchingUniques(uniqueType, stateForConditionals)
)
}
fun forCivGetMatchingUniques(
civ: Civilization,
uniqueType: UniqueType,
stateForConditionals: StateForConditionals = StateForConditionals(
civ
)
): Sequence<Unique> {
return get(
"civ-${civ.civName}-${uniqueType.name}-${stateForConditionals}",
civ.getMatchingUniques(uniqueType, stateForConditionals)
)
}
/** Get cached results as a sequence */
fun get(key: String, sequence: Sequence<Unique>): Sequence<Unique> {
private fun get(key: String, sequence: Sequence<Unique>): Sequence<Unique> {
if (!cache) return sequence
if (keyToUniques.containsKey(key)) return keyToUniques[key]!!
// Iterate the sequence, save actual results as a list, as return a sequence to that

View File

@ -8,6 +8,7 @@ import com.unciv.UncivGame
import com.unciv.logic.city.City
import com.unciv.logic.civilization.Civilization
import com.unciv.logic.map.tile.Tile
import com.unciv.models.ruleset.unique.LocalUniqueCache
import com.unciv.models.stats.Stat
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.components.extensions.addToCenter
@ -31,8 +32,8 @@ class CityTileGroup(val city: City, tile: Tile, tileSetStrings: TileSetStrings)
layerMisc.touchable = Touchable.childrenOnly
}
override fun update(viewingCiv: Civilization?) {
super.update(city.civ)
override fun update(viewingCiv: Civilization?, localUniqueCache: LocalUniqueCache) {
super.update(city.civ, localUniqueCache)
tileState = CityTileState.NONE

View File

@ -4,6 +4,7 @@ import com.badlogic.gdx.graphics.g2d.Batch
import com.badlogic.gdx.scenes.scene2d.Group
import com.unciv.logic.civilization.Civilization
import com.unciv.logic.map.tile.Tile
import com.unciv.models.ruleset.unique.LocalUniqueCache
import com.unciv.ui.components.tilegroups.layers.TileLayerBorders
import com.unciv.ui.components.tilegroups.layers.TileLayerCityButton
import com.unciv.ui.components.tilegroups.layers.TileLayerFeatures
@ -74,10 +75,10 @@ open class TileGroup(
|| viewingCiv.viewableTiles.contains(tile)
|| viewingCiv.isSpectator()
private fun reset() {
private fun reset(localUniqueCache: LocalUniqueCache) {
layerTerrain.reset()
layerBorders.reset()
layerMisc.reset()
layerMisc.reset(localUniqueCache)
layerOverlay.reset()
layerUnitArt.reset()
layerUnitFlag.reset()
@ -94,8 +95,9 @@ open class TileGroup(
layerCityButton.isVisible = isVisible
}
open fun update(viewingCiv: Civilization? = null) {
open fun update(
viewingCiv: Civilization? = null,
localUniqueCache: LocalUniqueCache = LocalUniqueCache(false)) {
layerMisc.removeHexOutline()
layerMisc.hideTerrainOverlay()
layerOverlay.hideHighlight()
@ -107,7 +109,7 @@ open class TileGroup(
// Do not update layers if tile is not explored by viewing player
if (viewingCiv != null && !(isForceVisible || viewingCiv.hasExplored(tile))) {
reset()
reset(localUniqueCache)
// If tile has explored neighbors - reveal layers partially
if (tile.neighbors.none { viewingCiv.hasExplored(it) })
// Else - hide all layers
@ -117,14 +119,14 @@ open class TileGroup(
removeMissingModReferences()
layerTerrain.update(viewingCiv)
layerFeatures.update(viewingCiv)
layerBorders.update(viewingCiv)
layerOverlay.update(viewingCiv)
layerMisc.update(viewingCiv)
layerUnitArt.update(viewingCiv)
layerUnitFlag.update(viewingCiv)
layerCityButton.update(viewingCiv)
layerTerrain.update(viewingCiv, localUniqueCache)
layerFeatures.update(viewingCiv, localUniqueCache)
layerBorders.update(viewingCiv, localUniqueCache)
layerOverlay.update(viewingCiv, localUniqueCache)
layerMisc.update(viewingCiv, localUniqueCache)
layerUnitArt.update(viewingCiv, localUniqueCache)
layerUnitFlag.update(viewingCiv, localUniqueCache)
layerCityButton.update(viewingCiv, localUniqueCache)
}
private fun removeMissingModReferences() {

View File

@ -5,10 +5,10 @@ import com.badlogic.gdx.scenes.scene2d.Touchable
import com.unciv.UncivGame
import com.unciv.logic.civilization.Civilization
import com.unciv.logic.map.tile.Tile
import com.unciv.models.ruleset.unique.LocalUniqueCache
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.components.extensions.center
import com.unciv.ui.components.extensions.darken
import com.unciv.ui.screens.worldscreen.WorldScreen
class WorldTileGroup(tile: Tile, tileSetStrings: TileSetStrings)
@ -18,8 +18,8 @@ class WorldTileGroup(tile: Tile, tileSetStrings: TileSetStrings)
layerMisc.touchable = Touchable.disabled
}
override fun update(viewingCiv: Civilization?) {
super.update(viewingCiv)
override fun update(viewingCiv: Civilization?, localUniqueCache: LocalUniqueCache) {
super.update(viewingCiv, localUniqueCache)
updateWorkedIcon(viewingCiv!!)
}

View File

@ -5,6 +5,7 @@ import com.badlogic.gdx.scenes.scene2d.Touchable
import com.badlogic.gdx.scenes.scene2d.ui.Image
import com.unciv.logic.civilization.Civilization
import com.unciv.logic.map.tile.Tile
import com.unciv.models.ruleset.unique.LocalUniqueCache
import com.unciv.models.tilesets.TileSetCache
import com.unciv.ui.components.tilegroups.TileGroup
import com.unciv.ui.components.tilegroups.TileSetStrings
@ -32,8 +33,10 @@ abstract class TileLayer(val tileGroup: TileGroup, size: Float) : Group() {
fun isViewable(viewingCiv: Civilization) = tileGroup.isViewable(viewingCiv)
fun update(viewingCiv: Civilization?) {
doUpdate(viewingCiv)
fun update(
viewingCiv: Civilization?,
localUniqueCache: LocalUniqueCache = LocalUniqueCache(false)) {
doUpdate(viewingCiv, localUniqueCache)
determineVisibility()
}
@ -41,6 +44,8 @@ abstract class TileLayer(val tileGroup: TileGroup, size: Float) : Group() {
isVisible = hasChildren()
}
protected abstract fun doUpdate(viewingCiv: Civilization?)
protected abstract fun doUpdate(
viewingCiv: Civilization?,
localUniqueCache: LocalUniqueCache = LocalUniqueCache(false))
}

View File

@ -4,6 +4,7 @@ import com.badlogic.gdx.scenes.scene2d.Actor
import com.badlogic.gdx.scenes.scene2d.ui.Image
import com.unciv.logic.civilization.Civilization
import com.unciv.logic.map.tile.Tile
import com.unciv.models.ruleset.unique.LocalUniqueCache
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.components.tilegroups.TileGroup
import kotlin.math.PI
@ -135,7 +136,7 @@ class TileLayerBorders(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup,
}
override fun doUpdate(viewingCiv: Civilization?) {
override fun doUpdate(viewingCiv: Civilization?, localUniqueCache: LocalUniqueCache) {
updateBorders()
}

View File

@ -5,6 +5,7 @@ import com.badlogic.gdx.scenes.scene2d.Actor
import com.badlogic.gdx.scenes.scene2d.Touchable
import com.badlogic.gdx.utils.Align
import com.unciv.logic.civilization.Civilization
import com.unciv.models.ruleset.unique.LocalUniqueCache
import com.unciv.ui.components.tilegroups.CityButton
import com.unciv.ui.components.tilegroups.TileGroup
import com.unciv.ui.components.tilegroups.WorldTileGroup
@ -43,7 +44,7 @@ class TileLayerCityButton(tileGroup: TileGroup, size: Float) : TileLayer(tileGro
cityButton?.moveButtonDown()
}
override fun doUpdate(viewingCiv: Civilization?) {
override fun doUpdate(viewingCiv: Civilization?, localUniqueCache: LocalUniqueCache) {
if (tileGroup !is WorldTileGroup)
return

View File

@ -5,6 +5,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Image
import com.unciv.logic.civilization.Civilization
import com.unciv.logic.map.tile.RoadStatus
import com.unciv.logic.map.tile.Tile
import com.unciv.models.ruleset.unique.LocalUniqueCache
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.components.tilegroups.TileGroup
import kotlin.math.atan2
@ -69,7 +70,7 @@ class TileLayerFeatures(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup
}
override fun doUpdate(viewingCiv: Civilization?) {
override fun doUpdate(viewingCiv: Civilization?, localUniqueCache: LocalUniqueCache) {
updateRoadImages()
}

View File

@ -13,6 +13,7 @@ import com.unciv.models.helpers.MapArrowType
import com.unciv.models.helpers.MiscArrowTypes
import com.unciv.models.helpers.TintedMapArrow
import com.unciv.models.helpers.UnitMovementMemoryType
import com.unciv.models.ruleset.unique.LocalUniqueCache
import com.unciv.ui.components.extensions.center
import com.unciv.ui.components.extensions.centerX
import com.unciv.ui.components.extensions.toLabel
@ -268,7 +269,11 @@ class TileLayerMisc(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup, si
}
// JN updating display of tile yields
private fun updateYieldIcon(viewingCiv: Civilization?, show: Boolean) {
private fun updateYieldIcon(
viewingCiv: Civilization?,
show: Boolean,
localUniqueCache: LocalUniqueCache
) {
val effectiveVisible = show &&
!tileGroup.isForMapEditorIcon && // don't have a map to calc yields
!(viewingCiv == null && tileGroup.isForceVisible) // main menu background
@ -278,9 +283,9 @@ class TileLayerMisc(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup, si
if (effectiveVisible) yields.run {
// Update YieldGroup Icon
if (tileGroup is CityTileGroup)
setStats(tile().stats.getTileStats(tileGroup.city, viewingCiv))
setStats(tile().stats.getTileStats(tileGroup.city, viewingCiv, localUniqueCache))
else
setStats(tile().stats.getTileStats(viewingCiv))
setStats(tile().stats.getTileStats(viewingCiv, localUniqueCache))
toFront()
centerX(tileGroup)
isVisible = true
@ -345,7 +350,7 @@ class TileLayerMisc(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup, si
determineVisibility()
}
override fun doUpdate(viewingCiv: Civilization?) {
override fun doUpdate(viewingCiv: Civilization?, localUniqueCache: LocalUniqueCache) {
var showResourcesAndImprovements = true
var showTileYields = true
@ -356,7 +361,7 @@ class TileLayerMisc(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup, si
}
updateImprovementIcon(viewingCiv, showResourcesAndImprovements)
updateYieldIcon(viewingCiv, showTileYields)
updateYieldIcon(viewingCiv, showTileYields, localUniqueCache)
updateResourceIcon(viewingCiv, showResourcesAndImprovements)
if (tileGroup !is WorldTileGroup || DebugUtils.SHOW_TILE_COORDS)
updateStartingLocationIcon(true)
@ -374,9 +379,9 @@ class TileLayerMisc(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup, si
|| terrainOverlay.isVisible
}
fun reset() {
fun reset(localUniqueCache: LocalUniqueCache) {
updateImprovementIcon(null, false)
updateYieldIcon(null, false)
updateYieldIcon(null, false, localUniqueCache)
updateResourceIcon(null, false)
updateStartingLocationIcon(false)
clearArrows()

View File

@ -4,6 +4,7 @@ import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.Actor
import com.unciv.Constants
import com.unciv.logic.civilization.Civilization
import com.unciv.models.ruleset.unique.LocalUniqueCache
import com.unciv.ui.components.tilegroups.TileGroup
import com.unciv.ui.images.ImageGetter
@ -79,7 +80,7 @@ class TileLayerOverlay(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup,
determineVisibility()
}
override fun doUpdate(viewingCiv: Civilization?) {
override fun doUpdate(viewingCiv: Civilization?, localUniqueCache: LocalUniqueCache) {
val isViewable = viewingCiv == null || isViewable(viewingCiv)
fog.isVisible = !isViewable && !tileGroup.isForceVisible

View File

@ -6,6 +6,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Image
import com.unciv.UncivGame
import com.unciv.logic.civilization.Civilization
import com.unciv.logic.map.tile.Tile
import com.unciv.models.ruleset.unique.LocalUniqueCache
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.components.tilegroups.TileGroup
import com.unciv.ui.screens.basescreen.BaseScreen
@ -194,7 +195,7 @@ class TileLayerTerrain(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup,
}
}
override fun doUpdate(viewingCiv: Civilization?) {
override fun doUpdate(viewingCiv: Civilization?, localUniqueCache: LocalUniqueCache) {
updateTileImage(viewingCiv)
updateRivers(tileGroup.tile.hasBottomRightRiver, tileGroup.tile.hasBottomRiver, tileGroup.tile.hasBottomLeftRiver)
updateTileColor(viewingCiv)

View File

@ -5,6 +5,7 @@ import com.badlogic.gdx.scenes.scene2d.Group
import com.unciv.UncivGame
import com.unciv.logic.civilization.Civilization
import com.unciv.logic.map.mapunit.MapUnit
import com.unciv.models.ruleset.unique.LocalUniqueCache
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.components.tilegroups.TileGroup
@ -63,7 +64,7 @@ class TileLayerUnitArt(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup,
color.a = 0.5f
}
override fun doUpdate(viewingCiv: Civilization?) {
override fun doUpdate(viewingCiv: Civilization?, localUniqueCache: LocalUniqueCache) {
val slot1Unit = tileGroup.tile.civilianUnit
val slot2Unit = tileGroup.tile.militaryUnit

View File

@ -6,6 +6,7 @@ import com.badlogic.gdx.utils.Align
import com.unciv.UncivGame
import com.unciv.logic.civilization.Civilization
import com.unciv.logic.map.mapunit.MapUnit
import com.unciv.models.ruleset.unique.LocalUniqueCache
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.components.tilegroups.TileGroup
import com.unciv.ui.screens.basescreen.BaseScreen
@ -133,7 +134,7 @@ class TileLayerUnitFlag(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup
}
override fun doUpdate(viewingCiv: Civilization?) {
override fun doUpdate(viewingCiv: Civilization?, localUniqueCache: LocalUniqueCache) {
clearSlots()
fillSlots(viewingCiv)

View File

@ -32,6 +32,7 @@ import com.unciv.logic.map.tile.Tile
import com.unciv.models.UncivSound
import com.unciv.models.helpers.MapArrowType
import com.unciv.models.helpers.MiscArrowTypes
import com.unciv.models.ruleset.unique.LocalUniqueCache
import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.ui.audio.SoundPlayer
import com.unciv.ui.components.KeyCharAndCode
@ -567,8 +568,9 @@ class WorldMapHolder(
}
// General update of all tiles
val uniqueCache = LocalUniqueCache(true)
for (tileGroup in tileGroups.values)
tileGroup.update(viewingCiv)
tileGroup.update(viewingCiv, uniqueCache)
// Update tiles according to selected unit/city
val unitTable = worldScreen.bottomUnitTable