mirror of
https://github.com/yairm210/Unciv.git
synced 2025-02-03 12:54:43 +07:00
RulesetValidator reorg - instead of running 2 sets of unique checks for base rulesets and filtering out results from the first to get the second, we now separate and have one function for non-base-rulesets, and one for base rulesets.
This commit is contained in:
parent
fae5e84675
commit
eb3f92c989
@ -383,7 +383,7 @@ class Ruleset {
|
|||||||
Unique(it),
|
Unique(it),
|
||||||
false,
|
false,
|
||||||
cityStateType,
|
cityStateType,
|
||||||
UniqueType.UniqueParameterErrorSeverity.RulesetSpecific
|
true
|
||||||
).isEmpty()
|
).isEmpty()
|
||||||
})
|
})
|
||||||
allyBonusUniques = ArrayList(cityStateType.allyBonusUniques.filter {
|
allyBonusUniques = ArrayList(cityStateType.allyBonusUniques.filter {
|
||||||
@ -391,7 +391,7 @@ class Ruleset {
|
|||||||
Unique(it),
|
Unique(it),
|
||||||
false,
|
false,
|
||||||
cityStateType,
|
cityStateType,
|
||||||
UniqueType.UniqueParameterErrorSeverity.RulesetSpecific
|
true
|
||||||
).isEmpty()
|
).isEmpty()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,7 @@ class Unique(val text: String, val sourceObjectType: UniqueTarget? = null, val s
|
|||||||
val unique = Unique(it)
|
val unique = Unique(it)
|
||||||
val errors = UniqueValidator(ruleset).checkUnique(
|
val errors = UniqueValidator(ruleset).checkUnique(
|
||||||
unique, true, null,
|
unique, true, null,
|
||||||
UniqueType.UniqueParameterErrorSeverity.RulesetSpecific
|
true
|
||||||
)
|
)
|
||||||
errors.isEmpty()
|
errors.isEmpty()
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,13 @@ enum class UniqueParameterType(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Fraction("fraction", docExample = "0.5", "Indicates a fractional number, which can be negative"){
|
||||||
|
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset): UniqueType.UniqueParameterErrorSeverity? {
|
||||||
|
return if (parameterText.toFloatOrNull () == null) UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
|
||||||
|
else null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
RelativeNumber("relativeAmount", "+20", "This indicates a number, usually with a + or - sign, such as `+25` (this kind of parameter is often followed by '%' which is nevertheless not part of the value)") {
|
RelativeNumber("relativeAmount", "+20", "This indicates a number, usually with a + or - sign, such as `+25` (this kind of parameter is often followed by '%' which is nevertheless not part of the value)") {
|
||||||
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
|
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
|
||||||
UniqueType.UniqueParameterErrorSeverity? {
|
UniqueType.UniqueParameterErrorSeverity? {
|
||||||
|
@ -529,7 +529,7 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
|
|||||||
HasQuality("Considered [terrainQuality] when determining start locations", UniqueTarget.Terrain, flags = UniqueFlag.setOfHiddenToUsers),
|
HasQuality("Considered [terrainQuality] when determining start locations", UniqueTarget.Terrain, flags = UniqueFlag.setOfHiddenToUsers),
|
||||||
|
|
||||||
NoNaturalGeneration("Doesn't generate naturally", UniqueTarget.Terrain, UniqueTarget.Resource, flags = UniqueFlag.setOfHiddenToUsers),
|
NoNaturalGeneration("Doesn't generate naturally", UniqueTarget.Terrain, UniqueTarget.Resource, flags = UniqueFlag.setOfHiddenToUsers),
|
||||||
TileGenerationConditions("Occurs at temperature between [amount] and [amount] and humidity between [amount] and [amount]", UniqueTarget.Terrain, UniqueTarget.Resource, flags = UniqueFlag.setOfHiddenToUsers),
|
TileGenerationConditions("Occurs at temperature between [fraction] and [amount] and humidity between [amount] and [amount]", UniqueTarget.Terrain, UniqueTarget.Resource, flags = UniqueFlag.setOfHiddenToUsers),
|
||||||
OccursInChains("Occurs in chains at high elevations", UniqueTarget.Terrain, flags = UniqueFlag.setOfHiddenToUsers),
|
OccursInChains("Occurs in chains at high elevations", UniqueTarget.Terrain, flags = UniqueFlag.setOfHiddenToUsers),
|
||||||
OccursInGroups("Occurs in groups around high elevations", UniqueTarget.Terrain, flags = UniqueFlag.setOfHiddenToUsers),
|
OccursInGroups("Occurs in groups around high elevations", UniqueTarget.Terrain, flags = UniqueFlag.setOfHiddenToUsers),
|
||||||
MajorStrategicFrequency("Every [amount] tiles with this terrain will receive a major deposit of a strategic resource.", UniqueTarget.Terrain, flags = UniqueFlag.setOfHiddenToUsers),
|
MajorStrategicFrequency("Every [amount] tiles with this terrain will receive a major deposit of a strategic resource.", UniqueTarget.Terrain, flags = UniqueFlag.setOfHiddenToUsers),
|
||||||
@ -1174,8 +1174,7 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
|
|||||||
/** This is a warning, regardless of what ruleset we're in.
|
/** This is a warning, regardless of what ruleset we're in.
|
||||||
* This is for filters that can also potentially accept free text, like UnitFilter and TileFilter */
|
* This is for filters that can also potentially accept free text, like UnitFilter and TileFilter */
|
||||||
WarningOnly {
|
WarningOnly {
|
||||||
override fun getRulesetErrorSeverity(severityToReport: UniqueParameterErrorSeverity) =
|
override fun getRulesetErrorSeverity() = RulesetErrorSeverity.WarningOptionsOnly
|
||||||
RulesetErrorSeverity.WarningOptionsOnly
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/** An error, but only because of other information in the current ruleset.
|
/** An error, but only because of other information in the current ruleset.
|
||||||
@ -1184,15 +1183,13 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
|
|||||||
RulesetSpecific {
|
RulesetSpecific {
|
||||||
// Report Warning on the first pass of RulesetValidator only, where mods are checked standalone
|
// Report Warning on the first pass of RulesetValidator only, where mods are checked standalone
|
||||||
// but upgrade to error when the econd pass asks, which runs only for combined or base rulesets.
|
// but upgrade to error when the econd pass asks, which runs only for combined or base rulesets.
|
||||||
override fun getRulesetErrorSeverity(severityToReport: UniqueParameterErrorSeverity) =
|
override fun getRulesetErrorSeverity() = RulesetErrorSeverity.Warning
|
||||||
RulesetErrorSeverity.Warning
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/** An error, regardless of the ruleset we're in.
|
/** An error, regardless of the ruleset we're in.
|
||||||
* This is a problem like "numbers don't parse", "stat isn't stat", "city filter not applicable" */
|
* This is a problem like "numbers don't parse", "stat isn't stat", "city filter not applicable" */
|
||||||
RulesetInvariant {
|
RulesetInvariant {
|
||||||
override fun getRulesetErrorSeverity(severityToReport: UniqueParameterErrorSeverity) =
|
override fun getRulesetErrorSeverity() = RulesetErrorSeverity.Error
|
||||||
RulesetErrorSeverity.Error
|
|
||||||
},
|
},
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -1201,7 +1198,7 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
|
|||||||
* first pass that also runs for extension mods without a base mixed in; the complex check
|
* first pass that also runs for extension mods without a base mixed in; the complex check
|
||||||
* runs with [severityToReport]==[RulesetSpecific].
|
* runs with [severityToReport]==[RulesetSpecific].
|
||||||
*/
|
*/
|
||||||
abstract fun getRulesetErrorSeverity(severityToReport: UniqueParameterErrorSeverity): RulesetErrorSeverity
|
abstract fun getRulesetErrorSeverity(): RulesetErrorSeverity
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getDeprecationAnnotation(): Deprecated? = declaringJavaClass.getField(name)
|
fun getDeprecationAnnotation(): Deprecated? = declaringJavaClass.getField(name)
|
||||||
|
@ -8,8 +8,10 @@ import com.unciv.json.fromJsonFile
|
|||||||
import com.unciv.json.json
|
import com.unciv.json.json
|
||||||
import com.unciv.logic.map.tile.RoadStatus
|
import com.unciv.logic.map.tile.RoadStatus
|
||||||
import com.unciv.models.metadata.BaseRuleset
|
import com.unciv.models.metadata.BaseRuleset
|
||||||
|
import com.unciv.models.ruleset.Building
|
||||||
import com.unciv.models.ruleset.Ruleset
|
import com.unciv.models.ruleset.Ruleset
|
||||||
import com.unciv.models.ruleset.RulesetCache
|
import com.unciv.models.ruleset.RulesetCache
|
||||||
|
import com.unciv.models.ruleset.nation.Nation
|
||||||
import com.unciv.models.ruleset.nation.getContrastRatio
|
import com.unciv.models.ruleset.nation.getContrastRatio
|
||||||
import com.unciv.models.ruleset.nation.getRelativeLuminance
|
import com.unciv.models.ruleset.nation.getRelativeLuminance
|
||||||
import com.unciv.models.ruleset.tile.TerrainType
|
import com.unciv.models.ruleset.tile.TerrainType
|
||||||
@ -23,66 +25,75 @@ import com.unciv.models.tilesets.TileSetConfig
|
|||||||
|
|
||||||
class RulesetValidator(val ruleset: Ruleset) {
|
class RulesetValidator(val ruleset: Ruleset) {
|
||||||
|
|
||||||
val uniqueValidator = UniqueValidator(ruleset)
|
private val uniqueValidator = UniqueValidator(ruleset)
|
||||||
|
|
||||||
fun getErrorList(tryFixUnknownUniques: Boolean = false): RulesetErrorList {
|
fun getErrorList(tryFixUnknownUniques: Boolean = false): RulesetErrorList {
|
||||||
|
// When no base ruleset is loaded - references cannot be checked
|
||||||
|
if (!ruleset.modOptions.isBaseRuleset) return getNonBaseRulesetErrorList(tryFixUnknownUniques)
|
||||||
|
|
||||||
|
return getBaseRulesetErrorList(tryFixUnknownUniques)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getNonBaseRulesetErrorList(tryFixUnknownUniques: Boolean): RulesetErrorList {
|
||||||
val lines = RulesetErrorList()
|
val lines = RulesetErrorList()
|
||||||
|
|
||||||
/********************** Ruleset Invariant Part **********************/
|
|
||||||
// Checks for ALL MODS - only those that can succeed without loading a base 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
|
||||||
|
uniqueValidator.checkUniques(ruleset.globalUniques, lines, false, tryFixUnknownUniques)
|
||||||
val rulesetInvariant = UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
|
addUnitErrorsRulesetInvariant(lines, tryFixUnknownUniques)
|
||||||
val rulesetSpecific = UniqueType.UniqueParameterErrorSeverity.RulesetSpecific
|
addTechErrorsRulesetInvariant(lines, tryFixUnknownUniques)
|
||||||
|
|
||||||
uniqueValidator.checkUniques(ruleset.globalUniques, lines, rulesetInvariant, tryFixUnknownUniques)
|
|
||||||
addUnitErrorsRulesetInvariant(lines, rulesetInvariant, tryFixUnknownUniques)
|
|
||||||
addTechErrorsRulesetInvariant(lines, rulesetInvariant, tryFixUnknownUniques)
|
|
||||||
addTechColumnErrorsRulesetInvariant(lines)
|
addTechColumnErrorsRulesetInvariant(lines)
|
||||||
addBuildingErrorsRulesetInvariant(lines, rulesetInvariant, tryFixUnknownUniques)
|
addBuildingErrorsRulesetInvariant(lines, tryFixUnknownUniques)
|
||||||
addNationErrorsRulesetInvariant(lines, rulesetInvariant, tryFixUnknownUniques)
|
addNationErrorsRulesetInvariant(lines, tryFixUnknownUniques)
|
||||||
addPromotionErrorsRulesetInvariant(lines, rulesetInvariant, tryFixUnknownUniques)
|
addPromotionErrorsRulesetInvariant(lines, tryFixUnknownUniques)
|
||||||
addResourceErrorsRulesetInvariant(lines, rulesetInvariant, tryFixUnknownUniques)
|
addResourceErrorsRulesetInvariant(lines, tryFixUnknownUniques)
|
||||||
|
|
||||||
/********************** Tileset tests **********************/
|
/********************** **********************/
|
||||||
// e.g. json configs complete and parseable
|
// e.g. json configs complete and parseable
|
||||||
|
// Check for mod or Civ_V_GnK to avoid running the same test twice (~200ms for the builtin assets)
|
||||||
|
if (ruleset.folderLocation != null) {
|
||||||
|
checkTilesetSanity(lines)
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun getBaseRulesetErrorList(tryFixUnknownUniques: Boolean): RulesetErrorList{
|
||||||
|
|
||||||
|
val lines = RulesetErrorList()
|
||||||
|
|
||||||
|
uniqueValidator.checkUniques(ruleset.globalUniques, lines, true, tryFixUnknownUniques)
|
||||||
|
|
||||||
|
addUnitErrorsBaseRuleset(lines, tryFixUnknownUniques)
|
||||||
|
addBuildingErrors(lines, tryFixUnknownUniques)
|
||||||
|
addSpecialistErrors(lines)
|
||||||
|
addResourceErrors(lines, tryFixUnknownUniques)
|
||||||
|
addImprovementErrors(lines, tryFixUnknownUniques)
|
||||||
|
addTerrainErrors(lines, tryFixUnknownUniques)
|
||||||
|
addTechErrors(lines, tryFixUnknownUniques)
|
||||||
|
addTechColumnErrorsRulesetInvariant(lines)
|
||||||
|
addEraErrors(lines, tryFixUnknownUniques)
|
||||||
|
addSpeedErrors(lines)
|
||||||
|
addBeliefErrors(lines, tryFixUnknownUniques)
|
||||||
|
addNationErrors(lines, tryFixUnknownUniques)
|
||||||
|
addPolicyErrors(lines, tryFixUnknownUniques)
|
||||||
|
addRuinsErrors(lines, tryFixUnknownUniques)
|
||||||
|
addPromotionErrors(lines, tryFixUnknownUniques)
|
||||||
|
addUnitTypeErrors(lines, tryFixUnknownUniques)
|
||||||
|
addVictoryTypeErrors(lines)
|
||||||
|
addDifficutlyErrors(lines)
|
||||||
|
addCityStateTypeErrors(tryFixUnknownUniques, lines)
|
||||||
|
|
||||||
// Check for mod or Civ_V_GnK to avoid running the same test twice (~200ms for the builtin assets)
|
// Check for mod or Civ_V_GnK to avoid running the same test twice (~200ms for the builtin assets)
|
||||||
if (ruleset.folderLocation != null || ruleset.name == BaseRuleset.Civ_V_GnK.fullName) {
|
if (ruleset.folderLocation != null || ruleset.name == BaseRuleset.Civ_V_GnK.fullName) {
|
||||||
checkTilesetSanity(lines)
|
checkTilesetSanity(lines)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quit here when no base ruleset is loaded - references cannot be checked
|
|
||||||
if (!ruleset.modOptions.isBaseRuleset) return lines
|
|
||||||
|
|
||||||
/********************** Ruleset Specific Part **********************/
|
|
||||||
|
|
||||||
uniqueValidator.checkUniques(ruleset.globalUniques, lines, rulesetSpecific, tryFixUnknownUniques)
|
|
||||||
|
|
||||||
addUnitErrors(lines, rulesetSpecific, tryFixUnknownUniques)
|
|
||||||
addBuildingErrors(lines, rulesetSpecific, tryFixUnknownUniques)
|
|
||||||
addSpecialistErrors(lines)
|
|
||||||
addResourceErrors(lines, rulesetSpecific, tryFixUnknownUniques)
|
|
||||||
addImprovementErrors(lines, rulesetSpecific, tryFixUnknownUniques)
|
|
||||||
addTerrainErrors(lines, rulesetSpecific, tryFixUnknownUniques)
|
|
||||||
addTechErrors(lines, rulesetSpecific, tryFixUnknownUniques)
|
|
||||||
addEraErrors(lines, rulesetSpecific, tryFixUnknownUniques)
|
|
||||||
addSpeedErrors(lines)
|
|
||||||
addBeliefErrors(lines, rulesetSpecific, tryFixUnknownUniques)
|
|
||||||
addNationErrors(lines, rulesetSpecific, tryFixUnknownUniques)
|
|
||||||
addPolicyErrors(lines, rulesetSpecific, tryFixUnknownUniques)
|
|
||||||
addRuinsErrors(lines, rulesetSpecific, tryFixUnknownUniques)
|
|
||||||
addPromotionErrors(lines, rulesetSpecific, tryFixUnknownUniques)
|
|
||||||
addUnitTypeErrors(lines, rulesetSpecific, tryFixUnknownUniques)
|
|
||||||
addVictoryTypeErrors(lines)
|
|
||||||
addDifficutlyErrors(lines)
|
|
||||||
addCityStateTypeErrors(tryFixUnknownUniques, rulesetSpecific, lines)
|
|
||||||
|
|
||||||
return lines
|
return lines
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addCityStateTypeErrors(
|
private fun addCityStateTypeErrors(
|
||||||
tryFixUnknownUniques: Boolean,
|
tryFixUnknownUniques: Boolean,
|
||||||
rulesetSpecific: UniqueType.UniqueParameterErrorSeverity,
|
|
||||||
lines: RulesetErrorList
|
lines: RulesetErrorList
|
||||||
) {
|
) {
|
||||||
for (cityStateType in ruleset.cityStateTypes.values) {
|
for (cityStateType in ruleset.cityStateTypes.values) {
|
||||||
@ -91,7 +102,7 @@ class RulesetValidator(val ruleset: Ruleset) {
|
|||||||
unique,
|
unique,
|
||||||
tryFixUnknownUniques,
|
tryFixUnknownUniques,
|
||||||
cityStateType,
|
cityStateType,
|
||||||
rulesetSpecific
|
true
|
||||||
)
|
)
|
||||||
lines.addAll(errors)
|
lines.addAll(errors)
|
||||||
}
|
}
|
||||||
@ -131,20 +142,20 @@ class RulesetValidator(val ruleset: Ruleset) {
|
|||||||
|
|
||||||
private fun addUnitTypeErrors(
|
private fun addUnitTypeErrors(
|
||||||
lines: RulesetErrorList,
|
lines: RulesetErrorList,
|
||||||
rulesetSpecific: UniqueType.UniqueParameterErrorSeverity,
|
|
||||||
tryFixUnknownUniques: Boolean
|
tryFixUnknownUniques: Boolean
|
||||||
) {
|
) {
|
||||||
for (unitType in ruleset.unitTypes.values) {
|
for (unitType in ruleset.unitTypes.values) {
|
||||||
uniqueValidator.checkUniques(unitType, lines, rulesetSpecific, tryFixUnknownUniques)
|
uniqueValidator.checkUniques(unitType, lines, true, tryFixUnknownUniques)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addPromotionErrors(
|
private fun addPromotionErrors(
|
||||||
lines: RulesetErrorList,
|
lines: RulesetErrorList,
|
||||||
rulesetSpecific: UniqueType.UniqueParameterErrorSeverity,
|
|
||||||
tryFixUnknownUniques: Boolean
|
tryFixUnknownUniques: Boolean
|
||||||
) {
|
) {
|
||||||
for (promotion in ruleset.unitPromotions.values) {
|
for (promotion in ruleset.unitPromotions.values) {
|
||||||
|
addPromotionErrorRulesetInvariant(promotion, lines)
|
||||||
|
|
||||||
// These are warning as of 3.17.5 to not break existing mods and give them time to correct, should be upgraded to error in the future
|
// These are warning as of 3.17.5 to not break existing mods and give them time to correct, should be upgraded to error in the future
|
||||||
for (prereq in promotion.prerequisites)
|
for (prereq in promotion.prerequisites)
|
||||||
if (!ruleset.unitPromotions.containsKey(prereq))
|
if (!ruleset.unitPromotions.containsKey(prereq))
|
||||||
@ -158,27 +169,25 @@ class RulesetValidator(val ruleset: Ruleset) {
|
|||||||
RulesetErrorSeverity.Warning
|
RulesetErrorSeverity.Warning
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
uniqueValidator.checkUniques(promotion, lines, rulesetSpecific, tryFixUnknownUniques)
|
uniqueValidator.checkUniques(promotion, lines, true, tryFixUnknownUniques)
|
||||||
}
|
}
|
||||||
checkPromotionCircularReferences(lines)
|
checkPromotionCircularReferences(lines)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addRuinsErrors(
|
private fun addRuinsErrors(
|
||||||
lines: RulesetErrorList,
|
lines: RulesetErrorList,
|
||||||
rulesetSpecific: UniqueType.UniqueParameterErrorSeverity,
|
|
||||||
tryFixUnknownUniques: Boolean
|
tryFixUnknownUniques: Boolean
|
||||||
) {
|
) {
|
||||||
for (reward in ruleset.ruinRewards.values) {
|
for (reward in ruleset.ruinRewards.values) {
|
||||||
for (difficulty in reward.excludedDifficulties)
|
for (difficulty in reward.excludedDifficulties)
|
||||||
if (!ruleset.difficulties.containsKey(difficulty))
|
if (!ruleset.difficulties.containsKey(difficulty))
|
||||||
lines += "${reward.name} references difficulty ${difficulty}, which does not exist!"
|
lines += "${reward.name} references difficulty ${difficulty}, which does not exist!"
|
||||||
uniqueValidator.checkUniques(reward, lines, rulesetSpecific, tryFixUnknownUniques)
|
uniqueValidator.checkUniques(reward, lines, true, tryFixUnknownUniques)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addPolicyErrors(
|
private fun addPolicyErrors(
|
||||||
lines: RulesetErrorList,
|
lines: RulesetErrorList,
|
||||||
rulesetSpecific: UniqueType.UniqueParameterErrorSeverity,
|
|
||||||
tryFixUnknownUniques: Boolean
|
tryFixUnknownUniques: Boolean
|
||||||
) {
|
) {
|
||||||
for (policy in ruleset.policies.values) {
|
for (policy in ruleset.policies.values) {
|
||||||
@ -186,7 +195,7 @@ class RulesetValidator(val ruleset: Ruleset) {
|
|||||||
for (prereq in policy.requires!!)
|
for (prereq in policy.requires!!)
|
||||||
if (!ruleset.policies.containsKey(prereq))
|
if (!ruleset.policies.containsKey(prereq))
|
||||||
lines += "${policy.name} requires policy $prereq which does not exist!"
|
lines += "${policy.name} requires policy $prereq which does not exist!"
|
||||||
uniqueValidator.checkUniques(policy, lines, rulesetSpecific, tryFixUnknownUniques)
|
uniqueValidator.checkUniques(policy, lines, true, tryFixUnknownUniques)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (branch in ruleset.policyBranches.values)
|
for (branch in ruleset.policyBranches.values)
|
||||||
@ -202,11 +211,12 @@ class RulesetValidator(val ruleset: Ruleset) {
|
|||||||
|
|
||||||
private fun addNationErrors(
|
private fun addNationErrors(
|
||||||
lines: RulesetErrorList,
|
lines: RulesetErrorList,
|
||||||
rulesetSpecific: UniqueType.UniqueParameterErrorSeverity,
|
|
||||||
tryFixUnknownUniques: Boolean
|
tryFixUnknownUniques: Boolean
|
||||||
) {
|
) {
|
||||||
for (nation in ruleset.nations.values) {
|
for (nation in ruleset.nations.values) {
|
||||||
uniqueValidator.checkUniques(nation, lines, rulesetSpecific, tryFixUnknownUniques)
|
addNationErrorRulesetInvariant(nation, lines)
|
||||||
|
|
||||||
|
uniqueValidator.checkUniques(nation, lines, true, tryFixUnknownUniques)
|
||||||
|
|
||||||
if (nation.cityStateType != null && nation.cityStateType !in ruleset.cityStateTypes)
|
if (nation.cityStateType != null && nation.cityStateType !in ruleset.cityStateTypes)
|
||||||
lines += "${nation.name} is of city-state type ${nation.cityStateType} which does not exist!"
|
lines += "${nation.name} is of city-state type ${nation.cityStateType} which does not exist!"
|
||||||
@ -217,11 +227,10 @@ class RulesetValidator(val ruleset: Ruleset) {
|
|||||||
|
|
||||||
private fun addBeliefErrors(
|
private fun addBeliefErrors(
|
||||||
lines: RulesetErrorList,
|
lines: RulesetErrorList,
|
||||||
rulesetSpecific: UniqueType.UniqueParameterErrorSeverity,
|
|
||||||
tryFixUnknownUniques: Boolean
|
tryFixUnknownUniques: Boolean
|
||||||
) {
|
) {
|
||||||
for (belief in ruleset.beliefs.values) {
|
for (belief in ruleset.beliefs.values) {
|
||||||
uniqueValidator.checkUniques(belief, lines, rulesetSpecific, tryFixUnknownUniques)
|
uniqueValidator.checkUniques(belief, lines, true, tryFixUnknownUniques)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,7 +245,6 @@ class RulesetValidator(val ruleset: Ruleset) {
|
|||||||
|
|
||||||
private fun addEraErrors(
|
private fun addEraErrors(
|
||||||
lines: RulesetErrorList,
|
lines: RulesetErrorList,
|
||||||
rulesetSpecific: UniqueType.UniqueParameterErrorSeverity,
|
|
||||||
tryFixUnknownUniques: Boolean
|
tryFixUnknownUniques: Boolean
|
||||||
) {
|
) {
|
||||||
if (ruleset.eras.isEmpty()) {
|
if (ruleset.eras.isEmpty()) {
|
||||||
@ -288,13 +296,12 @@ class RulesetValidator(val ruleset: Ruleset) {
|
|||||||
RulesetErrorSeverity.WarningOptionsOnly
|
RulesetErrorSeverity.WarningOptionsOnly
|
||||||
)
|
)
|
||||||
|
|
||||||
uniqueValidator.checkUniques(era, lines, rulesetSpecific, tryFixUnknownUniques)
|
uniqueValidator.checkUniques(era, lines, true, tryFixUnknownUniques)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addTechErrors(
|
private fun addTechErrors(
|
||||||
lines: RulesetErrorList,
|
lines: RulesetErrorList,
|
||||||
rulesetSpecific: UniqueType.UniqueParameterErrorSeverity,
|
|
||||||
tryFixUnknownUniques: Boolean
|
tryFixUnknownUniques: Boolean
|
||||||
) {
|
) {
|
||||||
for (tech in ruleset.technologies.values) {
|
for (tech in ruleset.technologies.values) {
|
||||||
@ -316,13 +323,12 @@ class RulesetValidator(val ruleset: Ruleset) {
|
|||||||
}
|
}
|
||||||
if (tech.era() !in ruleset.eras)
|
if (tech.era() !in ruleset.eras)
|
||||||
lines += "Unknown era ${tech.era()} referenced in column of tech ${tech.name}"
|
lines += "Unknown era ${tech.era()} referenced in column of tech ${tech.name}"
|
||||||
uniqueValidator.checkUniques(tech, lines, rulesetSpecific, tryFixUnknownUniques)
|
uniqueValidator.checkUniques(tech, lines, true, tryFixUnknownUniques)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addTerrainErrors(
|
private fun addTerrainErrors(
|
||||||
lines: RulesetErrorList,
|
lines: RulesetErrorList,
|
||||||
rulesetSpecific: UniqueType.UniqueParameterErrorSeverity,
|
|
||||||
tryFixUnknownUniques: Boolean
|
tryFixUnknownUniques: Boolean
|
||||||
) {
|
) {
|
||||||
if (ruleset.terrains.values.none { it.type == TerrainType.Land && !it.impassable })
|
if (ruleset.terrains.values.none { it.type == TerrainType.Land && !it.impassable })
|
||||||
@ -345,13 +351,12 @@ class RulesetValidator(val ruleset: Ruleset) {
|
|||||||
// See https://github.com/hackedpassword/Z2/blob/main/HybridTileTech.md for a clever exploit
|
// See https://github.com/hackedpassword/Z2/blob/main/HybridTileTech.md for a clever exploit
|
||||||
lines.add("${terrain.name} turns into terrain ${terrain.turnsInto} which is not a base terrain!", RulesetErrorSeverity.Warning)
|
lines.add("${terrain.name} turns into terrain ${terrain.turnsInto} which is not a base terrain!", RulesetErrorSeverity.Warning)
|
||||||
}
|
}
|
||||||
uniqueValidator.checkUniques(terrain, lines, rulesetSpecific, tryFixUnknownUniques)
|
uniqueValidator.checkUniques(terrain, lines, true, tryFixUnknownUniques)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addImprovementErrors(
|
private fun addImprovementErrors(
|
||||||
lines: RulesetErrorList,
|
lines: RulesetErrorList,
|
||||||
rulesetSpecific: UniqueType.UniqueParameterErrorSeverity,
|
|
||||||
tryFixUnknownUniques: Boolean
|
tryFixUnknownUniques: Boolean
|
||||||
) {
|
) {
|
||||||
for (improvement in ruleset.tileImprovements.values) {
|
for (improvement in ruleset.tileImprovements.values) {
|
||||||
@ -400,13 +405,12 @@ class RulesetValidator(val ruleset: Ruleset) {
|
|||||||
RulesetErrorSeverity.Warning
|
RulesetErrorSeverity.Warning
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
uniqueValidator.checkUniques(improvement, lines, rulesetSpecific, tryFixUnknownUniques)
|
uniqueValidator.checkUniques(improvement, lines, true, tryFixUnknownUniques)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addResourceErrors(
|
private fun addResourceErrors(
|
||||||
lines: RulesetErrorList,
|
lines: RulesetErrorList,
|
||||||
rulesetSpecific: UniqueType.UniqueParameterErrorSeverity,
|
|
||||||
tryFixUnknownUniques: Boolean
|
tryFixUnknownUniques: Boolean
|
||||||
) {
|
) {
|
||||||
for (resource in ruleset.tileResources.values) {
|
for (resource in ruleset.tileResources.values) {
|
||||||
@ -420,7 +424,7 @@ class RulesetValidator(val ruleset: Ruleset) {
|
|||||||
for (terrain in resource.terrainsCanBeFoundOn)
|
for (terrain in resource.terrainsCanBeFoundOn)
|
||||||
if (!ruleset.terrains.containsKey(terrain))
|
if (!ruleset.terrains.containsKey(terrain))
|
||||||
lines += "${resource.name} can be found on terrain $terrain which does not exist!"
|
lines += "${resource.name} can be found on terrain $terrain which does not exist!"
|
||||||
uniqueValidator.checkUniques(resource, lines, rulesetSpecific, tryFixUnknownUniques)
|
uniqueValidator.checkUniques(resource, lines, true, tryFixUnknownUniques)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,13 +441,13 @@ class RulesetValidator(val ruleset: Ruleset) {
|
|||||||
|
|
||||||
private fun addBuildingErrors(
|
private fun addBuildingErrors(
|
||||||
lines: RulesetErrorList,
|
lines: RulesetErrorList,
|
||||||
rulesetSpecific: UniqueType.UniqueParameterErrorSeverity,
|
|
||||||
tryFixUnknownUniques: Boolean
|
tryFixUnknownUniques: Boolean
|
||||||
) {
|
) {
|
||||||
for (building in ruleset.buildings.values) {
|
for (building in ruleset.buildings.values) {
|
||||||
|
addBuildingErrorRulesetInvariant(building, lines)
|
||||||
|
|
||||||
if (building.requiredTech != null && !ruleset.technologies.containsKey(building.requiredTech!!))
|
if (building.requiredTech != null && !ruleset.technologies.containsKey(building.requiredTech!!))
|
||||||
lines += "${building.name} requires tech ${building.requiredTech} which does not exist!"
|
lines += "${building.name} requires tech ${building.requiredTech} which does not exist!"
|
||||||
|
|
||||||
for (specialistName in building.specialistSlots.keys)
|
for (specialistName in building.specialistSlots.keys)
|
||||||
if (!ruleset.specialists.containsKey(specialistName))
|
if (!ruleset.specialists.containsKey(specialistName))
|
||||||
lines += "${building.name} provides specialist $specialistName which does not exist!"
|
lines += "${building.name} provides specialist $specialistName which does not exist!"
|
||||||
@ -454,127 +458,147 @@ class RulesetValidator(val ruleset: Ruleset) {
|
|||||||
lines += "${building.name} replaces ${building.replaces} which does not exist!"
|
lines += "${building.name} replaces ${building.replaces} which does not exist!"
|
||||||
if (building.requiredBuilding != null && !ruleset.buildings.containsKey(building.requiredBuilding!!))
|
if (building.requiredBuilding != null && !ruleset.buildings.containsKey(building.requiredBuilding!!))
|
||||||
lines += "${building.name} requires ${building.requiredBuilding} which does not exist!"
|
lines += "${building.name} requires ${building.requiredBuilding} which does not exist!"
|
||||||
uniqueValidator.checkUniques(building, lines, rulesetSpecific, tryFixUnknownUniques)
|
uniqueValidator.checkUniques(building, lines, true, tryFixUnknownUniques)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addUnitErrors(
|
|
||||||
|
private fun addUnitErrorsRulesetInvariant(
|
||||||
|
lines: RulesetErrorList,
|
||||||
|
tryFixUnknownUniques: Boolean
|
||||||
|
) {
|
||||||
|
for (unit in ruleset.units.values) {
|
||||||
|
checkUnitRulesetInvariant(unit, lines)
|
||||||
|
uniqueValidator.checkUniques(unit, lines, false, tryFixUnknownUniques)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addUnitErrorsBaseRuleset(
|
||||||
lines: RulesetErrorList,
|
lines: RulesetErrorList,
|
||||||
rulesetSpecific: UniqueType.UniqueParameterErrorSeverity,
|
|
||||||
tryFixUnknownUniques: Boolean
|
tryFixUnknownUniques: Boolean
|
||||||
) {
|
) {
|
||||||
if (ruleset.units.values.none { it.isCityFounder() })
|
if (ruleset.units.values.none { it.isCityFounder() })
|
||||||
lines += "No city-founding units in ruleset!"
|
lines += "No city-founding units in ruleset!"
|
||||||
|
|
||||||
for (unit in ruleset.units.values) {
|
for (unit in ruleset.units.values) {
|
||||||
|
checkUnitRulesetInvariant(unit, lines)
|
||||||
checkUnitRulesetSpecific(unit, lines)
|
checkUnitRulesetSpecific(unit, lines)
|
||||||
uniqueValidator.checkUniques(unit, lines, rulesetSpecific, tryFixUnknownUniques)
|
uniqueValidator.checkUniques(unit, lines, false, tryFixUnknownUniques)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addResourceErrorsRulesetInvariant(
|
private fun addResourceErrorsRulesetInvariant(
|
||||||
lines: RulesetErrorList,
|
lines: RulesetErrorList,
|
||||||
rulesetInvariant: UniqueType.UniqueParameterErrorSeverity,
|
|
||||||
tryFixUnknownUniques: Boolean
|
tryFixUnknownUniques: Boolean
|
||||||
) {
|
) {
|
||||||
for (resource in ruleset.tileResources.values) {
|
for (resource in ruleset.tileResources.values) {
|
||||||
uniqueValidator.checkUniques(resource, lines, rulesetInvariant, tryFixUnknownUniques)
|
uniqueValidator.checkUniques(resource, lines, false, tryFixUnknownUniques)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addPromotionErrorsRulesetInvariant(
|
private fun addPromotionErrorsRulesetInvariant(
|
||||||
lines: RulesetErrorList,
|
lines: RulesetErrorList,
|
||||||
rulesetInvariant: UniqueType.UniqueParameterErrorSeverity,
|
|
||||||
tryFixUnknownUniques: Boolean
|
tryFixUnknownUniques: Boolean
|
||||||
) {
|
) {
|
||||||
for (promotion in ruleset.unitPromotions.values) {
|
for (promotion in ruleset.unitPromotions.values) {
|
||||||
uniqueValidator.checkUniques(promotion, lines, rulesetInvariant, tryFixUnknownUniques)
|
uniqueValidator.checkUniques(promotion, lines, false, tryFixUnknownUniques)
|
||||||
if (promotion.row < -1) lines += "Promotion ${promotion.name} has invalid row value: ${promotion.row}"
|
|
||||||
if (promotion.column < 0) lines += "Promotion ${promotion.name} has invalid column value: ${promotion.column}"
|
addPromotionErrorRulesetInvariant(promotion, lines)
|
||||||
if (promotion.row == -1) continue
|
|
||||||
for (otherPromotion in ruleset.unitPromotions.values)
|
|
||||||
if (promotion != otherPromotion && promotion.column == otherPromotion.column && promotion.row == otherPromotion.row)
|
|
||||||
lines += "Promotions ${promotion.name} and ${otherPromotion.name} have the same position: ${promotion.row}/${promotion.column}"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun addPromotionErrorRulesetInvariant(promotion: Promotion, lines: RulesetErrorList) {
|
||||||
|
if (promotion.row < -1) lines += "Promotion ${promotion.name} has invalid row value: ${promotion.row}"
|
||||||
|
if (promotion.column < 0) lines += "Promotion ${promotion.name} has invalid column value: ${promotion.column}"
|
||||||
|
if (promotion.row == -1) return
|
||||||
|
for (otherPromotion in ruleset.unitPromotions.values)
|
||||||
|
if (promotion != otherPromotion && promotion.column == otherPromotion.column && promotion.row == otherPromotion.row)
|
||||||
|
lines += "Promotions ${promotion.name} and ${otherPromotion.name} have the same position: ${promotion.row}/${promotion.column}"
|
||||||
|
}
|
||||||
|
|
||||||
private fun addNationErrorsRulesetInvariant(
|
private fun addNationErrorsRulesetInvariant(
|
||||||
lines: RulesetErrorList,
|
lines: RulesetErrorList,
|
||||||
rulesetInvariant: UniqueType.UniqueParameterErrorSeverity,
|
|
||||||
tryFixUnknownUniques: Boolean
|
tryFixUnknownUniques: Boolean
|
||||||
) {
|
) {
|
||||||
for (nation in ruleset.nations.values) {
|
for (nation in ruleset.nations.values) {
|
||||||
if (nation.cities.isEmpty() && !nation.isSpectator && !nation.isBarbarian) {
|
addNationErrorRulesetInvariant(nation, lines)
|
||||||
lines += "${nation.name} can settle cities, but has no city names!"
|
|
||||||
|
uniqueValidator.checkUniques(nation, lines, false, tryFixUnknownUniques)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addNationErrorRulesetInvariant(nation: Nation, lines: RulesetErrorList) {
|
||||||
|
if (nation.cities.isEmpty() && !nation.isSpectator && !nation.isBarbarian) {
|
||||||
|
lines += "${nation.name} can settle cities, but has no city names!"
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/WCAG20/#visual-audio-contrast-contrast
|
||||||
|
val constrastRatio = nation.getContrastRatio()
|
||||||
|
if (constrastRatio < 3) {
|
||||||
|
val innerColorLuminance = getRelativeLuminance(nation.getInnerColor())
|
||||||
|
val outerColorLuminance = getRelativeLuminance(nation.getOuterColor())
|
||||||
|
|
||||||
|
val innerLerpColor: Color
|
||||||
|
val outerLerpColor: Color
|
||||||
|
|
||||||
|
if (innerColorLuminance > outerColorLuminance) { // inner is brighter
|
||||||
|
innerLerpColor = Color.WHITE
|
||||||
|
outerLerpColor = Color.BLACK
|
||||||
|
} else {
|
||||||
|
innerLerpColor = Color.BLACK
|
||||||
|
outerLerpColor = Color.WHITE
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.w3.org/TR/WCAG20/#visual-audio-contrast-contrast
|
var text = "${nation.name}'s colors do not contrast enough - it is unreadable!"
|
||||||
val constrastRatio = nation.getContrastRatio()
|
|
||||||
if (constrastRatio < 3) {
|
|
||||||
val innerColorLuminance = getRelativeLuminance(nation.getInnerColor())
|
|
||||||
val outerColorLuminance = getRelativeLuminance(nation.getOuterColor())
|
|
||||||
|
|
||||||
val innerLerpColor: Color
|
for (i in 1..10) {
|
||||||
val outerLerpColor: Color
|
val newInnerColor = nation.getInnerColor().cpy().lerp(innerLerpColor, 0.05f * i)
|
||||||
|
val newOuterColor = nation.getOuterColor().cpy().lerp(outerLerpColor, 0.05f * i)
|
||||||
|
|
||||||
if (innerColorLuminance > outerColorLuminance) { // inner is brighter
|
if (getContrastRatio(newInnerColor, newOuterColor) > 3) {
|
||||||
innerLerpColor = Color.WHITE
|
text += "\nSuggested colors: "
|
||||||
outerLerpColor = Color.BLACK
|
text += "\n\t\t\"outerColor\": [${(newOuterColor.r * 255).toInt()}, ${(newOuterColor.g * 255).toInt()}, ${(newOuterColor.b * 255).toInt()}],"
|
||||||
} else {
|
text += "\n\t\t\"innerColor\": [${(newInnerColor.r * 255).toInt()}, ${(newInnerColor.g * 255).toInt()}, ${(newInnerColor.b * 255).toInt()}],"
|
||||||
innerLerpColor = Color.BLACK
|
break
|
||||||
outerLerpColor = Color.WHITE
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var text = "${nation.name}'s colors do not contrast enough - it is unreadable!"
|
|
||||||
|
|
||||||
for (i in 1..10) {
|
|
||||||
val newInnerColor = nation.getInnerColor().cpy().lerp(innerLerpColor, 0.05f * i)
|
|
||||||
val newOuterColor = nation.getOuterColor().cpy().lerp(outerLerpColor, 0.05f * i)
|
|
||||||
|
|
||||||
if (getContrastRatio(newInnerColor, newOuterColor) > 3) {
|
|
||||||
text += "\nSuggested colors: "
|
|
||||||
text += "\n\t\t\"outerColor\": [${(newOuterColor.r * 255).toInt()}, ${(newOuterColor.g * 255).toInt()}, ${(newOuterColor.b * 255).toInt()}],"
|
|
||||||
text += "\n\t\t\"innerColor\": [${(newInnerColor.r * 255).toInt()}, ${(newInnerColor.g * 255).toInt()}, ${(newInnerColor.b * 255).toInt()}],"
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lines.add(
|
|
||||||
text, RulesetErrorSeverity.WarningOptionsOnly
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uniqueValidator.checkUniques(nation, lines, rulesetInvariant, tryFixUnknownUniques)
|
lines.add(
|
||||||
|
text, RulesetErrorSeverity.WarningOptionsOnly
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addBuildingErrorsRulesetInvariant(
|
private fun addBuildingErrorsRulesetInvariant(
|
||||||
lines: RulesetErrorList,
|
lines: RulesetErrorList,
|
||||||
rulesetInvariant: UniqueType.UniqueParameterErrorSeverity,
|
|
||||||
tryFixUnknownUniques: Boolean
|
tryFixUnknownUniques: Boolean
|
||||||
) {
|
) {
|
||||||
for (building in ruleset.buildings.values) {
|
for (building in ruleset.buildings.values) {
|
||||||
if (building.requiredTech == null && building.cost == -1 && !building.hasUnique(
|
addBuildingErrorRulesetInvariant(building, lines)
|
||||||
UniqueType.Unbuildable
|
|
||||||
)
|
|
||||||
)
|
|
||||||
lines.add(
|
|
||||||
"${building.name} is buildable and therefore should either have an explicit cost or reference an existing tech!",
|
|
||||||
RulesetErrorSeverity.Warning
|
|
||||||
)
|
|
||||||
|
|
||||||
for (gpp in building.greatPersonPoints)
|
uniqueValidator.checkUniques(building, lines, false, tryFixUnknownUniques)
|
||||||
if (gpp.key !in ruleset.units)
|
|
||||||
lines.add(
|
|
||||||
"Building ${building.name} has greatPersonPoints for ${gpp.key}, which is not a unit in the ruleset!",
|
|
||||||
RulesetErrorSeverity.Warning
|
|
||||||
)
|
|
||||||
|
|
||||||
uniqueValidator.checkUniques(building, lines, rulesetInvariant, tryFixUnknownUniques)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun addBuildingErrorRulesetInvariant(building: Building, lines: RulesetErrorList) {
|
||||||
|
if (building.requiredTech == null && building.cost == -1 && !building.hasUnique(
|
||||||
|
UniqueType.Unbuildable
|
||||||
|
)
|
||||||
|
)
|
||||||
|
lines.add(
|
||||||
|
"${building.name} is buildable and therefore should either have an explicit cost or reference an existing tech!",
|
||||||
|
RulesetErrorSeverity.Warning
|
||||||
|
)
|
||||||
|
|
||||||
|
for (gpp in building.greatPersonPoints)
|
||||||
|
if (gpp.key !in ruleset.units)
|
||||||
|
lines.add(
|
||||||
|
"Building ${building.name} has greatPersonPoints for ${gpp.key}, which is not a unit in the ruleset!",
|
||||||
|
RulesetErrorSeverity.Warning
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private fun addTechColumnErrorsRulesetInvariant(lines: RulesetErrorList) {
|
private fun addTechColumnErrorsRulesetInvariant(lines: RulesetErrorList) {
|
||||||
for (techColumn in ruleset.techColumns) {
|
for (techColumn in ruleset.techColumns) {
|
||||||
if (techColumn.columnNumber < 0)
|
if (techColumn.columnNumber < 0)
|
||||||
@ -590,40 +614,25 @@ class RulesetValidator(val ruleset: Ruleset) {
|
|||||||
RulesetErrorSeverity.Warning
|
RulesetErrorSeverity.Warning
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun addTechErrorsRulesetInvariant(
|
|
||||||
lines: RulesetErrorList,
|
|
||||||
rulesetInvariant: UniqueType.UniqueParameterErrorSeverity,
|
|
||||||
tryFixUnknownUniques: Boolean
|
|
||||||
) {
|
|
||||||
for (tech in ruleset.technologies.values) {
|
for (tech in ruleset.technologies.values) {
|
||||||
for (otherTech in ruleset.technologies.values) {
|
for (otherTech in ruleset.technologies.values) {
|
||||||
if (tech != otherTech && otherTech.column?.columnNumber == tech.column?.columnNumber && otherTech.row == tech.row)
|
if (tech != otherTech && otherTech.column?.columnNumber == tech.column?.columnNumber && otherTech.row == tech.row)
|
||||||
lines += "${tech.name} is in the same row and column as ${otherTech.name}!"
|
lines += "${tech.name} is in the same row and column as ${otherTech.name}!"
|
||||||
}
|
}
|
||||||
|
|
||||||
uniqueValidator.checkUniques(tech, lines, rulesetInvariant, tryFixUnknownUniques)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addUnitErrorsRulesetInvariant(
|
private fun addTechErrorsRulesetInvariant(
|
||||||
lines: RulesetErrorList,
|
lines: RulesetErrorList,
|
||||||
rulesetInvariant: UniqueType.UniqueParameterErrorSeverity,
|
|
||||||
tryFixUnknownUniques: Boolean
|
tryFixUnknownUniques: Boolean
|
||||||
) {
|
) {
|
||||||
for (unit in ruleset.units.values) {
|
for (tech in ruleset.technologies.values) {
|
||||||
if (unit.upgradesTo == unit.name || (unit.upgradesTo != null && unit.upgradesTo == unit.replaces))
|
uniqueValidator.checkUniques(tech, lines, false, tryFixUnknownUniques)
|
||||||
lines += "${unit.name} upgrades to itself!"
|
|
||||||
if (!unit.isCivilian() && unit.strength == 0)
|
|
||||||
lines += "${unit.name} is a military unit but has no assigned strength!"
|
|
||||||
if (unit.isRanged() && unit.rangedStrength == 0 && !unit.hasUnique(UniqueType.CannotAttack))
|
|
||||||
lines += "${unit.name} is a ranged unit but has no assigned rangedStrength!"
|
|
||||||
|
|
||||||
uniqueValidator.checkUniques(unit, lines, rulesetInvariant, tryFixUnknownUniques)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Collects known technology prerequisite paths: key is the technology name,
|
/** Collects known technology prerequisite paths: key is the technology name,
|
||||||
* value a Set of its prerequisites including indirect ones */
|
* value a Set of its prerequisites including indirect ones */
|
||||||
private val prereqsHashMap = HashMap<String, HashSet<String>>()
|
private val prereqsHashMap = HashMap<String, HashSet<String>>()
|
||||||
@ -640,6 +649,15 @@ class RulesetValidator(val ruleset: Ruleset) {
|
|||||||
return techHashSet
|
return techHashSet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun checkUnitRulesetInvariant(unit: BaseUnit, lines: RulesetErrorList) {
|
||||||
|
if (unit.upgradesTo == unit.name || (unit.upgradesTo != null && unit.upgradesTo == unit.replaces))
|
||||||
|
lines += "${unit.name} upgrades to itself!"
|
||||||
|
if (!unit.isCivilian() && unit.strength == 0)
|
||||||
|
lines += "${unit.name} is a military unit but has no assigned strength!"
|
||||||
|
if (unit.isRanged() && unit.rangedStrength == 0 && !unit.hasUnique(UniqueType.CannotAttack))
|
||||||
|
lines += "${unit.name} is a ranged unit but has no assigned rangedStrength!"
|
||||||
|
}
|
||||||
|
|
||||||
/** Collects all RulesetSpecific checks for a BaseUnit */
|
/** Collects all RulesetSpecific checks for a BaseUnit */
|
||||||
private fun checkUnitRulesetSpecific(unit: BaseUnit, lines: RulesetErrorList) {
|
private fun checkUnitRulesetSpecific(unit: BaseUnit, lines: RulesetErrorList) {
|
||||||
if (unit.requiredTech != null && !ruleset.technologies.containsKey(unit.requiredTech!!))
|
if (unit.requiredTech != null && !ruleset.technologies.containsKey(unit.requiredTech!!))
|
||||||
|
@ -16,7 +16,7 @@ class UniqueValidator(val ruleset: Ruleset) {
|
|||||||
fun checkUniques(
|
fun checkUniques(
|
||||||
uniqueContainer: IHasUniques,
|
uniqueContainer: IHasUniques,
|
||||||
lines: RulesetErrorList,
|
lines: RulesetErrorList,
|
||||||
severityToReport: UniqueType.UniqueParameterErrorSeverity,
|
reportRulesetSpecificErrors: Boolean,
|
||||||
tryFixUnknownUniques: Boolean
|
tryFixUnknownUniques: Boolean
|
||||||
) {
|
) {
|
||||||
for (unique in uniqueContainer.uniqueObjects) {
|
for (unique in uniqueContainer.uniqueObjects) {
|
||||||
@ -24,7 +24,7 @@ class UniqueValidator(val ruleset: Ruleset) {
|
|||||||
unique,
|
unique,
|
||||||
tryFixUnknownUniques,
|
tryFixUnknownUniques,
|
||||||
uniqueContainer as? INamed,
|
uniqueContainer as? INamed,
|
||||||
severityToReport
|
reportRulesetSpecificErrors
|
||||||
)
|
)
|
||||||
lines.addAll(errors)
|
lines.addAll(errors)
|
||||||
}
|
}
|
||||||
@ -34,7 +34,7 @@ class UniqueValidator(val ruleset: Ruleset) {
|
|||||||
unique: Unique,
|
unique: Unique,
|
||||||
tryFixUnknownUniques: Boolean,
|
tryFixUnknownUniques: Boolean,
|
||||||
namedObj: INamed?,
|
namedObj: INamed?,
|
||||||
severityToReport: UniqueType.UniqueParameterErrorSeverity
|
reportRulesetSpecificErrors: Boolean
|
||||||
): List<RulesetError> {
|
): List<RulesetError> {
|
||||||
val prefix by lazy { (if (namedObj is IRulesetObject) "${namedObj.originRuleset}: " else "") +
|
val prefix by lazy { (if (namedObj is IRulesetObject) "${namedObj.originRuleset}: " else "") +
|
||||||
(if (namedObj == null) "The" else "${namedObj.name}'s") }
|
(if (namedObj == null) "The" else "${namedObj.name}'s") }
|
||||||
@ -47,25 +47,25 @@ class UniqueValidator(val ruleset: Ruleset) {
|
|||||||
|
|
||||||
val typeComplianceErrors = getComplianceErrors(unique)
|
val typeComplianceErrors = getComplianceErrors(unique)
|
||||||
for (complianceError in typeComplianceErrors) {
|
for (complianceError in typeComplianceErrors) {
|
||||||
if (complianceError.errorSeverity <= severityToReport)
|
if (!reportRulesetSpecificErrors && complianceError.errorSeverity == UniqueType.UniqueParameterErrorSeverity.RulesetSpecific)
|
||||||
rulesetErrors.add(RulesetError("$prefix unique \"${unique.text}\" contains parameter ${complianceError.parameterName}," +
|
continue
|
||||||
" which does not fit parameter type" +
|
|
||||||
" ${complianceError.acceptableParameterTypes.joinToString(" or ") { it.parameterName }} !",
|
rulesetErrors.add(RulesetError("$prefix unique \"${unique.text}\" contains parameter ${complianceError.parameterName}," +
|
||||||
complianceError.errorSeverity.getRulesetErrorSeverity(severityToReport)
|
" which does not fit parameter type" +
|
||||||
))
|
" ${complianceError.acceptableParameterTypes.joinToString(" or ") { it.parameterName }} !",
|
||||||
|
complianceError.errorSeverity.getRulesetErrorSeverity()
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
for (conditional in unique.conditionals) {
|
for (conditional in unique.conditionals) {
|
||||||
addConditionalErrors(conditional, rulesetErrors, prefix, unique, severityToReport)
|
addConditionalErrors(conditional, rulesetErrors, prefix, unique, reportRulesetSpecificErrors)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (severityToReport != UniqueType.UniqueParameterErrorSeverity.RulesetSpecific)
|
if (reportRulesetSpecificErrors)
|
||||||
// If we don't filter these messages will be listed twice as this function is called twice on most objects
|
// If we don't filter these messages will be listed twice as this function is called twice on most objects
|
||||||
// The tests are RulesetInvariant in nature, but RulesetSpecific is called for _all_ objects, invariant is not.
|
// The tests are RulesetInvariant in nature, but RulesetSpecific is called for _all_ objects, invariant is not.
|
||||||
return rulesetErrors
|
addDeprecationAnnotationErrors(unique, prefix, rulesetErrors)
|
||||||
|
|
||||||
addDeprecationAnnotationErrors(unique, prefix, rulesetErrors)
|
|
||||||
|
|
||||||
return rulesetErrors
|
return rulesetErrors
|
||||||
}
|
}
|
||||||
@ -75,7 +75,7 @@ class UniqueValidator(val ruleset: Ruleset) {
|
|||||||
rulesetErrors: RulesetErrorList,
|
rulesetErrors: RulesetErrorList,
|
||||||
prefix: String,
|
prefix: String,
|
||||||
unique: Unique,
|
unique: Unique,
|
||||||
severityToReport: UniqueType.UniqueParameterErrorSeverity
|
reportRulesetSpecificErrors: Boolean
|
||||||
) {
|
) {
|
||||||
if (conditional.type == null) {
|
if (conditional.type == null) {
|
||||||
rulesetErrors.add(
|
rulesetErrors.add(
|
||||||
@ -104,16 +104,19 @@ class UniqueValidator(val ruleset: Ruleset) {
|
|||||||
|
|
||||||
val conditionalComplianceErrors =
|
val conditionalComplianceErrors =
|
||||||
getComplianceErrors(conditional)
|
getComplianceErrors(conditional)
|
||||||
|
|
||||||
for (complianceError in conditionalComplianceErrors) {
|
for (complianceError in conditionalComplianceErrors) {
|
||||||
if (complianceError.errorSeverity == severityToReport)
|
if (!reportRulesetSpecificErrors && complianceError.errorSeverity == UniqueType.UniqueParameterErrorSeverity.RulesetSpecific)
|
||||||
rulesetErrors.add(
|
continue
|
||||||
RulesetError(
|
|
||||||
"$prefix unique \"${unique.text}\" contains the conditional \"${conditional.text}\"." +
|
rulesetErrors.add(
|
||||||
" This contains the parameter ${complianceError.parameterName} which does not fit parameter type" +
|
RulesetError(
|
||||||
" ${complianceError.acceptableParameterTypes.joinToString(" or ") { it.parameterName }} !",
|
"$prefix unique \"${unique.text}\" contains the conditional \"${conditional.text}\"." +
|
||||||
complianceError.errorSeverity.getRulesetErrorSeverity(severityToReport)
|
" This contains the parameter ${complianceError.parameterName} which does not fit parameter type" +
|
||||||
)
|
" ${complianceError.acceptableParameterTypes.joinToString(" or ") { it.parameterName }} !",
|
||||||
|
complianceError.errorSeverity.getRulesetErrorSeverity()
|
||||||
)
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,19 +8,18 @@ import com.badlogic.gdx.utils.Align
|
|||||||
import com.unciv.models.ruleset.Ruleset
|
import com.unciv.models.ruleset.Ruleset
|
||||||
import com.unciv.models.ruleset.RulesetCache
|
import com.unciv.models.ruleset.RulesetCache
|
||||||
import com.unciv.models.ruleset.unique.Unique
|
import com.unciv.models.ruleset.unique.Unique
|
||||||
import com.unciv.models.ruleset.unique.UniqueType
|
|
||||||
import com.unciv.models.ruleset.validation.RulesetError
|
import com.unciv.models.ruleset.validation.RulesetError
|
||||||
import com.unciv.models.ruleset.validation.RulesetErrorSeverity
|
import com.unciv.models.ruleset.validation.RulesetErrorSeverity
|
||||||
import com.unciv.models.ruleset.validation.UniqueValidator
|
import com.unciv.models.ruleset.validation.UniqueValidator
|
||||||
import com.unciv.models.translations.tr
|
import com.unciv.models.translations.tr
|
||||||
import com.unciv.ui.components.widgets.ExpanderTab
|
|
||||||
import com.unciv.ui.components.widgets.TabbedPager
|
|
||||||
import com.unciv.ui.components.widgets.TranslatedSelectBox
|
|
||||||
import com.unciv.ui.components.extensions.surroundWithCircle
|
import com.unciv.ui.components.extensions.surroundWithCircle
|
||||||
import com.unciv.ui.components.extensions.toLabel
|
import com.unciv.ui.components.extensions.toLabel
|
||||||
import com.unciv.ui.components.extensions.toTextButton
|
import com.unciv.ui.components.extensions.toTextButton
|
||||||
import com.unciv.ui.components.input.onChange
|
import com.unciv.ui.components.input.onChange
|
||||||
import com.unciv.ui.components.input.onClick
|
import com.unciv.ui.components.input.onClick
|
||||||
|
import com.unciv.ui.components.widgets.ExpanderTab
|
||||||
|
import com.unciv.ui.components.widgets.TabbedPager
|
||||||
|
import com.unciv.ui.components.widgets.TranslatedSelectBox
|
||||||
import com.unciv.ui.images.ImageGetter
|
import com.unciv.ui.images.ImageGetter
|
||||||
import com.unciv.ui.popups.ToastPopup
|
import com.unciv.ui.popups.ToastPopup
|
||||||
import com.unciv.ui.screens.basescreen.BaseScreen
|
import com.unciv.ui.screens.basescreen.BaseScreen
|
||||||
@ -75,7 +74,7 @@ class ModCheckTab(
|
|||||||
runAction()
|
runAction()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun runModChecker(base: String = MOD_CHECK_WITHOUT_BASE) {
|
private fun runModChecker(base: String = MOD_CHECK_WITHOUT_BASE) {
|
||||||
|
|
||||||
modCheckFirstRun = false
|
modCheckFirstRun = false
|
||||||
if (modCheckBaseSelect == null) return
|
if (modCheckBaseSelect == null) return
|
||||||
@ -204,7 +203,7 @@ class ModCheckTab(
|
|||||||
replacementUnique,
|
replacementUnique,
|
||||||
false,
|
false,
|
||||||
null,
|
null,
|
||||||
UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
|
true
|
||||||
)
|
)
|
||||||
for (error in modInvariantErrors)
|
for (error in modInvariantErrors)
|
||||||
Log.error("ModInvariantError: %s - %s", error.text, error.errorSeverityToReport)
|
Log.error("ModInvariantError: %s - %s", error.text, error.errorSeverityToReport)
|
||||||
@ -215,7 +214,7 @@ class ModCheckTab(
|
|||||||
replacementUnique,
|
replacementUnique,
|
||||||
false,
|
false,
|
||||||
null,
|
null,
|
||||||
UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
|
true
|
||||||
)
|
)
|
||||||
for (error in modSpecificErrors)
|
for (error in modSpecificErrors)
|
||||||
Log.error("ModSpecificError: %s - %s", error.text, error.errorSeverityToReport)
|
Log.error("ModSpecificError: %s - %s", error.text, error.errorSeverityToReport)
|
||||||
|
Loading…
Reference in New Issue
Block a user