A ModOptions unique allowing a mod to control which map gets preselected (#11468)

* Minor linting

* UniqueType.ModMapPreselection
This commit is contained in:
SomeTroglodyte 2024-06-04 17:00:29 +02:00 committed by GitHub
parent 4b2f5e468d
commit 7e3bbb6053
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 42 additions and 7 deletions

View File

@ -887,6 +887,8 @@ enum class UniqueType(
ModIsAudioVisualOnly("Should only be used as permanent audiovisual mod", UniqueTarget.ModOptions, flags = UniqueFlag.setOfNoConditionals),
ModIsAudioVisual("Can be used as permanent audiovisual mod", UniqueTarget.ModOptions, flags = UniqueFlag.setOfNoConditionals),
ModIsNotAudioVisual("Cannot be used as permanent audiovisual mod", UniqueTarget.ModOptions, flags = UniqueFlag.setOfNoConditionals),
ModMapPreselection("Mod preselects map [comment]", UniqueTarget.ModOptions, flags = UniqueFlag.setOfNoConditionals,
docDescription = "Only meaningful for Mods containing several maps. When this mod is selected on the new game screen's custom maps mod dropdown, the named map will be selected on the map dropdown. Also disables selection by recently modified. Case insensitive."),
// endregion

View File

@ -123,6 +123,23 @@ class RulesetValidator(val ruleset: Ruleset) {
// modOptions is a valid sourceObject, but unnecessary
if (ruleset.modOptions.uniqueObjects.count { it.type in audioVisualUniqueTypes } > 1)
lines.add("A mod should only specify one of the 'can/should/cannot be used as permanent audiovisual mod' options.", sourceObject = null)
val mapSelectUniques = ruleset.modOptions.getMatchingUniques(UniqueType.ModMapPreselection).toList()
if (mapSelectUniques.size > 1)
lines.add("Specifying more than one map as preselection makes no sense", RulesetErrorSeverity.WarningOptionsOnly, sourceObject = null)
if (mapSelectUniques.isNotEmpty()) {
val mapsFolder = Gdx.files.local("mods").child(ruleset.name).child("maps")
if (mapsFolder.exists()) {
val maps = mapsFolder.list().map { it.name().lowercase() }
for (unique in mapSelectUniques) {
if (unique.params[0].lowercase() in maps) continue
lines.add("Mod names map '${unique.params[0]}' as preselection, which does not exist.", RulesetErrorSeverity.WarningOptionsOnly, sourceObject = null)
}
} else {
lines.add("Mod option for map preselection exists but Mod has no 'maps' folder.", RulesetErrorSeverity.WarningOptionsOnly, sourceObject = null)
}
}
if (!ruleset.modOptions.isBaseRuleset) return
for (unique in ruleset.modOptions.getMatchingUniques(UniqueType.ModRequires)) {
lines.add("Mod option '${unique.text}' is invalid for a base ruleset.", sourceObject = null)

View File

@ -18,6 +18,7 @@ import com.unciv.logic.map.TileMap
import com.unciv.models.metadata.Player
import com.unciv.models.ruleset.RulesetCache
import com.unciv.models.ruleset.nation.Nation
import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.translations.tr
import com.unciv.ui.components.SmallButtonStyle
import com.unciv.ui.components.extensions.disable
@ -209,13 +210,22 @@ class MapFileSelectTable(
.toGdxArray()
fun getPreselect(): MapWrapper? {
if (mapFiles.isEmpty) return null
val recent = mapFiles.asSequence()
.filter { it.fileHandle.isRecentlyModified() }
.maxByOrNull { it.fileHandle.lastModified() }
val oldestTimestamp = mapFiles.minOfOrNull { it.fileHandle.lastModified() } ?: 0L
// Do not use most recent if all maps in the category have the same time within a tenth of a second (like a mod unzip does)
if (recent != null && (recent.fileHandle.lastModified() - oldestTimestamp) > 100 || mapFiles.size == 1)
return recent
val modOptionPreselect = RulesetCache[selectedRuleset]
?.modOptions?.getMatchingUniques(UniqueType.ModMapPreselection)
?.firstOrNull()?.params?.get(0)
if (modOptionPreselect != null) {
val preselectFile = mapFiles.firstOrNull { it.fileHandle.name() == modOptionPreselect }
if (preselectFile != null)
return preselectFile
} else {
val recent = mapFiles.asSequence()
.filter { it.fileHandle.isRecentlyModified() }
.maxByOrNull { it.fileHandle.lastModified() }
val oldestTimestamp = mapFiles.minOfOrNull { it.fileHandle.lastModified() } ?: 0L
// Do not use most recent if all maps in the category have the same time within a tenth of a second (like a mod unzip does)
if (recent != null && (recent.fileHandle.lastModified() - oldestTimestamp) > 100 || mapFiles.size == 1)
return recent
}
val named = mapFiles.firstOrNull { it.fileHandle.name() == preselectedName }
if (named != null)
return named

View File

@ -1921,6 +1921,12 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
??? example "Cannot be used as permanent audiovisual mod"
Applicable to: ModOptions
??? example "Mod preselects map [comment]"
Only meaningful for Mods containing several maps. When this mod is selected on the new game screen's custom maps mod dropdown, the named map will be selected on the map dropdown. Also disables selection by recently modified. Case insensitive.
Example: "Mod preselects map [comment]"
Applicable to: ModOptions
## Conditional uniques
!!! note ""