mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-24 03:53:12 -04:00
Harden new game screen against bad scenarios (#13826)
* Refactor and lint ScenarioSelectTable * Catch and display scenario file parsing errors
This commit is contained in:
parent
8c2fada877
commit
c01d72feb6
@ -379,6 +379,7 @@ Custom =
|
|||||||
Map Generation Type =
|
Map Generation Type =
|
||||||
Enabled Map Generation Types =
|
Enabled Map Generation Types =
|
||||||
Example map =
|
Example map =
|
||||||
|
Scenario file [name] is invalid. =
|
||||||
|
|
||||||
# Map types
|
# Map types
|
||||||
Default =
|
Default =
|
||||||
|
@ -1,67 +1,11 @@
|
|||||||
package com.unciv.ui.screens.newgamescreen
|
package com.unciv.ui.screens.newgamescreen
|
||||||
|
|
||||||
import com.badlogic.gdx.files.FileHandle
|
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||||
import com.unciv.Constants
|
|
||||||
import com.unciv.logic.GameInfoPreview
|
|
||||||
import com.unciv.logic.map.MapGeneratedMainType
|
import com.unciv.logic.map.MapGeneratedMainType
|
||||||
import com.unciv.models.ruleset.Ruleset
|
|
||||||
import com.unciv.ui.components.extensions.toLabel
|
import com.unciv.ui.components.extensions.toLabel
|
||||||
import com.unciv.ui.components.input.onChange
|
import com.unciv.ui.components.input.onChange
|
||||||
import com.unciv.ui.components.widgets.TranslatedSelectBox
|
import com.unciv.ui.components.widgets.TranslatedSelectBox
|
||||||
import com.unciv.ui.screens.basescreen.BaseScreen
|
import com.unciv.ui.screens.basescreen.BaseScreen
|
||||||
import com.unciv.utils.Concurrency
|
|
||||||
|
|
||||||
class ScenarioSelectTable(val newGameScreen: NewGameScreen) : Table() {
|
|
||||||
|
|
||||||
data class ScenarioData(val name:String, val file: FileHandle){
|
|
||||||
var preview: GameInfoPreview? = null
|
|
||||||
}
|
|
||||||
|
|
||||||
val scenarios = HashMap<String, ScenarioData>()
|
|
||||||
lateinit var selectedScenario: ScenarioData
|
|
||||||
var scenarioSelectBox: TranslatedSelectBox? = null
|
|
||||||
|
|
||||||
init {
|
|
||||||
// Only the first so it's fast
|
|
||||||
val firstScenarioFile = newGameScreen.game.files.getScenarioFiles().firstOrNull()
|
|
||||||
if (firstScenarioFile != null) {
|
|
||||||
createScenarioSelectBox(listOf(firstScenarioFile))
|
|
||||||
Concurrency.run {
|
|
||||||
val scenarioFiles = newGameScreen.game.files.getScenarioFiles().toList()
|
|
||||||
Concurrency.runOnGLThread {
|
|
||||||
createScenarioSelectBox(scenarioFiles)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createScenarioSelectBox(scenarioFiles: List<Pair<FileHandle, Ruleset>>) {
|
|
||||||
for ((file, _) in scenarioFiles)
|
|
||||||
scenarios[file.name()] = ScenarioData(file.name(), file)
|
|
||||||
|
|
||||||
scenarioSelectBox = TranslatedSelectBox(scenarios.keys.sorted(), scenarios.keys.first())
|
|
||||||
scenarioSelectBox!!.onChange { selectScenario() }
|
|
||||||
clear()
|
|
||||||
add(scenarioSelectBox)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun selectScenario(){
|
|
||||||
val scenario = scenarios[scenarioSelectBox!!.selected.value]!!
|
|
||||||
val preload = if (scenario.preview != null) scenario.preview!! else {
|
|
||||||
val preview = newGameScreen.game.files.loadGamePreviewFromFile(scenario.file)
|
|
||||||
scenario.preview = preview
|
|
||||||
preview
|
|
||||||
}
|
|
||||||
newGameScreen.gameSetupInfo.gameParameters.players = preload.gameParameters.players
|
|
||||||
.apply { removeAll { it.chosenCiv == Constants.spectator } }
|
|
||||||
newGameScreen.gameSetupInfo.gameParameters.baseRuleset = preload.gameParameters.baseRuleset
|
|
||||||
newGameScreen.gameSetupInfo.gameParameters.mods = preload.gameParameters.mods
|
|
||||||
newGameScreen.tryUpdateRuleset(true)
|
|
||||||
newGameScreen.playerPickerTable.update()
|
|
||||||
selectedScenario = scenario
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MapOptionsTable(private val newGameScreen: NewGameScreen) : Table() {
|
class MapOptionsTable(private val newGameScreen: NewGameScreen) : Table() {
|
||||||
|
|
||||||
@ -126,8 +70,8 @@ class MapOptionsTable(private val newGameScreen: NewGameScreen) : Table() {
|
|||||||
add(mapTypeSelectWrapper).pad(10f).fillX().row()
|
add(mapTypeSelectWrapper).pad(10f).fillX().row()
|
||||||
add(mapTypeSpecificTable).row()
|
add(mapTypeSpecificTable).row()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getSelectedScenario(): ScenarioSelectTable.ScenarioData? {
|
internal fun getSelectedScenario(): ScenarioSelectTable.ScenarioData? {
|
||||||
if (mapTypeSelectBox.selected.value != MapGeneratedMainType.scenario) return null
|
if (mapTypeSelectBox.selected.value != MapGeneratedMainType.scenario) return null
|
||||||
return scenarioOptionsTable.selectedScenario
|
return scenarioOptionsTable.selectedScenario
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,71 @@
|
|||||||
|
package com.unciv.ui.screens.newgamescreen
|
||||||
|
|
||||||
|
import com.badlogic.gdx.files.FileHandle
|
||||||
|
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||||
|
import com.badlogic.gdx.utils.SerializationException
|
||||||
|
import com.unciv.Constants
|
||||||
|
import com.unciv.logic.GameInfoPreview
|
||||||
|
import com.unciv.logic.files.UncivFiles
|
||||||
|
import com.unciv.models.ruleset.Ruleset
|
||||||
|
import com.unciv.ui.components.input.onChange
|
||||||
|
import com.unciv.ui.components.widgets.TranslatedSelectBox
|
||||||
|
import com.unciv.ui.popups.ToastPopup
|
||||||
|
import com.unciv.utils.Concurrency
|
||||||
|
|
||||||
|
internal class ScenarioSelectTable(private val newGameScreen: NewGameScreen) : Table() {
|
||||||
|
|
||||||
|
data class ScenarioData(val name:String, val file: FileHandle) {
|
||||||
|
var preview: GameInfoPreview? = null
|
||||||
|
}
|
||||||
|
|
||||||
|
val scenarios = HashMap<String, ScenarioData>()
|
||||||
|
var selectedScenario: ScenarioData? = null
|
||||||
|
private var scenarioSelectBox: TranslatedSelectBox? = null
|
||||||
|
|
||||||
|
init {
|
||||||
|
// Only the first so it's fast
|
||||||
|
val firstScenarioFile = newGameScreen.game.files.getScenarioFiles().firstOrNull()
|
||||||
|
if (firstScenarioFile != null) {
|
||||||
|
createScenarioSelectBox(listOf(firstScenarioFile))
|
||||||
|
Concurrency.run {
|
||||||
|
val scenarioFiles = newGameScreen.game.files.getScenarioFiles().toList()
|
||||||
|
Concurrency.runOnGLThread {
|
||||||
|
createScenarioSelectBox(scenarioFiles)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createScenarioSelectBox(scenarioFiles: List<Pair<FileHandle, Ruleset>>) {
|
||||||
|
for ((file, _) in scenarioFiles)
|
||||||
|
scenarios[file.name()] = ScenarioData(file.name(), file)
|
||||||
|
|
||||||
|
scenarioSelectBox = TranslatedSelectBox(scenarios.keys.sorted(), scenarios.keys.first())
|
||||||
|
scenarioSelectBox!!.onChange { selectScenario() }
|
||||||
|
clear()
|
||||||
|
add(scenarioSelectBox)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun selectScenario() {
|
||||||
|
val scenario = scenarios[scenarioSelectBox!!.selected.value]!!
|
||||||
|
val preload = scenario.getCachedPreview() ?: return
|
||||||
|
newGameScreen.gameSetupInfo.gameParameters.players = preload.gameParameters.players
|
||||||
|
.apply { removeAll { it.chosenCiv == Constants.spectator } }
|
||||||
|
newGameScreen.gameSetupInfo.gameParameters.baseRuleset = preload.gameParameters.baseRuleset
|
||||||
|
newGameScreen.gameSetupInfo.gameParameters.mods = preload.gameParameters.mods
|
||||||
|
newGameScreen.tryUpdateRuleset(true)
|
||||||
|
newGameScreen.playerPickerTable.update()
|
||||||
|
selectedScenario = scenario
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ScenarioData.getCachedPreview(): GameInfoPreview? {
|
||||||
|
if (preview == null) {
|
||||||
|
try {
|
||||||
|
preview = newGameScreen.game.files.loadGamePreviewFromFile(file)
|
||||||
|
} catch (_: SerializationException) {
|
||||||
|
ToastPopup("Scenario file [${file.name()}] is invalid.", newGameScreen)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return preview
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user