mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-23 11:34:54 -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 =
|
||||
Enabled Map Generation Types =
|
||||
Example map =
|
||||
Scenario file [name] is invalid. =
|
||||
|
||||
# Map types
|
||||
Default =
|
||||
|
@ -1,67 +1,11 @@
|
||||
package com.unciv.ui.screens.newgamescreen
|
||||
|
||||
import com.badlogic.gdx.files.FileHandle
|
||||
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.models.ruleset.Ruleset
|
||||
import com.unciv.ui.components.extensions.toLabel
|
||||
import com.unciv.ui.components.input.onChange
|
||||
import com.unciv.ui.components.widgets.TranslatedSelectBox
|
||||
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() {
|
||||
|
||||
@ -127,7 +71,7 @@ class MapOptionsTable(private val newGameScreen: NewGameScreen) : Table() {
|
||||
add(mapTypeSpecificTable).row()
|
||||
}
|
||||
|
||||
fun getSelectedScenario(): ScenarioSelectTable.ScenarioData? {
|
||||
internal fun getSelectedScenario(): ScenarioSelectTable.ScenarioData? {
|
||||
if (mapTypeSelectBox.selected.value != MapGeneratedMainType.scenario) return null
|
||||
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