Fix: New game screen, selection of mods from custom maps (#11387)

* Fix new game portrait mode geometry

* Allow updating ModCheckboxTable state from upstream

* Bubble a few notifications between NewGameScreen elements so changes can propagate better
This commit is contained in:
SomeTroglodyte
2024-04-04 22:41:17 +02:00
committed by GitHub
parent d5d05ecd6d
commit ac35433057
5 changed files with 50 additions and 12 deletions

View File

@ -11,6 +11,7 @@ import com.unciv.logic.civilization.PlayerType
import com.unciv.models.metadata.BaseRuleset import com.unciv.models.metadata.BaseRuleset
import com.unciv.models.metadata.GameParameters import com.unciv.models.metadata.GameParameters
import com.unciv.models.metadata.Player import com.unciv.models.metadata.Player
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.Nation
import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.ruleset.unique.UniqueType
@ -42,9 +43,12 @@ class GameOptionsTable(
private val updatePlayerPickerRandomLabel: () -> Unit private val updatePlayerPickerRandomLabel: () -> Unit
) : Table(BaseScreen.skin) { ) : Table(BaseScreen.skin) {
var gameParameters = previousScreen.gameSetupInfo.gameParameters var gameParameters = previousScreen.gameSetupInfo.gameParameters
val ruleset = previousScreen.ruleset var ruleset = previousScreen.ruleset
var locked = false var locked = false
private var baseRulesetHash = gameParameters.baseRuleset.hashCode()
private var selectedModsHash = gameParameters.mods.hashCode()
/** Holds the UI for the Extension Mods /** Holds the UI for the Extension Mods
* *
* Attention: This Widget is a little tricky due to the UI changes to support portrait mode: * Attention: This Widget is a little tricky due to the UI changes to support portrait mode:
@ -53,7 +57,7 @@ class GameOptionsTable(
* *
* The second reason this is public: [NewGameScreen] accesses [ModCheckboxTable.savedModcheckResult] for display. * The second reason this is public: [NewGameScreen] accesses [ModCheckboxTable.savedModcheckResult] for display.
*/ */
var modCheckboxes = getModCheckboxes(isPortrait = isPortrait) val modCheckboxes = getModCheckboxes(isPortrait = isPortrait)
// Remember this so we can unselect it when the pool dialog returns an empty pool // Remember this so we can unselect it when the pool dialog returns an empty pool
private var randomNationsPoolCheckbox: CheckBox? = null private var randomNationsPoolCheckbox: CheckBox? = null
@ -69,8 +73,18 @@ class GameOptionsTable(
fun update() { fun update() {
clear() clear()
// Mods may have changed
modCheckboxes = getModCheckboxes(isPortrait = isPortrait) // Mods may have changed (e.g. custom map selection)
val newBaseRulesetHash = gameParameters.baseRuleset.hashCode()
if (newBaseRulesetHash != baseRulesetHash) {
baseRulesetHash = newBaseRulesetHash
modCheckboxes.setBaseRuleset(gameParameters.baseRuleset)
}
val newSelectedModsHash = gameParameters.mods.hashCode()
if (newSelectedModsHash != selectedModsHash) {
selectedModsHash = newSelectedModsHash
modCheckboxes.updateSelection(gameParameters.mods)
}
add(Table().apply { add(Table().apply {
defaults().pad(5f) defaults().pad(5f)
@ -430,6 +444,12 @@ class GameOptionsTable(
add(victoryConditionsTable).colspan(2).row() add(victoryConditionsTable).colspan(2).row()
} }
fun updateRuleset(ruleset: Ruleset) {
this.ruleset = ruleset
gameParameters.acceptedModCheckErrors = ""
modCheckboxes.setBaseRuleset(gameParameters.baseRuleset)
}
fun resetRuleset() { fun resetRuleset() {
val rulesetName = BaseRuleset.Civ_V_GnK.fullName val rulesetName = BaseRuleset.Civ_V_GnK.fullName
gameParameters.baseRuleset = rulesetName gameParameters.baseRuleset = rulesetName
@ -446,6 +466,7 @@ class GameOptionsTable(
ruleset.mods += gameParameters.baseRuleset ruleset.mods += gameParameters.baseRuleset
ruleset.mods += gameParameters.mods ruleset.mods += gameParameters.mods
ruleset.modOptions = newRuleset.modOptions ruleset.modOptions = newRuleset.modOptions
gameParameters.acceptedModCheckErrors = ""
ImageGetter.setNewRuleset(ruleset) ImageGetter.setNewRuleset(ruleset)
UncivGame.Current.musicController.setModList(gameParameters.getModsAndBaseRuleset()) UncivGame.Current.musicController.setModList(gameParameters.getModsAndBaseRuleset())

View File

@ -131,8 +131,9 @@ class MapFileSelectTable(
// Do NOT try to put back the "bad" preselection! // Do NOT try to put back the "bad" preselection!
} }
private fun onSelectBoxChange() { fun onSelectBoxChange() {
cancelBackgroundJobs() cancelBackgroundJobs()
if (mapFileSelectBox.selection.isEmpty) return
val mapFile = mapFileSelectBox.selected.fileHandle val mapFile = mapFileSelectBox.selected.fileHandle
mapParameters.name = mapFile.name() mapParameters.name = mapFile.name()
newGameScreen.gameSetupInfo.mapFile = mapFile newGameScreen.gameSetupInfo.mapFile = mapFile
@ -140,7 +141,7 @@ class MapFileSelectTable(
newGameScreen.gameSetupInfo.gameParameters.mods = LinkedHashSet(mapMods.second) newGameScreen.gameSetupInfo.gameParameters.mods = LinkedHashSet(mapMods.second)
newGameScreen.gameSetupInfo.gameParameters.baseRuleset = mapMods.first.firstOrNull() newGameScreen.gameSetupInfo.gameParameters.baseRuleset = mapMods.first.firstOrNull()
?: mapFileSelectBox.selected.mapParameters.baseRuleset ?: mapFileSelectBox.selected.mapParameters.baseRuleset
val success = newGameScreen.tryUpdateRuleset() val success = newGameScreen.tryUpdateRuleset(updateUI = true)
newGameScreen.updateTables() newGameScreen.updateTables()
hideMiniMap() hideMiniMap()
if (success) { if (success) {

View File

@ -38,6 +38,7 @@ class MapOptionsTable(private val newGameScreen: NewGameScreen, isReset: Boolean
MapGeneratedMainType.custom -> { MapGeneratedMainType.custom -> {
mapParameters.type = MapGeneratedMainType.custom mapParameters.type = MapGeneratedMainType.custom
mapTypeSpecificTable.add(savedMapOptionsTable) mapTypeSpecificTable.add(savedMapOptionsTable)
savedMapOptionsTable.onSelectBoxChange()
newGameScreen.unlockTables() newGameScreen.unlockTables()
} }
MapGeneratedMainType.generated -> { MapGeneratedMainType.generated -> {

View File

@ -47,6 +47,7 @@ class ModCheckboxTable(
private var disableChangeEvents = false private var disableChangeEvents = false
private val expanderPadTop = if (isPortrait) 0f else 16f private val expanderPadTop = if (isPortrait) 0f else 16f
private val expanderPadOther = if (isPortrait) 0f else 10f
init { init {
val modRulesets = RulesetCache.values.filter { val modRulesets = RulesetCache.values.filter {
@ -67,6 +68,18 @@ class ModCheckboxTable(
setBaseRuleset(initialBaseRuleset) setBaseRuleset(initialBaseRuleset)
} }
fun updateSelection(newMods: Collection<String>) {
savedModcheckResult = null
mods.clear()
mods.addAll(newMods)
disableChangeEvents = true
for (mod in modWidgets) {
mod.widget.isChecked = mod.mod.name in mods
}
disableChangeEvents = false
deselectIncompatibleMods(null)
}
fun setBaseRuleset(newBaseRuleset: String) { fun setBaseRuleset(newBaseRuleset: String) {
baseRulesetName = newBaseRuleset baseRulesetName = newBaseRuleset
savedModcheckResult = null savedModcheckResult = null
@ -88,7 +101,7 @@ class ModCheckboxTable(
for (mod in compatibleMods) { for (mod in compatibleMods) {
it.add(mod.widget).row() it.add(mod.widget).row()
} }
}).pad(10f).padTop(expanderPadTop).growX().row() }).pad(expanderPadOther).padTop(expanderPadTop).growX().row()
disableIncompatibleMods() disableIncompatibleMods()
@ -103,6 +116,7 @@ class ModCheckboxTable(
mods.clear() mods.clear()
disableChangeEvents = false disableChangeEvents = false
savedModcheckResult = null
disableIncompatibleMods() disableIncompatibleMods()
onUpdate("-") // should match no mod onUpdate("-") // should match no mod
} }
@ -176,11 +190,10 @@ class ModCheckboxTable(
/** Deselect incompatible mods after [skipCheckBox] was selected. /** Deselect incompatible mods after [skipCheckBox] was selected.
* *
* Note: Inactive - we don'n even allow a conflict to be turned on using [disableIncompatibleMods]. * Note: Inactive - we don't even allow a conflict to be turned on using [disableIncompatibleMods].
* But if we want the alternative UX instead - use this in [checkBoxChanged] near `mods.add` and skip disabling... * But if we want the alternative UX instead - use this in [checkBoxChanged] near `mods.add` and skip disabling...
*/ */
@Suppress("unused") private fun deselectIncompatibleMods(skipCheckBox: CheckBox?) {
private fun deselectIncompatibleMods(skipCheckBox: CheckBox) {
disableChangeEvents = true disableChangeEvents = true
for (modWidget in modWidgets) { for (modWidget in modWidgets) {
if (modWidget.widget == skipCheckBox) continue if (modWidget.widget == skipCheckBox) continue

View File

@ -61,7 +61,7 @@ class NewGameScreen(
init { init {
val isPortrait = isNarrowerThan4to3() val isPortrait = isNarrowerThan4to3()
tryUpdateRuleset() // must come before playerPickerTable so mod nations from fromSettings tryUpdateRuleset(updateUI = false) // must come before playerPickerTable so mod nations from fromSettings
// remove the victory types which are not in the rule set (e.g. were in the recently disabled mod) // remove the victory types which are not in the rule set (e.g. were in the recently disabled mod)
gameSetupInfo.gameParameters.victoryTypes.removeAll { it !in ruleset.victories.keys } gameSetupInfo.gameParameters.victoryTypes.removeAll { it !in ruleset.victories.keys }
@ -365,7 +365,7 @@ class NewGameScreen(
* *
* @return Success - failure means gameSetupInfo was reset to defaults and the Ruleset was reverted to G&K * @return Success - failure means gameSetupInfo was reset to defaults and the Ruleset was reverted to G&K
*/ */
fun tryUpdateRuleset(): Boolean { fun tryUpdateRuleset(updateUI: Boolean): Boolean {
var success = true var success = true
fun handleFailure(message: String): Ruleset { fun handleFailure(message: String): Ruleset {
success = false success = false
@ -388,6 +388,8 @@ class NewGameScreen(
ruleset.add(newRuleset) ruleset.add(newRuleset)
ImageGetter.setNewRuleset(ruleset) ImageGetter.setNewRuleset(ruleset)
game.musicController.setModList(gameSetupInfo.gameParameters.getModsAndBaseRuleset()) game.musicController.setModList(gameSetupInfo.gameParameters.getModsAndBaseRuleset())
if (updateUI) newGameOptionsTable.updateRuleset(ruleset)
return success return success
} }