From 1620a4c231e9c55ac7abccf8a9bad0e5b8502921 Mon Sep 17 00:00:00 2001 From: yairm210 Date: Tue, 22 Jul 2025 16:06:55 +0300 Subject: [PATCH] chore(purity): Update to ensure new collections/sequences functions are ok --- build.gradle.kts | 4 ++-- core/src/com/unciv/logic/civilization/Civilization.kt | 6 +++++- core/src/com/unciv/models/Counter.kt | 2 ++ core/src/com/unciv/models/ruleset/tile/Terrain.kt | 2 +- core/src/com/unciv/models/ruleset/unique/Countables.kt | 8 +++----- 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index e38dfd83e0..f08587c27c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -37,7 +37,7 @@ plugins { // This is *with* gradle 8.2 downloaded according the project specs, no idea what that's about kotlin("multiplatform") version "1.9.24" kotlin("plugin.serialization") version "1.9.24" - id("io.github.yairm210.purity-plugin") version "0.0.27" apply(false) + id("io.github.yairm210.purity-plugin") version "0.0.33" apply(false) } allprojects { @@ -174,7 +174,7 @@ project(":core") { "implementation"("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion") "implementation"("org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion") - "implementation"("io.github.yairm210:purity-annotations:0.0.25") + "implementation"("io.github.yairm210:purity-annotations:0.0.32") "implementation"("io.ktor:ktor-client-core:$ktorVersion") "implementation"("io.ktor:ktor-client-cio:$ktorVersion") diff --git a/core/src/com/unciv/logic/civilization/Civilization.kt b/core/src/com/unciv/logic/civilization/Civilization.kt index 577e928813..2a46fd4ec5 100644 --- a/core/src/com/unciv/logic/civilization/Civilization.kt +++ b/core/src/com/unciv/logic/civilization/Civilization.kt @@ -36,7 +36,6 @@ import com.unciv.models.Counter import com.unciv.models.metadata.GameParameters import com.unciv.models.ruleset.Building import com.unciv.models.ruleset.Policy -import com.unciv.models.ruleset.Victory import com.unciv.models.ruleset.nation.CityStateType import com.unciv.models.ruleset.nation.Difficulty import com.unciv.models.ruleset.nation.Nation @@ -56,6 +55,7 @@ import com.unciv.models.translations.tr import com.unciv.ui.components.extensions.toPercent import com.unciv.ui.screens.victoryscreen.RankingType import org.jetbrains.annotations.VisibleForTesting +import yairm210.purity.annotations.LocalState import yairm210.purity.annotations.Readonly import kotlin.math.max import kotlin.math.min @@ -472,7 +472,9 @@ class Civilization : IsPartOfGameInfoSerialization { * Returns a dictionary of ALL resource names, and the amount that the civ has of each * Stockpiled resources return the stockpiled amount */ + @Readonly @Suppress("purity") fun getCivResourcesByName(): HashMap { + @LocalState val hashMap = HashMap(gameInfo.ruleset.tileResources.size) for (resource in gameInfo.ruleset.tileResources.keys) hashMap[resource] = 0 for (entry in getCivResourceSupply()) @@ -486,6 +488,7 @@ class Civilization : IsPartOfGameInfoSerialization { /** Gets the number of resources available to this city * Does not include city-wide resources * Returns 0 for undefined resources */ + @Readonly fun getResourceAmount(resourceName: String): Int { return getCivResourcesByName()[resourceName] ?: 0 } @@ -745,6 +748,7 @@ class Civilization : IsPartOfGameInfoSerialization { @Readonly fun calculateScoreBreakdown(): HashMap { + @LocalState val scoreBreakdown = hashMapOf() // 1276 is the number of tiles in a medium sized map. The original uses 4160 for this, // but they have bigger maps diff --git a/core/src/com/unciv/models/Counter.kt b/core/src/com/unciv/models/Counter.kt index 8efd43d167..ef259e4d01 100644 --- a/core/src/com/unciv/models/Counter.kt +++ b/core/src/com/unciv/models/Counter.kt @@ -3,6 +3,7 @@ package com.unciv.models import com.badlogic.gdx.utils.Json import com.badlogic.gdx.utils.JsonValue import com.unciv.logic.IsPartOfGameInfoSerialization +import yairm210.purity.annotations.LocalState import yairm210.purity.annotations.Readonly /** @@ -51,6 +52,7 @@ open class Counter( @Readonly /** Creates a new instance (does not modify) */ operator fun times(amount: Int): Counter { + @LocalState val newCounter = Counter() for (key in keys) newCounter[key] = this[key] * amount return newCounter diff --git a/core/src/com/unciv/models/ruleset/tile/Terrain.kt b/core/src/com/unciv/models/ruleset/tile/Terrain.kt index 375c040349..c7a272167b 100644 --- a/core/src/com/unciv/models/ruleset/tile/Terrain.kt +++ b/core/src/com/unciv/models/ruleset/tile/Terrain.kt @@ -162,7 +162,7 @@ class Terrain : RulesetStatsObject() { /** Terrain filter matching is "pure" - input always returns same output, and it's called a bajillion times */ val cachedMatchesFilterResult = HashMap() - @Readonly + @Readonly @Suppress("purity") fun matchesFilter(filter: String, state: GameContext? = null, multiFilter: Boolean = true): Boolean { return if (multiFilter) MultiFilter.multiFilter(filter, { cachedMatchesFilterResult.getOrPut(it) { matchesSingleFilter(it) } || diff --git a/core/src/com/unciv/models/ruleset/unique/Countables.kt b/core/src/com/unciv/models/ruleset/unique/Countables.kt index 26638e71d7..68912a66ce 100644 --- a/core/src/com/unciv/models/ruleset/unique/Countables.kt +++ b/core/src/com/unciv/models/ruleset/unique/Countables.kt @@ -229,6 +229,7 @@ enum class Countables( private val engine = Expressions() override val matchesWithRuleset: Boolean = true + @Suppress("purity") override fun matches(parameterText: String, ruleset: Ruleset) = engine.matches(parameterText, ruleset) override fun eval(parameterText: String, gameContext: GameContext): Int? = @@ -258,7 +259,6 @@ enum class Countables( open val noPlaceholders = !text.contains('[') // Leave these in place only for the really simple cases - @Readonly open fun matches(parameterText: String) = if (noPlaceholders) parameterText == text else parameterText.equalsPlaceholderText(placeholderText) @@ -268,9 +268,7 @@ enum class Countables( /** This indicates whether a parameter *is of this countable type*, not *whether its parameters are correct* * E.g. "[fakeBuilding] Buildings" is obviously a countable of type "[buildingFilter] Buildings", therefore matches will return true. * But it has another problem, which is that the building filter is bad, so its getErrorSeverity will return "ruleset specific" */ - @Readonly open fun matches(parameterText: String, ruleset: Ruleset): Boolean = false - @Readonly abstract fun eval(parameterText: String, gameContext: GameContext): Int? open val documentationHeader get() = @@ -293,7 +291,7 @@ enum class Countables( getErrorSeverity(parameterText.getPlaceholderParameters().first(), ruleset) companion object { - @Readonly + @Readonly @Suppress("purity") fun getMatching(parameterText: String, ruleset: Ruleset?) = Countables.entries .firstOrNull { if (it.matchesWithRuleset) @@ -301,7 +299,7 @@ enum class Countables( else it.matches(parameterText) } - @Readonly + @Readonly @Suppress("purity") fun getCountableAmount(parameterText: String, gameContext: GameContext): Int? { val ruleset = gameContext.gameInfo?.ruleset val countable = getMatching(parameterText, ruleset) ?: return null