diff --git a/build.gradle.kts b/build.gradle.kts index 778ebb3be9..1d85163831 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -52,6 +52,7 @@ allprojects { "java.util.regex.Pattern.matcher", "java.util.regex.Matcher.find", "java.util.regex.Matcher.replaceAll", + "kotlin.collections.linkedMapOf", ) wellKnownReadonlyFunctions = setOf( "com.badlogic.gdx.math.Vector2.len", diff --git a/core/src/com/unciv/logic/city/City.kt b/core/src/com/unciv/logic/city/City.kt index 54b50142e9..00844826b9 100644 --- a/core/src/com/unciv/logic/city/City.kt +++ b/core/src/com/unciv/logic/city/City.kt @@ -180,7 +180,7 @@ class City : IsPartOfGameInfoSerialization, INamed { @Readonly fun getWorkRange(): Int = civ.gameInfo.ruleset.modOptions.constants.cityWorkRange @Readonly fun getExpandRange(): Int = civ.gameInfo.ruleset.modOptions.constants.cityExpandRange - @Readonly @Suppress("purity") // the readonly connection type not respected for some reason for default value + @Readonly fun isConnectedToCapital(@Readonly connectionTypePredicate: (Set) -> Boolean = { true }): Boolean { val mediumTypes = civ.cache.citiesConnectedToCapitalToMediums[this] ?: return false return connectionTypePredicate(mediumTypes) diff --git a/core/src/com/unciv/models/stats/Stats.kt b/core/src/com/unciv/models/stats/Stats.kt index f3495cc749..baf4903a95 100644 --- a/core/src/com/unciv/models/stats/Stats.kt +++ b/core/src/com/unciv/models/stats/Stats.kt @@ -1,9 +1,7 @@ package com.unciv.models.stats import com.unciv.models.translations.tr -import yairm210.purity.annotations.InternalState -import yairm210.purity.annotations.Pure -import yairm210.purity.annotations.Readonly +import yairm210.purity.annotations.* /** * A container for the seven basic ["currencies"][Stat] in Unciv, @@ -170,6 +168,7 @@ open class Stats( * * Example output: `+1 Production, -1 Food`. */ + @Readonly override fun toString(): String { return this.joinToString { (if (it.value > 0) "+" else "") + it.value.toInt().tr() + " " + it.key.toString().tr() @@ -265,13 +264,15 @@ open class Stats( * - Order is not important. * @see [isStats] */ + @Pure fun parse(string: String): Stats { val toReturn = Stats() val statsWithBonuses = string.split(", ") - for(statWithBonuses in statsWithBonuses) { + statsWithBonuses.forEach { statWithBonuses -> val match = statRegex.matchEntire(statWithBonuses)!! - val statName = match.groupValues[3] - val statAmount = match.groupValues[2].toFloat() * (if (match.groupValues[1] == "-") -1 else 1) + @Immutable val groupValues = match.groupValues + val statName = groupValues[3] + val statAmount = groupValues[2].toFloat() * (if (groupValues[1] == "-") -1 else 1) toReturn.add(Stat.valueOf(statName), statAmount) } return toReturn diff --git a/core/src/com/unciv/models/translations/Translations.kt b/core/src/com/unciv/models/translations/Translations.kt index 6489b0a83b..b65211b955 100644 --- a/core/src/com/unciv/models/translations/Translations.kt +++ b/core/src/com/unciv/models/translations/Translations.kt @@ -58,6 +58,7 @@ class Translations : LinkedHashMap() { * * @return the translation entry or null when not available */ + @Readonly fun get(text: String, language: String, activeMods: HashSet? = null): TranslationEntry? { if (activeMods != null) for (activeMod in activeMods) { @@ -73,6 +74,7 @@ class Translations : LinkedHashMap() { /** * @see get */ + @Readonly fun getText(text: String, language: String, activeMods: HashSet? = null): String { return get(text, language, activeMods)?.get(language) ?: text } @@ -207,26 +209,30 @@ class Translations : LinkedHashMap() { debug("Loading percent complete of languages - %sms", System.currentTimeMillis() - startTime) } - + @Readonly fun getConditionalOrder(language: String): String { return getText(englishConditionalOrderingString, language, null) } + @Readonly fun placeConditionalsAfterUnique(language: String) = get(conditionalUniqueOrderString, language, null)?.get(language) != "before" /** Returns the equivalent of a space in the given language * Defaults to a space if no translation is provided */ + @Readonly fun getSpaceEquivalent(language: String): String { val translation = getText("\" \"", language, null) return translation.substring(1, translation.length-1) } + @Readonly fun shouldCapitalize(language: String): Boolean { return get(shouldCapitalizeString, language, null)?.get(language)?.toBoolean() ?: true } + @Readonly fun triggerNotificationEffectBeforeCause(language: String): Boolean{ return get(effectBeforeCause, language, null)?.get(language)?.toBoolean() ?: true } @@ -318,7 +324,7 @@ object TranslationActiveModsCache { * defaults to the input string if no translation is available, * but with placeholder or sentence brackets removed. */ -@Readonly @Suppress("purity") +@Readonly fun String.tr(hideIcons: Boolean = false, hideStats: Boolean = false): String { val language: String = UncivGame.Current.settings.language @@ -345,6 +351,7 @@ fun String.tr(hideIcons: Boolean = false, hideStats: Boolean = false): String { } +@Readonly private fun String.translateConditionals(hideIcons: Boolean, language: String): String { /** * So conditionals can contain placeholders, such as , which themselves @@ -404,6 +411,7 @@ private fun String.translateConditionals(hideIcons: Boolean, language: String): return fullyTranslatedString } +@Readonly private fun String.translatePlaceholders(language: String, hideIcons: Boolean): String { /** * I'm SURE there's an easier way to do this but I can't think of it =\ @@ -453,6 +461,7 @@ private fun String.translatePlaceholders(language: String, hideIcons: Boolean): /** No brackets of any kind, just a single word */ +@Readonly private fun String.translateIndividualWord(language: String, hideIcons: Boolean, hideStats: Boolean): String { if (Stats.isStats(this)) return Stats.parse(this).toString() @@ -577,6 +586,7 @@ fun Number.tr(): String { * * @return locale-dependent String representation of receiver, may contain formatting like thousands separators */ +@Readonly fun Number.tr(language: String): String { return LocaleCode.getNumberFormatFromLanguage(language).format(this) }