From a56874282be72df929341c2c3bbf1fd854ea20fe Mon Sep 17 00:00:00 2001 From: Yair Morgenstern Date: Wed, 26 Jan 2022 21:10:46 +0200 Subject: [PATCH] Converted RulesetObject unique checks to work against a map for efficiency --- core/src/com/unciv/models/ruleset/Era.kt | 10 ++------ .../com/unciv/models/ruleset/GlobalUniques.kt | 1 - .../com/unciv/models/ruleset/IHasUniques.kt | 24 ++++++++++--------- core/src/com/unciv/models/ruleset/Ruleset.kt | 2 ++ .../com/unciv/models/ruleset/RulesetObject.kt | 10 +++++++- .../com/unciv/models/ruleset/unit/UnitType.kt | 12 ++++------ core/src/com/unciv/ui/saves/LoadGameScreen.kt | 2 +- 7 files changed, 32 insertions(+), 29 deletions(-) diff --git a/core/src/com/unciv/models/ruleset/Era.kt b/core/src/com/unciv/models/ruleset/Era.kt index 0b224e5221..d50d24198e 100644 --- a/core/src/com/unciv/models/ruleset/Era.kt +++ b/core/src/com/unciv/models/ruleset/Era.kt @@ -8,8 +8,7 @@ import com.unciv.models.ruleset.unique.UniqueTarget import com.unciv.models.stats.INamed import com.unciv.ui.utils.colorFromRGB -class Era : INamed, IHasUniques { - override var name: String = "" +class Era : RulesetObject(), IHasUniques { var eraNumber: Int = -1 var researchAgreementCost = 300 var startingSettlerCount = 1 @@ -32,10 +31,8 @@ class Era : INamed, IHasUniques { val allyBonusObjects: Map> by lazy { initBonuses(allyBonus) } var iconRGB: List? = null - override var uniques: ArrayList = arrayListOf() override fun getUniqueTarget() = UniqueTarget.Era - override val uniqueObjects: List by lazy { uniques.map { Unique(it, - getUniqueTarget(), name) } } + override fun makeLink() = "" // No own category on Civilopedia screen private fun initBonuses(bonusMap: Map>): Map> { val objectMap = HashMap>() @@ -71,7 +68,4 @@ class Era : INamed, IHasUniques { } fun getHexColor() = "#" + getColor().toString().substring(0, 6) - - /** This is used for display purposes in templates */ - override fun toString() = name } diff --git a/core/src/com/unciv/models/ruleset/GlobalUniques.kt b/core/src/com/unciv/models/ruleset/GlobalUniques.kt index cf4f1d00cc..df6dcccd45 100644 --- a/core/src/com/unciv/models/ruleset/GlobalUniques.kt +++ b/core/src/com/unciv/models/ruleset/GlobalUniques.kt @@ -5,7 +5,6 @@ import com.unciv.models.ruleset.unique.UniqueTarget import com.unciv.models.ruleset.unique.UniqueType class GlobalUniques: RulesetObject() { - override var name = "" override fun getUniqueTarget() = UniqueTarget.Global override fun makeLink() = "" // No own category on Civilopedia screen diff --git a/core/src/com/unciv/models/ruleset/IHasUniques.kt b/core/src/com/unciv/models/ruleset/IHasUniques.kt index 7e17063a8d..4fcfde9057 100644 --- a/core/src/com/unciv/models/ruleset/IHasUniques.kt +++ b/core/src/com/unciv/models/ruleset/IHasUniques.kt @@ -11,7 +11,9 @@ import com.unciv.models.ruleset.unique.UniqueType interface IHasUniques { var uniques: ArrayList // Can not be a hashset as that would remove doubles // I bet there's a way of initializing these without having to override it everywhere... - val uniqueObjects: List + val uniqueObjects: List + + val uniqueMap: Map> /** Technically not currently needed, since the unique target can be retrieved from every unique in the uniqueObjects, * But making this a function is relevant for future "unify Unciv object" plans ;) @@ -19,14 +21,14 @@ interface IHasUniques { fun getUniqueTarget(): UniqueTarget fun getMatchingUniques(uniqueTemplate: String, stateForConditionals: StateForConditionals? = null) = - uniqueObjects.asSequence().filter { it.placeholderText == uniqueTemplate && it.conditionalsApply(stateForConditionals) } - - fun getMatchingUniques(uniqueType: UniqueType, stateForConditionals: StateForConditionals? = null) = - uniqueObjects.asSequence().filter { it.isOfType(uniqueType) && it.conditionalsApply(stateForConditionals) } - - fun hasUnique(uniqueTemplate: String, stateForConditionals: StateForConditionals? = null) = - uniqueObjects.any { it.placeholderText == uniqueTemplate && it.conditionalsApply(stateForConditionals) } - - fun hasUnique(uniqueType: UniqueType, stateForConditionals: StateForConditionals? = null) = - uniqueObjects.any { it.isOfType(uniqueType) && it.conditionalsApply(stateForConditionals) } + uniqueMap[uniqueTemplate]?.asSequence() ?: sequenceOf() + + fun getMatchingUniques(uniqueType: UniqueType, stateForConditionals: StateForConditionals? = null) = + getMatchingUniques(uniqueType.placeholderText, stateForConditionals) + + fun hasUnique(uniqueTemplate: String, stateForConditionals: StateForConditionals? = null) = + getMatchingUniques(uniqueTemplate, stateForConditionals).any() + + fun hasUnique(uniqueType: UniqueType, stateForConditionals: StateForConditionals? = null) = + getMatchingUniques(uniqueType.placeholderText, stateForConditionals).any() } diff --git a/core/src/com/unciv/models/ruleset/Ruleset.kt b/core/src/com/unciv/models/ruleset/Ruleset.kt index c59b7f73b9..389df5d258 100644 --- a/core/src/com/unciv/models/ruleset/Ruleset.kt +++ b/core/src/com/unciv/models/ruleset/Ruleset.kt @@ -55,6 +55,7 @@ class ModOptions : IHasUniques { override var uniques = ArrayList() // If this is delegated with "by lazy", the mod download process crashes and burns override var uniqueObjects: List = listOf() + override var uniqueMap: Map> = mapOf() override fun getUniqueTarget() = UniqueTarget.ModOptions val constants = ModConstants() @@ -164,6 +165,7 @@ class Ruleset { modOptions.constants.maxXPfromBarbarians = modOptions.constants.maxXPfromBarbarians } catch (ex: Exception) {} modOptions.uniqueObjects = modOptions.uniques.map { Unique(it, UniqueTarget.ModOptions) } + modOptions.uniqueMap = modOptions.uniqueObjects.groupBy { it.placeholderText } } val techFile = folderHandle.child("Techs.json") diff --git a/core/src/com/unciv/models/ruleset/RulesetObject.kt b/core/src/com/unciv/models/ruleset/RulesetObject.kt index c526b26c07..d244996b0e 100644 --- a/core/src/com/unciv/models/ruleset/RulesetObject.kt +++ b/core/src/com/unciv/models/ruleset/RulesetObject.kt @@ -9,12 +9,16 @@ import com.unciv.ui.civilopedia.ICivilopediaText interface IRulesetObject:INamed, IHasUniques, ICivilopediaText abstract class RulesetObject: IRulesetObject { - override lateinit var name: String + override var name = "" override var uniques = ArrayList() // Can not be a hashset as that would remove doubles @delegate:Transient override val uniqueObjects: List by lazy { uniques.map { Unique(it, getUniqueTarget(), name) } } + @delegate:Transient + override val uniqueMap: Map> by lazy { + uniqueObjects.groupBy { it.placeholderText } + } override var civilopediaText = listOf() override fun toString() = name } @@ -26,5 +30,9 @@ abstract class RulesetStatsObject: NamedStats(), IRulesetObject { override val uniqueObjects: List by lazy { uniques.map { Unique(it, getUniqueTarget(), name) } } + @delegate:Transient + override val uniqueMap: Map> by lazy { + uniqueObjects.groupBy { it.placeholderText } + } override var civilopediaText = listOf() } diff --git a/core/src/com/unciv/models/ruleset/unit/UnitType.kt b/core/src/com/unciv/models/ruleset/unit/UnitType.kt index 0e2fb5b491..59cea5ded3 100644 --- a/core/src/com/unciv/models/ruleset/unit/UnitType.kt +++ b/core/src/com/unciv/models/ruleset/unit/UnitType.kt @@ -1,6 +1,7 @@ package com.unciv.models.ruleset.unit import com.unciv.models.ruleset.IHasUniques +import com.unciv.models.ruleset.RulesetObject import com.unciv.models.ruleset.unique.Unique import com.unciv.models.ruleset.unique.UniqueTarget import com.unciv.models.stats.INamed @@ -18,16 +19,13 @@ enum class UnitMovementType { // The types of tiles the unit can by default ente Air // Only city tiles and carrying units } -class UnitType() : INamed, IHasUniques { - override lateinit var name: String +class UnitType() : RulesetObject() { private var movementType: String? = null private val unitMovementType: UnitMovementType? by lazy { if (movementType == null) null else UnitMovementType.valueOf(movementType!!) } - - override var uniques: ArrayList = ArrayList() + override fun getUniqueTarget() = UniqueTarget.UnitType - override val uniqueObjects: List by lazy { uniques.map { Unique(it, - getUniqueTarget(), name) } } - + override fun makeLink() = "" // No own category on Civilopedia screen + constructor(name: String, domain: String? = null) : this() { this.name = name this.movementType = domain diff --git a/core/src/com/unciv/ui/saves/LoadGameScreen.kt b/core/src/com/unciv/ui/saves/LoadGameScreen.kt index 7e5296cdb9..c2bb6ee136 100644 --- a/core/src/com/unciv/ui/saves/LoadGameScreen.kt +++ b/core/src/com/unciv/ui/saves/LoadGameScreen.kt @@ -41,7 +41,7 @@ class LoadGameScreen(previousScreen:BaseScreen) : PickerScreen(disableScroll = t val loadingPopup = Popup( this) loadingPopup.addGoodSizedLabel("Loading...") loadingPopup.open() - crashHandlingThread { + crashHandlingThread(name = "Load Game") { try { // This is what can lead to ANRs - reading the file and setting the transients, that's why this is in another thread val loadedGame = GameSaver.loadGameByName(selectedSave)