List of saved games is now returned as a series of file hanldes - this means there's a lot less ping-ponging between the game name and the file in all kinds of places

This commit is contained in:
Yair Morgenstern
2020-08-14 14:28:47 +03:00
parent 4046837a3e
commit 1261b1de30
5 changed files with 42 additions and 38 deletions

View File

@ -31,18 +31,21 @@ object GameSaver {
return externalFile return externalFile
} }
fun getSaves(multiplayer: Boolean = false): Sequence<String> { fun getSaves(multiplayer: Boolean = false): Sequence<FileHandle> {
val localSaves = Gdx.files.local(getSubfolder(multiplayer)).list().asSequence().map { it.name() } val localSaves = Gdx.files.local(getSubfolder(multiplayer)).list().asSequence()
if (externalFilesDirForAndroid == "" || !Gdx.files.isExternalStorageAvailable) return localSaves if (externalFilesDirForAndroid == "" || !Gdx.files.isExternalStorageAvailable) return localSaves
return localSaves + Gdx.files.absolute(externalFilesDirForAndroid + "/${getSubfolder(multiplayer)}").list().asSequence().map { it.name() } return localSaves + Gdx.files.absolute(externalFilesDirForAndroid + "/${getSubfolder(multiplayer)}").list().asSequence()
} }
fun saveGame(game: GameInfo, GameName: String, multiplayer: Boolean = false) { fun saveGame(game: GameInfo, GameName: String, multiplayer: Boolean = false) {
json().toJson(game,getSave(GameName, multiplayer)) json().toJson(game,getSave(GameName, multiplayer))
} }
fun loadGameByName(GameName: String, multiplayer: Boolean = false) : GameInfo { fun loadGameByName(GameName: String, multiplayer: Boolean = false) =
val game = json().fromJson(GameInfo::class.java, getSave(GameName, multiplayer)) loadGameFromFile(getSave(GameName, multiplayer))
fun loadGameFromFile(gameFile: FileHandle): GameInfo {
val game = json().fromJson(GameInfo::class.java, gameFile)
game.setTransients() game.setTransients()
return game return game
} }
@ -110,10 +113,10 @@ object GameSaver {
val newAutosaveFilename = saveFilesFolder + File.separator + "Autosave-${gameInfo.currentPlayer}-${gameInfo.turns}" val newAutosaveFilename = saveFilesFolder + File.separator + "Autosave-${gameInfo.currentPlayer}-${gameInfo.turns}"
getSave("Autosave").copyTo(Gdx.files.local(newAutosaveFilename)) getSave("Autosave").copyTo(Gdx.files.local(newAutosaveFilename))
fun getAutosaves(): Sequence<String> { return getSaves().filter { it.startsWith("Autosave") } } fun getAutosaves(): Sequence<FileHandle> { return getSaves().filter { it.name().startsWith("Autosave") } }
while(getAutosaves().count()>10){ while(getAutosaves().count()>10){
val saveToDelete = getAutosaves().minBy { getSave(it).lastModified() }!! val saveToDelete = getAutosaves().minBy { it.lastModified() }!!
deleteSave(saveToDelete) deleteSave(saveToDelete.name())
} }
} }

View File

