mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-08 23:08:35 +07:00
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:
@ -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())
|
||||||
|
@ -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) {
|
||||||
|
@ -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 -> {
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user