Local mod folder names preserved. (#9844)

* Reduce conversion of local mod folder names to treat only ending spaces/dashes

* Wiki entry for GlobalUniques

* Missing originRuleset coverage

* Nicer RulesetValidator messages when name or originRuleset are missing
This commit is contained in:
SomeTroglodyte 2023-07-30 16:38:33 +02:00 committed by GitHub
parent b992144ecd
commit 443bf3afdb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 35 additions and 17 deletions

View File

@ -581,7 +581,7 @@ class GameInfo : IsPartOfGameInfoSerialization, HasGameInfoSerializationVersion
// Cater for the mad modder using trailing '-' in their repo name - convert the mods list so
// it requires our new, Windows-safe local name (no trailing blanks)
for ((oldName, newName) in gameParameters.mods.map { it to it.repoNameToFolderName() }) {
for ((oldName, newName) in gameParameters.mods.map { it to it.repoNameToFolderName(onlyOuterBlanks = true) }) {
if (newName == oldName) continue
gameParameters.mods.remove(oldName)
gameParameters.mods.add(newName)

View File

@ -230,6 +230,8 @@ class Ruleset {
allRulesetObjects() + sequenceOf(modOptions)
fun load(folderHandle: FileHandle) {
// Note: Most files are loaded using createHashmap, which sets originRuleset automatically.
// For other files containing IRulesetObject's we'll have to remember to do so manually - e.g. Tech.
val modOptionsFile = folderHandle.child("ModOptions.json")
if (modOptionsFile.exists()) {
try {
@ -250,6 +252,7 @@ class Ruleset {
for (tech in techColumn.techs) {
if (tech.cost == 0) tech.cost = techColumn.techCost
tech.column = techColumn
tech.originRuleset = name
technologies[tech.name] = tech
}
}
@ -261,7 +264,10 @@ class Ruleset {
val terrainsFile = folderHandle.child("Terrains.json")
if (terrainsFile.exists()) {
terrains += createHashmap(json().fromJsonFile(Array<Terrain>::class.java, terrainsFile))
for (terrain in terrains.values) terrain.setTransients()
for (terrain in terrains.values) {
terrain.originRuleset = name
terrain.setTransients()
}
}
val resourcesFile = folderHandle.child("TileResources.json")
@ -316,6 +322,7 @@ class Ruleset {
// Append child policies of this branch
for (policy in branch.policies) {
policy.branch = branch
policy.originRuleset = name
if (policy.requires == null) {
policy.requires = arrayListOf(branch.name)
}
@ -366,6 +373,7 @@ class Ruleset {
val globalUniquesFile = folderHandle.child("GlobalUniques.json")
if (globalUniquesFile.exists()) {
globalUniques = json().fromJsonFile(GlobalUniques::class.java, globalUniquesFile)
globalUniques.originRuleset = name
}
val victoryTypesFile = folderHandle.child("VictoryTypes.json")

View File

@ -475,8 +475,8 @@ class RulesetValidator(val ruleset: Ruleset) {
namedObj: INamed?,
severityToReport: UniqueType.UniqueComplianceErrorSeverity
): List<RulesetError> {
var name = namedObj?.name ?: ""
if (namedObj != null && namedObj is IRulesetObject) name = "${namedObj.originRuleset}: $name"
val prefix = (if (namedObj is IRulesetObject) "${namedObj.originRuleset}: " else "") +
(if (namedObj == null) "The" else "${namedObj.name}'s")
if (unique.type == null) {
if (!tryFixUnknownUniques) return emptyList()
val similarUniques = UniqueType.values().filter {
@ -490,17 +490,17 @@ class RulesetValidator(val ruleset: Ruleset) {
return when {
// Malformed conditional
unique.text.count { it=='<' } != unique.text.count { it=='>' } ->listOf(
RulesetError("$name's unique \"${unique.text}\" contains mismatched conditional braces!",
RulesetError("$prefix unique \"${unique.text}\" contains mismatched conditional braces!",
RulesetErrorSeverity.Warning))
// This should only ever happen if a bug is or has been introduced that prevents Unique.type from being set for a valid UniqueType, I think.\
equalUniques.isNotEmpty() -> listOf(RulesetError(
"$name's unique \"${unique.text}\" looks like it should be fine, but for some reason isn't recognized.",
"$prefix unique \"${unique.text}\" looks like it should be fine, but for some reason isn't recognized.",
RulesetErrorSeverity.OK))
similarUniques.isNotEmpty() -> {
val text =
"$name's unique \"${unique.text}\" looks like it may be a misspelling of:\n" +
"$prefix unique \"${unique.text}\" looks like it may be a misspelling of:\n" +
similarUniques.joinToString("\n") { uniqueType ->
var text = "\"${uniqueType.text}"
if (unique.conditionals.isNotEmpty())
@ -513,7 +513,7 @@ class RulesetValidator(val ruleset: Ruleset) {
}
RulesetCache.modCheckerAllowUntypedUniques -> emptyList()
else -> listOf(RulesetError(
"$name's unique \"${unique.text}\" not found in Unciv's unique types.",
"$prefix unique \"${unique.text}\" not found in Unciv's unique types.",
RulesetErrorSeverity.OK))
}
}
@ -521,12 +521,12 @@ class RulesetValidator(val ruleset: Ruleset) {
val rulesetErrors = RulesetErrorList()
if (namedObj is IHasUniques && !unique.type.canAcceptUniqueTarget(namedObj.getUniqueTarget()))
rulesetErrors.add(RulesetError("$name's unique \"${unique.text}\" is not allowed on its target type", RulesetErrorSeverity.Warning))
rulesetErrors.add(RulesetError("$prefix unique \"${unique.text}\" is not allowed on its target type", RulesetErrorSeverity.Warning))
val typeComplianceErrors = unique.type.getComplianceErrors(unique, ruleset)
for (complianceError in typeComplianceErrors) {
if (complianceError.errorSeverity <= severityToReport)
rulesetErrors.add(RulesetError("$name's unique \"${unique.text}\" contains parameter ${complianceError.parameterName}," +
rulesetErrors.add(RulesetError("$prefix unique \"${unique.text}\" contains parameter ${complianceError.parameterName}," +
" which does not fit parameter type" +
" ${complianceError.acceptableParameterTypes.joinToString(" or ") { it.parameterName }} !",
complianceError.errorSeverity.getRulesetErrorSeverity(severityToReport)
@ -536,13 +536,13 @@ class RulesetValidator(val ruleset: Ruleset) {
for (conditional in unique.conditionals) {
if (conditional.type == null) {
rulesetErrors.add(
"$name's unique \"${unique.text}\" contains the conditional \"${conditional.text}\"," +
"$prefix unique \"${unique.text}\" contains the conditional \"${conditional.text}\"," +
" which is of an unknown type!",
RulesetErrorSeverity.Warning
)
} else {
if (conditional.type.targetTypes.none { it.modifierType != UniqueTarget.ModifierType.None })
rulesetErrors.add("$name's unique \"${unique.text}\" contains the conditional \"${conditional.text}\"," +
rulesetErrors.add("$prefix unique \"${unique.text}\" contains the conditional \"${conditional.text}\"," +
" which is a Unique type not allowed as conditional or trigger.",
RulesetErrorSeverity.Warning)
@ -550,7 +550,7 @@ class RulesetValidator(val ruleset: Ruleset) {
conditional.type.getComplianceErrors(conditional, ruleset)
for (complianceError in conditionalComplianceErrors) {
if (complianceError.errorSeverity == severityToReport)
rulesetErrors.add(RulesetError( "$name's unique \"${unique.text}\" contains the conditional \"${conditional.text}\"." +
rulesetErrors.add(RulesetError( "$prefix unique \"${unique.text}\" contains the conditional \"${conditional.text}\"." +
" This contains the parameter ${complianceError.parameterName} which does not fit parameter type" +
" ${complianceError.acceptableParameterTypes.joinToString(" or ") { it.parameterName }} !",
complianceError.errorSeverity.getRulesetErrorSeverity(severityToReport)
@ -570,7 +570,7 @@ class RulesetValidator(val ruleset: Ruleset) {
if (deprecationAnnotation != null) {
val replacementUniqueText = unique.getReplacementText(ruleset)
val deprecationText =
"$name's unique \"${unique.text}\" is deprecated ${deprecationAnnotation.message}," +
"$prefix unique \"${unique.text}\" is deprecated ${deprecationAnnotation.message}," +
if (deprecationAnnotation.replaceWith.expression != "") " replace with \"${replacementUniqueText}\"" else ""
val severity = if (deprecationAnnotation.level == DeprecationLevel.WARNING)
RulesetErrorSeverity.WarningOptionsOnly // Not user-visible
@ -584,7 +584,7 @@ class RulesetValidator(val ruleset: Ruleset) {
}
class RulesetError(val text:String, val errorSeverityToReport: RulesetErrorSeverity)
class RulesetError(val text: String, val errorSeverityToReport: RulesetErrorSeverity)
enum class RulesetErrorSeverity(val color: Color) {
OK(Color.GREEN),

View File

@ -463,9 +463,10 @@ object Github {
* Replaces '-' with blanks but ensures no leading or trailing blanks.
* As mad modders know no limits, trailing "-" did indeed happen, causing things to break due to trailing blanks on a folder name.
* As "test-" and "test" are different allowed repository names, trimmed blanks are replaced with one overscore per side.
* @param onlyOuterBlanks If `true` ignores inner dashes - only start and end are treated. Useful when modders have manually creted local folder names using dashes.
*/
fun String.repoNameToFolderName(): String {
var result = replace('-', ' ')
fun String.repoNameToFolderName(onlyOuterBlanks: Boolean = false): String {
var result = if (onlyOuterBlanks) this else replace('-', ' ')
if (result.endsWith(' ')) result = result.trimEnd() + outerBlankReplacement
if (result.startsWith(' ')) result = outerBlankReplacement + result.trimStart()
return result

View File

@ -30,6 +30,7 @@ The JSON files that make up mods can have many different fields, and as not all
- [Difficulties.json](5-Miscellaneous-JSON-files.md#difficultiesjson)
- [Eras.json](5-Miscellaneous-JSON-files.md#erasjson)
- [ModOptions.json](5-Miscellaneous-JSON-files.md#modoptionsjson)
- [GlobalUniques.json](5-Miscellaneous-JSON-files.md#globaluniquesjson)
- [Tutorials.json](5-Miscellaneous-JSON-files.md#tutorialsjson)
- [Stats](3-Map-related-JSON-files.md#stats)
- [Sounds](../Images-and-Audio.md#sounds)

View File

@ -203,6 +203,14 @@ The formula for the gold cost of a unit upgrade is (rounded down to a multiple o
) ^ `exponent`
With `civModifier` being the multiplicative aggregate of ["\[relativeAmount\]% Gold cost of upgrading"](../uniques.md#global-uniques) uniques that apply.
## GlobalUniques.json
Defines uniques that apply globally. e.g. Vanilla rulesets define the effects of Unhappiness here.
Only the `uniques` field is used, but a name must still be set (the Ruleset validator might display it).
When extension rulesets define GlobalUniques, all uniques are merged. At the moment there is no way to change/remove uniques set by a base mod.
[link to original](https://github.com/yairm210/Unciv/tree/master/android/assets/jsons/GlobalUniques.json)
## Tutorials.json
[link to original](https://github.com/yairm210/Unciv/tree/master/android/assets/jsons/Tutorials.json)