Set tryFixUnknownUniques on RulesetValidator, for simpler function calls throughout

This commit is contained in:
yairm210 2025-06-01 11:04:43 +03:00
parent e42e963871
commit 2d91981440
3 changed files with 52 additions and 109 deletions

View File

@ -524,5 +524,5 @@ class Ruleset {
return stringList.joinToString { it.tr() } return stringList.joinToString { it.tr() }
} }
fun getErrorList(tryFixUnknownUniques: Boolean = false) = RulesetValidator(this).getErrorList(tryFixUnknownUniques) fun getErrorList(tryFixUnknownUniques: Boolean = false) = RulesetValidator(this, tryFixUnknownUniques).getErrorList()
} }

View File

@ -27,34 +27,34 @@ import com.unciv.ui.images.ImageGetter
import com.unciv.ui.images.Portrait import com.unciv.ui.images.Portrait
import com.unciv.ui.images.PortraitPromotion import com.unciv.ui.images.PortraitPromotion
class RulesetValidator(val ruleset: Ruleset) { class RulesetValidator(val ruleset: Ruleset, private val tryFixUnknownUniques: Boolean = false) {
private val uniqueValidator = UniqueValidator(ruleset) private val uniqueValidator = UniqueValidator(ruleset)
private lateinit var textureNamesCache: AtlasPreview private lateinit var textureNamesCache: AtlasPreview
fun getErrorList(tryFixUnknownUniques: Boolean = false): RulesetErrorList { fun getErrorList(): RulesetErrorList {
// When no base ruleset is loaded - references cannot be checked // When no base ruleset is loaded - references cannot be checked
if (!ruleset.modOptions.isBaseRuleset) return getNonBaseRulesetErrorList(tryFixUnknownUniques) if (!ruleset.modOptions.isBaseRuleset) return getNonBaseRulesetErrorList()
return getBaseRulesetErrorList(tryFixUnknownUniques) return getBaseRulesetErrorList()
} }
private fun getNonBaseRulesetErrorList(tryFixUnknownUniques: Boolean): RulesetErrorList { private fun getNonBaseRulesetErrorList(): RulesetErrorList {
val lines = RulesetErrorList(ruleset) val lines = RulesetErrorList(ruleset)
// When not checking the entire ruleset, we can only really detect ruleset-invariant errors in uniques // When not checking the entire ruleset, we can only really detect ruleset-invariant errors in uniques
addModOptionsErrors(lines, tryFixUnknownUniques) addModOptionsErrors(lines)
addGlobalUniqueErrors(lines, false, tryFixUnknownUniques) addGlobalUniqueErrors(lines, false)
addUnitErrorsRulesetInvariant(lines, tryFixUnknownUniques) addUnitErrorsRulesetInvariant(lines)
addTechErrorsRulesetInvariant(lines, tryFixUnknownUniques) addTechErrorsRulesetInvariant(lines)
addTechColumnErrorsRulesetInvariant(lines) addTechColumnErrorsRulesetInvariant(lines)
addBuildingErrorsRulesetInvariant(lines, tryFixUnknownUniques) addBuildingErrorsRulesetInvariant(lines)
addNationErrorsRulesetInvariant(lines, tryFixUnknownUniques) addNationErrorsRulesetInvariant(lines)
addPromotionErrorsRulesetInvariant(lines, tryFixUnknownUniques) addPromotionErrorsRulesetInvariant(lines)
addResourceErrorsRulesetInvariant(lines, tryFixUnknownUniques) addResourceErrorsRulesetInvariant(lines)
if (!::textureNamesCache.isInitialized) if (!::textureNamesCache.isInitialized)
textureNamesCache = AtlasPreview(ruleset, lines) // This logs Atlas list errors, and if these exist, scans for invalid png's textureNamesCache = AtlasPreview(ruleset, lines) // This logs Atlas list errors, and if these exist, scans for invalid png's
@ -68,31 +68,31 @@ class RulesetValidator(val ruleset: Ruleset) {
} }
private fun getBaseRulesetErrorList(tryFixUnknownUniques: Boolean): RulesetErrorList { private fun getBaseRulesetErrorList(): RulesetErrorList {
uniqueValidator.populateFilteringUniqueHashsets() uniqueValidator.populateFilteringUniqueHashsets()
val lines = RulesetErrorList(ruleset) val lines = RulesetErrorList(ruleset)
addModOptionsErrors(lines, tryFixUnknownUniques) addModOptionsErrors(lines)
addGlobalUniqueErrors(lines, true, tryFixUnknownUniques) addGlobalUniqueErrors(lines, true)
addUnitErrorsBaseRuleset(lines, tryFixUnknownUniques) addUnitErrorsBaseRuleset(lines)
addBuildingErrors(lines, tryFixUnknownUniques) addBuildingErrors(lines)
addSpecialistErrors(lines) addSpecialistErrors(lines)
addResourceErrors(lines, tryFixUnknownUniques) addResourceErrors(lines)
addImprovementErrors(lines, tryFixUnknownUniques) addImprovementErrors(lines)
addTerrainErrors(lines, tryFixUnknownUniques) addTerrainErrors(lines)
addTechErrors(lines, tryFixUnknownUniques) addTechErrors(lines)
addTechColumnErrorsRulesetInvariant(lines) addTechColumnErrorsRulesetInvariant(lines)
addEraErrors(lines, tryFixUnknownUniques) addEraErrors(lines)
addSpeedErrors(lines) addSpeedErrors(lines)
addPersonalityErrors(lines) addPersonalityErrors(lines)
addBeliefErrors(lines, tryFixUnknownUniques) addBeliefErrors(lines)
addNationErrors(lines, tryFixUnknownUniques) addNationErrors(lines)
addPolicyErrors(lines, tryFixUnknownUniques) addPolicyErrors(lines)
addRuinsErrors(lines, tryFixUnknownUniques) addRuinsErrors(lines)
addPromotionErrors(lines, tryFixUnknownUniques) addPromotionErrors(lines)
addUnitTypeErrors(lines, tryFixUnknownUniques) addUnitTypeErrors(lines)
addVictoryTypeErrors(lines) addVictoryTypeErrors(lines)
addDifficultyErrors(lines) addDifficultyErrors(lines)
addEventErrors(lines, tryFixUnknownUniques) addEventErrors(lines, tryFixUnknownUniques)
@ -220,7 +220,7 @@ class RulesetValidator(val ruleset: Ruleset) {
} }
private fun addModOptionsErrors(lines: RulesetErrorList, tryFixUnknownUniques: Boolean) { private fun addModOptionsErrors(lines: RulesetErrorList) {
// Basic Unique validation (type, target, parameters) should always run. // Basic Unique validation (type, target, parameters) should always run.
// Using reportRulesetSpecificErrors=true as ModOptions never should use Uniques depending on objects from a base ruleset anyway. // Using reportRulesetSpecificErrors=true as ModOptions never should use Uniques depending on objects from a base ruleset anyway.
uniqueValidator.checkUniques(ruleset.modOptions, lines, reportRulesetSpecificErrors = true, tryFixUnknownUniques) uniqueValidator.checkUniques(ruleset.modOptions, lines, reportRulesetSpecificErrors = true, tryFixUnknownUniques)
@ -329,10 +329,7 @@ class RulesetValidator(val ruleset: Ruleset) {
} }
private val unitMovementTypes = UnitMovementType.entries.map { it.name }.toSet() private val unitMovementTypes = UnitMovementType.entries.map { it.name }.toSet()
private fun addUnitTypeErrors( private fun addUnitTypeErrors(lines: RulesetErrorList) {
lines: RulesetErrorList,
tryFixUnknownUniques: Boolean
) {
for (unitType in ruleset.unitTypes.values) { for (unitType in ruleset.unitTypes.values) {
if (unitType.movementType !in unitMovementTypes) if (unitType.movementType !in unitMovementTypes)
lines.add("Unit type ${unitType.name} has an invalid movement type ${unitType.movementType}", sourceObject = unitType) lines.add("Unit type ${unitType.name} has an invalid movement type ${unitType.movementType}", sourceObject = unitType)
@ -340,10 +337,7 @@ class RulesetValidator(val ruleset: Ruleset) {
} }
} }
private fun addPromotionErrors( private fun addPromotionErrors(lines: RulesetErrorList) {
lines: RulesetErrorList,
tryFixUnknownUniques: Boolean
) {
for (promotion in ruleset.unitPromotions.values) { for (promotion in ruleset.unitPromotions.values) {
addPromotionErrorRulesetInvariant(promotion, lines) addPromotionErrorRulesetInvariant(promotion, lines)
@ -365,10 +359,7 @@ class RulesetValidator(val ruleset: Ruleset) {
checkPromotionCircularReferences(lines) checkPromotionCircularReferences(lines)
} }
private fun addRuinsErrors( private fun addRuinsErrors(lines: RulesetErrorList) {
lines: RulesetErrorList,
tryFixUnknownUniques: Boolean
) {
for (reward in ruleset.ruinRewards.values) { for (reward in ruleset.ruinRewards.values) {
@Suppress("KotlinConstantConditions") // data is read from json, so any assumptions may be wrong @Suppress("KotlinConstantConditions") // data is read from json, so any assumptions may be wrong
if (reward.weight < 0) lines.add("${reward.name} has a negative weight, which is not allowed!", sourceObject = reward) if (reward.weight < 0) lines.add("${reward.name} has a negative weight, which is not allowed!", sourceObject = reward)
@ -379,10 +370,7 @@ class RulesetValidator(val ruleset: Ruleset) {
} }
} }
private fun addPolicyErrors( private fun addPolicyErrors(lines: RulesetErrorList) {
lines: RulesetErrorList,
tryFixUnknownUniques: Boolean
) {
for (policy in ruleset.policies.values) { for (policy in ruleset.policies.values) {
for (prereq in policy.requires ?: emptyList()) for (prereq in policy.requires ?: emptyList())
if (!ruleset.policies.containsKey(prereq)) if (!ruleset.policies.containsKey(prereq))
@ -413,10 +401,7 @@ class RulesetValidator(val ruleset: Ruleset) {
} }
private fun addNationErrors( private fun addNationErrors(lines: RulesetErrorList) {
lines: RulesetErrorList,
tryFixUnknownUniques: Boolean
) {
for (nation in ruleset.nations.values) { for (nation in ruleset.nations.values) {
addNationErrorRulesetInvariant(nation, lines) addNationErrorRulesetInvariant(nation, lines)
@ -431,10 +416,7 @@ class RulesetValidator(val ruleset: Ruleset) {
} }
} }
private fun addBeliefErrors( private fun addBeliefErrors(lines: RulesetErrorList) {
lines: RulesetErrorList,
tryFixUnknownUniques: Boolean
) {
for (belief in ruleset.beliefs.values) { for (belief in ruleset.beliefs.values) {
if (belief.type == BeliefType.Any || belief.type == BeliefType.None) if (belief.type == BeliefType.Any || belief.type == BeliefType.None)
lines.add("${belief.name} type is ${belief.type}, which is not allowed!", sourceObject = belief) lines.add("${belief.name} type is ${belief.type}, which is not allowed!", sourceObject = belief)
@ -461,10 +443,7 @@ class RulesetValidator(val ruleset: Ruleset) {
} }
} }
private fun addEraErrors( private fun addEraErrors(lines: RulesetErrorList) {
lines: RulesetErrorList,
tryFixUnknownUniques: Boolean
) {
if (ruleset.eras.isEmpty()) { if (ruleset.eras.isEmpty()) {
lines.add("Eras file is empty! This will likely lead to crashes. Ask the mod maker to update this mod!", sourceObject = null) lines.add("Eras file is empty! This will likely lead to crashes. Ask the mod maker to update this mod!", sourceObject = null)
} }
@ -517,10 +496,7 @@ class RulesetValidator(val ruleset: Ruleset) {
} }
} }
private fun addTechErrors( private fun addTechErrors(lines: RulesetErrorList) {
lines: RulesetErrorList,
tryFixUnknownUniques: Boolean
) {
for (tech in ruleset.technologies.values) { for (tech in ruleset.technologies.values) {
for (prereq in tech.prerequisites) { for (prereq in tech.prerequisites) {
if (!ruleset.technologies.containsKey(prereq)) if (!ruleset.technologies.containsKey(prereq))
@ -542,10 +518,7 @@ class RulesetValidator(val ruleset: Ruleset) {
} }
} }
private fun addTerrainErrors( private fun addTerrainErrors(lines: RulesetErrorList) {
lines: RulesetErrorList,
tryFixUnknownUniques: Boolean
) {
if (ruleset.terrains.values.none { it.type == TerrainType.Land && !it.impassable && !it.hasUnique(UniqueType.NoNaturalGeneration) }) if (ruleset.terrains.values.none { it.type == TerrainType.Land && !it.impassable && !it.hasUnique(UniqueType.NoNaturalGeneration) })
lines.add("No passable land terrains exist!", sourceObject = null) lines.add("No passable land terrains exist!", sourceObject = null)
@ -569,10 +542,7 @@ class RulesetValidator(val ruleset: Ruleset) {
} }
} }
private fun addImprovementErrors( private fun addImprovementErrors(lines: RulesetErrorList) {
lines: RulesetErrorList,
tryFixUnknownUniques: Boolean
) {
for (improvement in ruleset.tileImprovements.values) { for (improvement in ruleset.tileImprovements.values) {
if (improvement.techRequired != null && !ruleset.technologies.containsKey(improvement.techRequired!!)) if (improvement.techRequired != null && !ruleset.technologies.containsKey(improvement.techRequired!!))
lines.add("${improvement.name} requires tech ${improvement.techRequired} which does not exist!", sourceObject = improvement) lines.add("${improvement.name} requires tech ${improvement.techRequired} which does not exist!", sourceObject = improvement)
@ -618,10 +588,7 @@ class RulesetValidator(val ruleset: Ruleset) {
} }
} }
private fun addResourceErrors( private fun addResourceErrors(lines: RulesetErrorList) {
lines: RulesetErrorList,
tryFixUnknownUniques: Boolean
) {
for (resource in ruleset.tileResources.values) { for (resource in ruleset.tileResources.values) {
if (resource.revealedBy != null && !ruleset.technologies.containsKey(resource.revealedBy!!)) if (resource.revealedBy != null && !ruleset.technologies.containsKey(resource.revealedBy!!))
lines.add("${resource.name} revealed by tech ${resource.revealedBy} which does not exist!", sourceObject = resource) lines.add("${resource.name} revealed by tech ${resource.revealedBy} which does not exist!", sourceObject = resource)
@ -649,10 +616,7 @@ class RulesetValidator(val ruleset: Ruleset) {
} }
} }
private fun addBuildingErrors( private fun addBuildingErrors(lines: RulesetErrorList) {
lines: RulesetErrorList,
tryFixUnknownUniques: Boolean
) {
for (building in ruleset.buildings.values) { for (building in ruleset.buildings.values) {
addBuildingErrorRulesetInvariant(building, lines) addBuildingErrorRulesetInvariant(building, lines)
@ -675,7 +639,7 @@ class RulesetValidator(val ruleset: Ruleset) {
} }
} }
private fun addGlobalUniqueErrors(lines: RulesetErrorList, reportRulesetSpecificErrors: Boolean, tryFixUnknownUniques: Boolean) { private fun addGlobalUniqueErrors(lines: RulesetErrorList, reportRulesetSpecificErrors: Boolean) {
uniqueValidator.checkUniques(ruleset.globalUniques, lines, reportRulesetSpecificErrors, tryFixUnknownUniques) uniqueValidator.checkUniques(ruleset.globalUniques, lines, reportRulesetSpecificErrors, tryFixUnknownUniques)
val fakeUniqueContainer = object : IHasUniques{ val fakeUniqueContainer = object : IHasUniques{
@ -700,20 +664,14 @@ class RulesetValidator(val ruleset: Ruleset) {
} }
private fun addUnitErrorsRulesetInvariant( private fun addUnitErrorsRulesetInvariant(lines: RulesetErrorList) {
lines: RulesetErrorList,
tryFixUnknownUniques: Boolean
) {
for (unit in ruleset.units.values) { for (unit in ruleset.units.values) {
checkUnitRulesetInvariant(unit, lines) checkUnitRulesetInvariant(unit, lines)
uniqueValidator.checkUniques(unit, lines, false, tryFixUnknownUniques) uniqueValidator.checkUniques(unit, lines, false, tryFixUnknownUniques)
} }
} }
private fun addUnitErrorsBaseRuleset( private fun addUnitErrorsBaseRuleset(lines: RulesetErrorList) {
lines: RulesetErrorList,
tryFixUnknownUniques: Boolean
) {
if (ruleset.units.values.none { it.isCityFounder() }) if (ruleset.units.values.none { it.isCityFounder() })
lines.add("No city-founding units in ruleset!", sourceObject = null) lines.add("No city-founding units in ruleset!", sourceObject = null)
@ -725,19 +683,13 @@ class RulesetValidator(val ruleset: Ruleset) {
} }
} }
private fun addResourceErrorsRulesetInvariant( private fun addResourceErrorsRulesetInvariant(lines: RulesetErrorList) {
lines: RulesetErrorList,
tryFixUnknownUniques: Boolean
) {
for (resource in ruleset.tileResources.values) { for (resource in ruleset.tileResources.values) {
uniqueValidator.checkUniques(resource, lines, false, tryFixUnknownUniques) uniqueValidator.checkUniques(resource, lines, false, tryFixUnknownUniques)
} }
} }
private fun addPromotionErrorsRulesetInvariant( private fun addPromotionErrorsRulesetInvariant(lines: RulesetErrorList) {
lines: RulesetErrorList,
tryFixUnknownUniques: Boolean
) {
for (promotion in ruleset.unitPromotions.values) { for (promotion in ruleset.unitPromotions.values) {
uniqueValidator.checkUniques(promotion, lines, false, tryFixUnknownUniques) uniqueValidator.checkUniques(promotion, lines, false, tryFixUnknownUniques)
checkContrasts(promotion.innerColorObject ?: PortraitPromotion.defaultInnerColor, checkContrasts(promotion.innerColorObject ?: PortraitPromotion.defaultInnerColor,
@ -755,10 +707,7 @@ class RulesetValidator(val ruleset: Ruleset) {
lines.add("Promotions ${promotion.name} and ${otherPromotion.name} have the same position: ${promotion.row}/${promotion.column}", sourceObject = promotion) lines.add("Promotions ${promotion.name} and ${otherPromotion.name} have the same position: ${promotion.row}/${promotion.column}", sourceObject = promotion)
} }
private fun addNationErrorsRulesetInvariant( private fun addNationErrorsRulesetInvariant(lines: RulesetErrorList) {
lines: RulesetErrorList,
tryFixUnknownUniques: Boolean
) {
for (nation in ruleset.nations.values) { for (nation in ruleset.nations.values) {
addNationErrorRulesetInvariant(nation, lines) addNationErrorRulesetInvariant(nation, lines)
uniqueValidator.checkUniques(nation, lines, false, tryFixUnknownUniques) uniqueValidator.checkUniques(nation, lines, false, tryFixUnknownUniques)
@ -822,10 +771,7 @@ class RulesetValidator(val ruleset: Ruleset) {
throw Exception("Error getting suggested colors") throw Exception("Error getting suggested colors")
} }
private fun addBuildingErrorsRulesetInvariant( private fun addBuildingErrorsRulesetInvariant(lines: RulesetErrorList) {
lines: RulesetErrorList,
tryFixUnknownUniques: Boolean
) {
for (building in ruleset.buildings.values) { for (building in ruleset.buildings.values) {
addBuildingErrorRulesetInvariant(building, lines) addBuildingErrorRulesetInvariant(building, lines)
@ -888,10 +834,7 @@ class RulesetValidator(val ruleset: Ruleset) {
} }
} }
private fun addTechErrorsRulesetInvariant( private fun addTechErrorsRulesetInvariant(lines: RulesetErrorList) {
lines: RulesetErrorList,
tryFixUnknownUniques: Boolean
) {
for (tech in ruleset.technologies.values) { for (tech in ruleset.technologies.values) {
if (tech.row < 1) lines.add("Tech ${tech.name} has a row value below 1: ${tech.row}", sourceObject = tech) if (tech.row < 1) lines.add("Tech ${tech.name} has a row value below 1: ${tech.row}", sourceObject = tech)
uniqueValidator.checkUniques(tech, lines, false, tryFixUnknownUniques) uniqueValidator.checkUniques(tech, lines, false, tryFixUnknownUniques)

View File

@ -49,7 +49,7 @@ internal object DesktopLauncher {
ruleset.load(jsonsFolder) ruleset.load(jsonsFolder)
} }
UniqueAutoUpdater.autoupdateUniques(ruleset) UniqueAutoUpdater.autoupdateUniques(ruleset)
val errors = RulesetValidator(ruleset).getErrorList(true) val errors = RulesetValidator(ruleset, true).getErrorList()
println(errors.getErrorText(true)) println(errors.getErrorText(true))
exitProcess(if (errors.any { it.errorSeverityToReport == RulesetErrorSeverity.Error }) 1 else 0) exitProcess(if (errors.any { it.errorSeverityToReport == RulesetErrorSeverity.Error }) 1 else 0)
} }