mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-09 15:29:32 +07:00
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:
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user