mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-18 03:38:55 +07:00
Re-show redundant tech prereq mod errors without impeding playability (#4046)
* Re-show redundant tech prereq mod errors without impeding playability * Re-enable playability of mods with less severe errors - fun version
This commit is contained in:
@ -227,9 +227,35 @@ class Ruleset {
|
|||||||
return stringList.joinToString()
|
return stringList.joinToString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Severity level of Mod RuleSet check */
|
||||||
fun checkModLinks(): String {
|
enum class CheckModLinksStatus {OK, Warning, Error}
|
||||||
|
/** Result of a Mod RuleSet check */
|
||||||
|
// essentially a named Pair with a few shortcuts
|
||||||
|
class CheckModLinksResult(val status: CheckModLinksStatus, val message: String) {
|
||||||
|
// Empty constructor just makes the Complex Mod Check on the new game screen shorter
|
||||||
|
constructor(): this(CheckModLinksStatus.OK, "")
|
||||||
|
// Constructor that joins lines
|
||||||
|
constructor(status: CheckModLinksStatus, lines: ArrayList<String>):
|
||||||
|
this (status,
|
||||||
|
lines.joinToString("\n"))
|
||||||
|
// Constructor that auto-determines severity
|
||||||
|
constructor(warningCount: Int, lines: ArrayList<String>):
|
||||||
|
this (
|
||||||
|
when {
|
||||||
|
lines.isEmpty() -> CheckModLinksStatus.OK
|
||||||
|
lines.size == warningCount -> CheckModLinksStatus.Warning
|
||||||
|
else -> CheckModLinksStatus.Error
|
||||||
|
},
|
||||||
|
lines)
|
||||||
|
// Allows $this in format strings
|
||||||
|
override fun toString() = message
|
||||||
|
// Readability shortcuts
|
||||||
|
fun isError() = status == CheckModLinksStatus.Error
|
||||||
|
fun isNotOK() = status != CheckModLinksStatus.OK
|
||||||
|
}
|
||||||
|
fun checkModLinks(): CheckModLinksResult {
|
||||||
val lines = ArrayList<String>()
|
val lines = ArrayList<String>()
|
||||||
|
var warningCount = 0
|
||||||
|
|
||||||
// Checks for all mods
|
// Checks for all mods
|
||||||
for (unit in units.values) {
|
for (unit in units.values) {
|
||||||
@ -253,7 +279,7 @@ class Ruleset {
|
|||||||
lines += "${building.name} must either have an explicit cost or reference an existing tech!"
|
lines += "${building.name} must either have an explicit cost or reference an existing tech!"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!modOptions.isBaseRuleset) return lines.joinToString("\n")
|
if (!modOptions.isBaseRuleset) return CheckModLinksResult(warningCount, lines)
|
||||||
|
|
||||||
|
|
||||||
for (unit in units.values) {
|
for (unit in units.values) {
|
||||||
@ -336,13 +362,14 @@ class Ruleset {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (tech.prerequisites.asSequence().filterNot { it == prereq }
|
if (tech.prerequisites.asSequence().filterNot { it == prereq }
|
||||||
.any { getPrereqTree(it).contains(prereq) })
|
.any { getPrereqTree(it).contains(prereq) }){
|
||||||
println("No need to add $prereq as a prerequisite of ${tech.name} - it is already implicit from the other prerequisites!")
|
lines += "No need to add $prereq as a prerequisite of ${tech.name} - it is already implicit from the other prerequisites!"
|
||||||
|
warningCount++
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return CheckModLinksResult(warningCount, lines)
|
||||||
return lines.joinToString("\n")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package com.unciv.ui.newgamescreen
|
|||||||
|
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.CheckBox
|
import com.badlogic.gdx.scenes.scene2d.ui.CheckBox
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||||
|
import com.unciv.models.ruleset.Ruleset.CheckModLinksResult
|
||||||
import com.unciv.models.ruleset.RulesetCache
|
import com.unciv.models.ruleset.RulesetCache
|
||||||
import com.unciv.models.translations.tr
|
import com.unciv.models.translations.tr
|
||||||
import com.unciv.ui.utils.CameraStageBaseScreen
|
import com.unciv.ui.utils.CameraStageBaseScreen
|
||||||
@ -22,35 +23,37 @@ class ModCheckboxTable(val mods:LinkedHashSet<String>, val screen: CameraStageBa
|
|||||||
checkBox.onChange {
|
checkBox.onChange {
|
||||||
if (checkBox.isChecked) {
|
if (checkBox.isChecked) {
|
||||||
val modLinkErrors = mod.checkModLinks()
|
val modLinkErrors = mod.checkModLinks()
|
||||||
if (modLinkErrors != "") {
|
if (modLinkErrors.isNotOK()) {
|
||||||
ToastPopup("The mod you selected is incorrectly defined!\n\n$modLinkErrors", screen)
|
ToastPopup("The mod you selected is incorrectly defined!\n\n$modLinkErrors", screen)
|
||||||
checkBox.isChecked = false
|
if (modLinkErrors.isError()) {
|
||||||
return@onChange
|
checkBox.isChecked = false
|
||||||
|
return@onChange
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val previousMods = mods.toList()
|
val previousMods = mods.toList()
|
||||||
|
|
||||||
if (mod.modOptions.isBaseRuleset)
|
if (mod.modOptions.isBaseRuleset)
|
||||||
for (oldBaseRuleset in previousMods) // so we don't get concurrent modification excpetions
|
for (oldBaseRuleset in previousMods) // so we don't get concurrent modification exceptions
|
||||||
if (modRulesets.firstOrNull { it.name == oldBaseRuleset }?.modOptions?.isBaseRuleset == true)
|
if (modRulesets.firstOrNull { it.name == oldBaseRuleset }?.modOptions?.isBaseRuleset == true)
|
||||||
mods.remove(oldBaseRuleset)
|
mods.remove(oldBaseRuleset)
|
||||||
mods.add(mod.name)
|
mods.add(mod.name)
|
||||||
|
|
||||||
var isCompatibleWithCurrentRuleset = true
|
var isCompatibleWithCurrentRuleset = true
|
||||||
var complexModLinkErrors = ""
|
var complexModLinkCheck = CheckModLinksResult()
|
||||||
try {
|
try {
|
||||||
val newRuleset = RulesetCache.getComplexRuleset(mods)
|
val newRuleset = RulesetCache.getComplexRuleset(mods)
|
||||||
newRuleset.modOptions.isBaseRuleset = true // This is so the checkModLinks finds all connections
|
newRuleset.modOptions.isBaseRuleset = true // This is so the checkModLinks finds all connections
|
||||||
complexModLinkErrors = newRuleset.checkModLinks()
|
complexModLinkCheck = newRuleset.checkModLinks()
|
||||||
if (complexModLinkErrors != "") isCompatibleWithCurrentRuleset = false
|
isCompatibleWithCurrentRuleset = !complexModLinkCheck.isError()
|
||||||
} catch (x: Exception) {
|
} catch (x: Exception) {
|
||||||
// This happens if a building is dependent on a tech not in the base ruleset
|
// This happens if a building is dependent on a tech not in the base ruleset
|
||||||
// because newRuleset.updateBuildingCosts() in getComplexRulset() throws an error
|
// because newRuleset.updateBuildingCosts() in getComplexRuleset() throws an error
|
||||||
isCompatibleWithCurrentRuleset = false
|
isCompatibleWithCurrentRuleset = false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isCompatibleWithCurrentRuleset) {
|
if (!isCompatibleWithCurrentRuleset) {
|
||||||
ToastPopup("The mod you selected is incompatible with the defined ruleset!\n\n$complexModLinkErrors", screen)
|
ToastPopup("The mod you selected is incompatible with the defined ruleset!\n\n$complexModLinkCheck", screen)
|
||||||
checkBox.isChecked = false
|
checkBox.isChecked = false
|
||||||
mods.clear()
|
mods.clear()
|
||||||
mods.addAll(previousMods)
|
mods.addAll(previousMods)
|
||||||
|
@ -249,11 +249,11 @@ class OptionsPopup(val previousScreen:CameraStageBaseScreen) : Popup(previousScr
|
|||||||
val lines = ArrayList<String>()
|
val lines = ArrayList<String>()
|
||||||
for (mod in RulesetCache.values) {
|
for (mod in RulesetCache.values) {
|
||||||
val modLinks = mod.checkModLinks()
|
val modLinks = mod.checkModLinks()
|
||||||
if (modLinks != "") {
|
if (modLinks.isNotOK()) {
|
||||||
lines += ""
|
lines += ""
|
||||||
lines += mod.name
|
lines += mod.name
|
||||||
lines += ""
|
lines += ""
|
||||||
lines += modLinks
|
lines += modLinks.message
|
||||||
lines += ""
|
lines += ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,8 +81,8 @@ class BasicTests {
|
|||||||
fun baseRulesetHasNoBugs() {
|
fun baseRulesetHasNoBugs() {
|
||||||
ruleset.modOptions.isBaseRuleset=true
|
ruleset.modOptions.isBaseRuleset=true
|
||||||
val modCheck = ruleset.checkModLinks()
|
val modCheck = ruleset.checkModLinks()
|
||||||
if(modCheck!="") println(modCheck)
|
if(modCheck.isNotOK()) println(modCheck)
|
||||||
Assert.assertTrue(modCheck == "")
|
Assert.assertFalse(modCheck.isNotOK())
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
Reference in New Issue
Block a user