@ -2,6 +2,7 @@ package com.unciv.ui
import com.unciv.ui.utils.AutoScrollPane as ScrollPane import com.unciv.ui.utils.AutoScrollPane as ScrollPane
import com.badlogic.gdx.Gdx import com.badlogic.gdx.Gdx
import com.badlogic.gdx.files.FileHandle
import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.ui.* import com.badlogic.gdx.scenes.scene2d.ui.*
import com.unciv.logic.GameInfo import com.unciv.logic.GameInfo
@ -18,7 +19,7 @@ class MultiplayerScreen(previousScreen: CameraStageBaseScreen) : PickerScreen()
private lateinit var selectedGame: GameInfo private lateinit var selectedGame: GameInfo
private lateinit var selectedGameName: String private lateinit var selectedGameName: String
private var multiplayerGameList = mutableMapOf<String, String>() private var multiplayerGameList = mutableMapOf<String, FileHandle>()
private val rightSideTable = Table() private val rightSideTable = Table()
private val leftSideTable = Table() private val leftSideTable = Table()
@ -186,7 +187,7 @@ class MultiplayerScreen(previousScreen: CameraStageBaseScreen) : PickerScreen()
fun reloadGameListUI() { fun reloadGameListUI() {
val leftSubTable = Table() val leftSubTable = Table()
val gameSaver = GameSaver val gameSaver = GameSaver
val savedGames: Sequence<String> val savedGames: Sequence<FileHandle>
try { try {
savedGames = gameSaver.getSaves(true) savedGames = gameSaver.getSaves(true)
@ -199,14 +200,14 @@ class MultiplayerScreen(previousScreen: CameraStageBaseScreen) : PickerScreen()
return return
} }
for (gameSaveName in savedGames) { for (gameSaveFile in savedGames) {
try { try {
val gameTable = Table() val gameTable = Table()
val game = gameSaver.loadGameByName(gameSaveName, true) val game = gameSaver.loadGameFromFile(gameSaveFile)
//Add games to list so saves don't have to be loaded as Files so often //Add games to list so saves don't have to be loaded as Files so often
if (!gameIsAlreadySavedAsMultiplayer(game.gameId)) if (!gameIsAlreadySavedAsMultiplayer(game.gameId))
multiplayerGameList[game.gameId] = gameSaveName multiplayerGameList[game.gameId] = gameSaveFile
if (isUsersTurn(game)) { if (isUsersTurn(game)) {
gameTable.add(ImageGetter.getNationIndicator(game.currentPlayerCiv.nation, 45f)) gameTable.add(ImageGetter.getNationIndicator(game.currentPlayerCiv.nation, 45f))
@ -214,11 +215,11 @@ class MultiplayerScreen(previousScreen: CameraStageBaseScreen) : PickerScreen()
gameTable.add() gameTable.add()
} }
val lastModifiedMillis = gameSaver.getSave(gameSaveName, true).lastModified() val lastModifiedMillis = gameSaveFile.lastModified()
val gameButton = TextButton(gameSaveName, skin) val gameButton = gameSaveFile.name().toTextButton()
gameButton.onClick { gameButton.onClick {
selectedGame = game selectedGame = game
selectedGameName = gameSaveName selectedGameName = gameSaveFile.name()
copyGameIdButton.enable() copyGameIdButton.enable()
editButton.enable() editButton.enable()
rightSideButton.enable() rightSideButton.enable()
@ -254,7 +255,7 @@ class MultiplayerScreen(previousScreen: CameraStageBaseScreen) : PickerScreen()
for (gameId in multiplayerGameList.keys) { for (gameId in multiplayerGameList.keys) {
try { try {
val game = OnlineMultiplayer().tryDownloadGame(gameId) val game = OnlineMultiplayer().tryDownloadGame(gameId)
GameSaver.saveGame(game, multiplayerGameList.getValue(gameId), true) GameSaver.saveGame(game, multiplayerGameList.getValue(gameId).name(), true)
} catch (ex: Exception) { } catch (ex: Exception) {
//skipping one is not fatal //skipping one is not fatal
//Trying to use as many prev. used strings as possible //Trying to use as many prev. used strings as possible

View File

@ -1,5 +1,6 @@
package com.unciv.ui.newgamescreen package com.unciv.ui.newgamescreen
import com.badlogic.gdx.files.FileHandle
import com.badlogic.gdx.scenes.scene2d.ui.SelectBox import com.badlogic.gdx.scenes.scene2d.ui.SelectBox
import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.utils.Array import com.badlogic.gdx.utils.Array
@ -29,10 +30,10 @@ class MapOptionsTable(val newGameScreen: NewGameScreen): Table() {
addMapTypeSelection() addMapTypeSelection()
} }
fun selectSavedGameAsScenario(gameName: String){ fun selectSavedGameAsScenario(gameFile: FileHandle){
val savedGame = GameSaver.loadGameByName(gameName) val savedGame = GameSaver.loadGameFromFile(gameFile)
mapParameters.type = MapType.scenario mapParameters.type = MapType.scenario
mapParameters.name = gameName mapParameters.name = gameFile.name()
newGameScreen.gameSetupInfo.gameParameters = savedGame.gameParameters newGameScreen.gameSetupInfo.gameParameters = savedGame.gameParameters
newGameScreen.gameSetupInfo.mapParameters = savedGame.tileMap.mapParameters newGameScreen.gameSetupInfo.mapParameters = savedGame.tileMap.mapParameters
newGameScreen.updateRuleset() newGameScreen.updateRuleset()
@ -46,7 +47,7 @@ class MapOptionsTable(val newGameScreen: NewGameScreen): Table() {
if (MapSaver.getMaps().isNotEmpty()) mapTypes.add(MapType.custom) if (MapSaver.getMaps().isNotEmpty()) mapTypes.add(MapType.custom)
if (MapSaver.getScenarios().isNotEmpty() && UncivGame.Current.settings.extendedMapEditor) if (MapSaver.getScenarios().isNotEmpty() && UncivGame.Current.settings.extendedMapEditor)
mapTypes.add(MapType.scenarioMap) mapTypes.add(MapType.scenarioMap)
if (GameSaver.getSaves().any { it.toLowerCase().endsWith("scenario") }) if (GameSaver.getSaves().any { it.name().toLowerCase().endsWith("scenario") })
mapTypes.add(MapType.scenario) mapTypes.add(MapType.scenario)
mapTypeSelectBox = TranslatedSelectBox(mapTypes, "Generated", CameraStageBaseScreen.skin) mapTypeSelectBox = TranslatedSelectBox(mapTypes, "Generated", CameraStageBaseScreen.skin)
@ -66,13 +67,13 @@ class MapOptionsTable(val newGameScreen: NewGameScreen): Table() {
.right().row() .right().row()
val scenarioSelectBox = SelectBox<String>(CameraStageBaseScreen.skin) val scenarioSelectBox = SelectBox<FileHandle>(CameraStageBaseScreen.skin)
for (savedGame in GameSaver.getSaves()) { for (savedGame in GameSaver.getSaves()) {
if (savedGame.toLowerCase().endsWith("scenario")) if (savedGame.name().toLowerCase().endsWith("scenario"))
scenarioSelectBox.items.add(savedGame) scenarioSelectBox.items.add(savedGame)
} }
scenarioSelectBox.items = scenarioSelectBox.items // it doesn't register them until you do this. scenarioSelectBox.items = scenarioSelectBox.items // it doesn't register them until you do this.
scenarioSelectBox.selected = scenarioMapSelectBox.items.first() scenarioSelectBox.selected = scenarioSelectBox.items.first()
// needs to be after the item change, so it doesn't activate before we choose the Scenario maptype // needs to be after the item change, so it doesn't activate before we choose the Scenario maptype
scenarioSelectBox.onChange { selectSavedGameAsScenario(scenarioSelectBox.selected) } scenarioSelectBox.onChange { selectSavedGameAsScenario(scenarioSelectBox.selected) }
scenarioOptionsTable.add("{Scenario file}:".toLabel()).left() scenarioOptionsTable.add("{Scenario file}:".toLabel()).left()

View File

@ -114,20 +114,20 @@ class LoadGameScreen(previousScreen:CameraStageBaseScreen) : PickerScreen() {
private fun updateLoadableGames(showAutosaves:Boolean) { private fun updateLoadableGames(showAutosaves:Boolean) {
saveTable.clear() saveTable.clear()
for (save in GameSaver.getSaves().sortedByDescending { GameSaver.getSave(it).lastModified() }) { for (save in GameSaver.getSaves().sortedByDescending { it.lastModified() }) {
if (save.startsWith("Autosave") && !showAutosaves) continue if (save.name().startsWith("Autosave") && !showAutosaves) continue
val textButton = TextButton(save, skin) val textButton = TextButton(save.name(), skin)
textButton.onClick { textButton.onClick {
selectedSave = save selectedSave = save.name()
copySavedGameToClipboardButton.enable() copySavedGameToClipboardButton.enable()
var textToSet = save var textToSet = save.name()
val savedAt = Date(GameSaver.getSave(save).lastModified()) val savedAt = Date(save.lastModified())
descriptionLabel.setText("Loading...".tr()) descriptionLabel.setText("Loading...".tr())
textToSet += "\n{Saved at}: ".tr() + SimpleDateFormat("yyyy-MM-dd HH:mm").format(savedAt) textToSet += "\n{Saved at}: ".tr() + SimpleDateFormat("yyyy-MM-dd HH:mm").format(savedAt)
thread { // Even loading the game to get its metadata can take a long time on older phones thread { // Even loading the game to get its metadata can take a long time on older phones
try { try {
val game = GameSaver.loadGameByName(save) val game = GameSaver.loadGameFromFile(save)
val playerCivNames = game.civilizations.filter { it.isPlayerCivilization() }.joinToString { it.civName.tr() } val playerCivNames = game.civilizations.filter { it.isPlayerCivilization() }.joinToString { it.civName.tr() }
textToSet += "\n" + playerCivNames + textToSet += "\n" + playerCivNames +
", " + game.difficulty.tr() + ", {Turn} ".tr() + game.turns ", " + game.difficulty.tr() + ", {Turn} ".tr() + game.turns
@ -137,7 +137,7 @@ class LoadGameScreen(previousScreen:CameraStageBaseScreen) : PickerScreen() {
Gdx.app.postRunnable { Gdx.app.postRunnable {
descriptionLabel.setText(textToSet) descriptionLabel.setText(textToSet)
rightSideButton.setText("Load [$save]".tr()) rightSideButton.setText("Load [${save.name()}]".tr())
rightSideButton.enable() rightSideButton.enable()
deleteSaveButton.enable() deleteSaveButton.enable()
deleteSaveButton.color = Color.RED deleteSaveButton.color = Color.RED

View File

@ -3,7 +3,6 @@ package com.unciv.ui.saves
import com.badlogic.gdx.Gdx import com.badlogic.gdx.Gdx
import com.badlogic.gdx.scenes.scene2d.ui.CheckBox import com.badlogic.gdx.scenes.scene2d.ui.CheckBox
import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
import com.badlogic.gdx.scenes.scene2d.ui.TextField import com.badlogic.gdx.scenes.scene2d.ui.TextField
import com.badlogic.gdx.utils.Json import com.badlogic.gdx.utils.Json
import com.unciv.UncivGame import com.unciv.UncivGame
@ -67,12 +66,12 @@ class SaveGameScreen : PickerScreen() {
fun updateShownSaves(showAutosaves: Boolean) { fun updateShownSaves(showAutosaves: Boolean) {
currentSaves.clear() currentSaves.clear()
val saves = GameSaver.getSaves() val saves = GameSaver.getSaves()
.sortedByDescending { GameSaver.getSave(it).lastModified() } .sortedByDescending { it.lastModified() }
for (saveGameName in saves) { for (saveGameFile in saves) {
if (saveGameName.startsWith("Autosave") && !showAutosaves) continue if (saveGameFile.name().startsWith("Autosave") && !showAutosaves) continue
val textButton = TextButton(saveGameName, skin) val textButton = saveGameFile.name().toTextButton()
textButton.onClick { textButton.onClick {
textField.text = saveGameName textField.text = saveGameFile.name()
} }
currentSaves.add(textButton).pad(5f).row() currentSaves.add(textButton).pad(5f).row()
} }