mirror of
https://github.com/yairm210/Unciv.git
synced 2025-01-05 21:11:35 +07:00
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:
parent
b992144ecd
commit
443bf3afdb
@ -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)
|
||||
|
@ -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")
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user