diff --git a/core/src/com/unciv/MainMenuScreen.kt b/core/src/com/unciv/MainMenuScreen.kt index 3364c3bad2..31e2c4c4bf 100644 --- a/core/src/com/unciv/MainMenuScreen.kt +++ b/core/src/com/unciv/MainMenuScreen.kt @@ -16,7 +16,7 @@ import com.unciv.logic.map.mapgenerator.MapGenerator import com.unciv.models.ruleset.RulesetCache import com.unciv.ui.MultiplayerScreen import com.unciv.ui.mapeditor.* -import com.unciv.ui.newgamescreen.GameSetupInfo +import com.unciv.models.metadata.GameSetupInfo import com.unciv.ui.newgamescreen.NewGameScreen import com.unciv.ui.pickerscreens.ModManagementScreen import com.unciv.ui.saves.LoadGameScreen @@ -236,7 +236,7 @@ class MainMenuScreen: CameraStageBaseScreen() { } private fun quickstartNewGame() { - val newGame = GameStarter.startNewGame(GameSetupInfo().apply { gameParameters.difficulty = "Chieftain" }) + val newGame = GameStarter.startNewGame(GameSetupInfo.fromSettings("Chieftain")) game.loadGame(newGame) } diff --git a/core/src/com/unciv/logic/GameStarter.kt b/core/src/com/unciv/logic/GameStarter.kt index 46e301e142..f19fa2bf5f 100644 --- a/core/src/com/unciv/logic/GameStarter.kt +++ b/core/src/com/unciv/logic/GameStarter.kt @@ -2,6 +2,7 @@ package com.unciv.logic import com.badlogic.gdx.math.Vector2 import com.unciv.Constants +import com.unciv.UncivGame import com.unciv.logic.civilization.* import com.unciv.logic.map.BFS import com.unciv.logic.map.TileInfo @@ -13,7 +14,7 @@ import com.unciv.models.ruleset.ModOptionsConstants import com.unciv.models.ruleset.Ruleset import com.unciv.models.ruleset.RulesetCache import com.unciv.models.ruleset.tile.ResourceType -import com.unciv.ui.newgamescreen.GameSetupInfo +import com.unciv.models.metadata.GameSetupInfo import java.util.* import kotlin.collections.ArrayList import kotlin.collections.HashMap @@ -90,6 +91,10 @@ object GameStarter { // This triggers the one-time greeting from Nation.startIntroPart1/2 addPlayerIntros(gameInfo) + UncivGame.Current.settings.apply { + lastGameSetup = gameSetupInfo + save() + } return gameInfo } diff --git a/core/src/com/unciv/logic/map/MapParameters.kt b/core/src/com/unciv/logic/map/MapParameters.kt index 2e0110c179..c25b524588 100644 --- a/core/src/com/unciv/logic/map/MapParameters.kt +++ b/core/src/com/unciv/logic/map/MapParameters.kt @@ -57,6 +57,13 @@ class MapSizeNew { this.radius = getEquivalentHexagonalRadius(width, height) } + fun clone() = MapSizeNew().also { + it.name = name + it.radius = radius + it.width = width + it.height = height + } + /** Check custom dimensions, fix if too extreme * @param worldWrap whether world wrap is on * @return null if size was acceptable, otherwise untranslated reason message @@ -141,6 +148,26 @@ class MapParameters { var resourceRichness = 0.1f var waterThreshold = 0f + fun clone() = MapParameters().also { + it.name = name + it.type = type + it.shape = shape + it.mapSize = mapSize.clone() + it.noRuins = noRuins + it.noNaturalWonders = noNaturalWonders + it.worldWrap = worldWrap + it.mods = LinkedHashSet(mods) + it.seed = seed + it.tilesPerBiomeArea = tilesPerBiomeArea + it.maxCoastExtension = maxCoastExtension + it.elevationExponent = elevationExponent + it.temperatureExtremeness = temperatureExtremeness + it.vegetationRichness = vegetationRichness + it.rareFeaturesRichness = rareFeaturesRichness + it.resourceRichness = resourceRichness + it.waterThreshold = waterThreshold + } + fun reseed() { seed = System.currentTimeMillis() } diff --git a/core/src/com/unciv/models/metadata/GameSettings.kt b/core/src/com/unciv/models/metadata/GameSettings.kt index 8586d21fa4..3dffd8f1d1 100644 --- a/core/src/com/unciv/models/metadata/GameSettings.kt +++ b/core/src/com/unciv/models/metadata/GameSettings.kt @@ -47,6 +47,9 @@ class GameSettings { var allowAndroidPortrait = false // Opt-in to allow Unciv to follow a screen rotation to portrait + /** Saves the last successful new game's setup */ + var lastGameSetup: GameSetupInfo? = null + init { // 26 = Android Oreo. Versions below may display permanent icon in notification bar. if (Gdx.app?.type == Application.ApplicationType.Android && Gdx.app.version < 26) { diff --git a/core/src/com/unciv/models/metadata/GameSetupInfo.kt b/core/src/com/unciv/models/metadata/GameSetupInfo.kt new file mode 100644 index 0000000000..cd765a1832 --- /dev/null +++ b/core/src/com/unciv/models/metadata/GameSetupInfo.kt @@ -0,0 +1,36 @@ +package com.unciv.models.metadata + +import com.badlogic.gdx.files.FileHandle +import com.unciv.UncivGame +import com.unciv.logic.GameInfo +import com.unciv.logic.map.MapParameters +import com.unciv.models.ruleset.Difficulty + +class GameSetupInfo( + var gameParameters: GameParameters = GameParameters(), + var mapParameters: MapParameters = MapParameters() +) { + @Transient + var mapFile: FileHandle? = null + + // This constructor is used for starting a new game from a running one, cloning the setup, including map seed + constructor(gameInfo: GameInfo) : this(gameInfo.gameParameters.clone(), gameInfo.tileMap.mapParameters.clone()) + // Cloning constructor used for [fromSettings] and [GameParametersScreen], reseeds map + constructor(setup: GameSetupInfo): this(setup.gameParameters.clone(), setup.mapParameters.clone()) + + companion object { + /** + * Get a cloned and reseeded [GameSetupInfo] from saved settings if present, otherwise a default instance. + * @param defaultDifficulty Overrides difficulty only when no saved settings found, so a virgin + * Unciv installation can QuickStart with a different difficulty than New Game defaults to. + */ + fun fromSettings(defaultDifficulty: String? = null) = UncivGame.Current.settings.run { + if (lastGameSetup == null) GameSetupInfo().apply { + if (defaultDifficulty != null) gameParameters.difficulty = defaultDifficulty + } + else GameSetupInfo(lastGameSetup!!).apply { + mapParameters.reseed() + } + } + } +} \ No newline at end of file diff --git a/core/src/com/unciv/models/simulation/Simulation.kt b/core/src/com/unciv/models/simulation/Simulation.kt index 8b9ead7770..af27a1874b 100644 --- a/core/src/com/unciv/models/simulation/Simulation.kt +++ b/core/src/com/unciv/models/simulation/Simulation.kt @@ -3,7 +3,7 @@ package com.unciv.models.simulation import com.unciv.logic.GameInfo import com.unciv.logic.GameStarter import com.unciv.models.ruleset.VictoryType -import com.unciv.ui.newgamescreen.GameSetupInfo +import com.unciv.models.metadata.GameSetupInfo import java.lang.Integer.max import java.time.Duration import kotlin.concurrent.thread diff --git a/core/src/com/unciv/ui/mapeditor/GameParametersScreen.kt b/core/src/com/unciv/ui/mapeditor/GameParametersScreen.kt index 6c4684955a..1c499ca42b 100644 --- a/core/src/com/unciv/ui/mapeditor/GameParametersScreen.kt +++ b/core/src/com/unciv/ui/mapeditor/GameParametersScreen.kt @@ -5,6 +5,7 @@ import com.unciv.UncivGame import com.unciv.models.ruleset.RulesetCache import com.unciv.models.translations.tr import com.unciv.ui.newgamescreen.GameOptionsTable +import com.unciv.models.metadata.GameSetupInfo import com.unciv.ui.newgamescreen.PlayerPickerTable import com.unciv.ui.newgamescreen.IPreviousScreen import com.unciv.ui.pickerscreens.PickerScreen @@ -18,7 +19,7 @@ import com.unciv.ui.utils.* * @param [mapEditorScreen] previous screen from map editor. */ class GameParametersScreen(var mapEditorScreen: MapEditorScreen): IPreviousScreen, PickerScreen(disableScroll = true) { - override var gameSetupInfo = mapEditorScreen.gameSetupInfo.clone() + override var gameSetupInfo = GameSetupInfo(mapEditorScreen.gameSetupInfo) override var ruleset = RulesetCache.getComplexRuleset(gameSetupInfo.gameParameters.mods) var playerPickerTable = PlayerPickerTable(this, gameSetupInfo.gameParameters) var gameOptionsTable = GameOptionsTable(this) { desiredCiv: String -> playerPickerTable.update(desiredCiv) } diff --git a/core/src/com/unciv/ui/mapeditor/MapEditorScreen.kt b/core/src/com/unciv/ui/mapeditor/MapEditorScreen.kt index 768480bb0f..ed4f813340 100644 --- a/core/src/com/unciv/ui/mapeditor/MapEditorScreen.kt +++ b/core/src/com/unciv/ui/mapeditor/MapEditorScreen.kt @@ -10,7 +10,7 @@ import com.unciv.logic.map.TileInfo import com.unciv.logic.map.TileMap import com.unciv.models.ruleset.Ruleset import com.unciv.models.ruleset.RulesetCache -import com.unciv.ui.newgamescreen.GameSetupInfo +import com.unciv.models.metadata.GameSetupInfo import com.unciv.ui.utils.* class MapEditorScreen(): CameraStageBaseScreen() { diff --git a/core/src/com/unciv/ui/newgamescreen/IPreviousScreen.kt b/core/src/com/unciv/ui/newgamescreen/IPreviousScreen.kt index 1d0d9d090c..a688b57aca 100644 --- a/core/src/com/unciv/ui/newgamescreen/IPreviousScreen.kt +++ b/core/src/com/unciv/ui/newgamescreen/IPreviousScreen.kt @@ -1,6 +1,7 @@ package com.unciv.ui.newgamescreen import com.badlogic.gdx.scenes.scene2d.Stage +import com.unciv.models.metadata.GameSetupInfo import com.unciv.models.ruleset.Ruleset /** diff --git a/core/src/com/unciv/ui/newgamescreen/NewGameScreen.kt b/core/src/com/unciv/ui/newgamescreen/NewGameScreen.kt index a70962ec93..f528b4b68a 100644 --- a/core/src/com/unciv/ui/newgamescreen/NewGameScreen.kt +++ b/core/src/com/unciv/ui/newgamescreen/NewGameScreen.kt @@ -1,7 +1,6 @@ package com.unciv.ui.newgamescreen import com.badlogic.gdx.Gdx -import com.badlogic.gdx.files.FileHandle import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.scenes.scene2d.ui.SelectBox import com.badlogic.gdx.scenes.scene2d.ui.Skin @@ -9,41 +8,24 @@ import com.badlogic.gdx.utils.Array import com.unciv.UncivGame import com.unciv.logic.* import com.unciv.logic.civilization.PlayerType -import com.unciv.logic.map.MapParameters import com.unciv.logic.map.MapType -import com.unciv.models.metadata.GameParameters +import com.unciv.models.metadata.GameSetupInfo import com.unciv.models.ruleset.RulesetCache import com.unciv.models.translations.tr import com.unciv.ui.pickerscreens.PickerScreen import com.unciv.ui.utils.* import com.unciv.ui.worldscreen.mainmenu.OnlineMultiplayer import java.util.* -import kotlin.collections.HashSet import kotlin.concurrent.thread import com.unciv.ui.utils.AutoScrollPane as ScrollPane -class GameSetupInfo(var gameId:String, var gameParameters: GameParameters, var mapParameters: MapParameters) { - var mapFile: FileHandle? = null - constructor() : this("", GameParameters(), MapParameters()) - constructor(gameInfo: GameInfo) : this("", gameInfo.gameParameters.clone(), gameInfo.tileMap.mapParameters) - constructor(gameParameters: GameParameters, mapParameters: MapParameters) : this("", gameParameters, mapParameters) - - fun clone(): GameSetupInfo { - val toReturn = GameSetupInfo() - toReturn.gameId = this.gameId - toReturn.gameParameters = this.gameParameters - toReturn.mapParameters = this.mapParameters - return toReturn - } -} - class NewGameScreen( private val previousScreen: CameraStageBaseScreen, _gameSetupInfo: GameSetupInfo? = null ): IPreviousScreen, PickerScreen() { - override val gameSetupInfo = _gameSetupInfo ?: GameSetupInfo() + override val gameSetupInfo = _gameSetupInfo ?: GameSetupInfo.fromSettings() override var ruleset = RulesetCache.getComplexRuleset(gameSetupInfo.gameParameters.mods) // needs to be set because the GameOptionsTable etc. depend on this private val newGameOptionsTable = GameOptionsTable(this, isNarrowerThan4to3()) { desiredCiv: String -> playerPickerTable.update(desiredCiv) } diff --git a/core/src/com/unciv/ui/victoryscreen/VictoryScreen.kt b/core/src/com/unciv/ui/victoryscreen/VictoryScreen.kt index 8db7db3979..e9c37ce144 100644 --- a/core/src/com/unciv/ui/victoryscreen/VictoryScreen.kt +++ b/core/src/com/unciv/ui/victoryscreen/VictoryScreen.kt @@ -9,7 +9,7 @@ import com.unciv.models.ruleset.Policy import com.unciv.models.ruleset.VictoryType import com.unciv.models.translations.getPlaceholderParameters import com.unciv.models.translations.tr -import com.unciv.ui.newgamescreen.GameSetupInfo +import com.unciv.models.metadata.GameSetupInfo import com.unciv.ui.newgamescreen.NewGameScreen import com.unciv.ui.overviewscreen.EmpireOverviewScreen import com.unciv.ui.pickerscreens.PickerScreen diff --git a/core/src/com/unciv/ui/worldscreen/mainmenu/WorldScreenMenuPopup.kt b/core/src/com/unciv/ui/worldscreen/mainmenu/WorldScreenMenuPopup.kt index 95ff5a2392..934724c155 100644 --- a/core/src/com/unciv/ui/worldscreen/mainmenu/WorldScreenMenuPopup.kt +++ b/core/src/com/unciv/ui/worldscreen/mainmenu/WorldScreenMenuPopup.kt @@ -3,7 +3,7 @@ package com.unciv.ui.worldscreen.mainmenu import com.badlogic.gdx.Gdx import com.unciv.MainMenuScreen import com.unciv.ui.civilopedia.CivilopediaScreen -import com.unciv.ui.newgamescreen.GameSetupInfo +import com.unciv.models.metadata.GameSetupInfo import com.unciv.ui.newgamescreen.NewGameScreen import com.unciv.ui.saves.LoadGameScreen import com.unciv.ui.saves.SaveGameScreen diff --git a/desktop/src/com/unciv/app/desktop/ConsoleLauncher.kt b/desktop/src/com/unciv/app/desktop/ConsoleLauncher.kt index 866e48021c..051e51829c 100644 --- a/desktop/src/com/unciv/app/desktop/ConsoleLauncher.kt +++ b/desktop/src/com/unciv/app/desktop/ConsoleLauncher.kt @@ -14,7 +14,7 @@ import com.unciv.models.metadata.Player import com.unciv.models.ruleset.RulesetCache import com.unciv.models.simulation.Simulation import com.unciv.models.tilesets.TileSetCache -import com.unciv.ui.newgamescreen.GameSetupInfo +import com.unciv.models.metadata.GameSetupInfo internal object ConsoleLauncher { @JvmStatic diff --git a/tests/src/com/unciv/testing/SerializationTests.kt b/tests/src/com/unciv/testing/SerializationTests.kt index c2ce75ec2d..2e1239555b 100644 --- a/tests/src/com/unciv/testing/SerializationTests.kt +++ b/tests/src/com/unciv/testing/SerializationTests.kt @@ -13,7 +13,7 @@ import com.unciv.models.metadata.GameParameters import com.unciv.models.metadata.GameSettings import com.unciv.models.metadata.Player import com.unciv.models.ruleset.RulesetCache -import com.unciv.ui.newgamescreen.GameSetupInfo +import com.unciv.models.metadata.GameSetupInfo import org.junit.Assert import org.junit.Before import org.junit.Test