diff --git a/assets/locales/en/terrarum.json b/assets/locales/en/terrarum.json index aec01884c..3d68e5433 100644 --- a/assets/locales/en/terrarum.json +++ b/assets/locales/en/terrarum.json @@ -38,7 +38,8 @@ "MENU_OPTIONS_NOTIFICATION_DISPLAY_DURATION": "Show notification for", "MENU_LABEL_STREAMING": "Livestreaming", "MENU_LABEL_EXTRA_JVM_ARGUMENTS": "Extra JVM Arguments", - "GAME_PREV_SAVE_WAS_LOADED": "The most recently saved game was corrupted.\nThe previously saved game was loaded.", + "GAME_PREV_SAVE_WAS_LOADED1": "The most recently saved game was corrupted.", + "GAME_PREV_SAVE_WAS_LOADED2": "The previously saved game was loaded.", "GAME_MORE_RECENT_AUTOSAVE1": "The Autosave is more recent than the manual save.", "GAME_MORE_RECENT_AUTOSAVE2": "Please select the saved game you want to load:" } \ No newline at end of file diff --git a/src/net/torvald/terrarum/SavegameCollection.kt b/src/net/torvald/terrarum/SavegameCollection.kt index c32b378e8..79865e018 100644 --- a/src/net/torvald/terrarum/SavegameCollection.kt +++ b/src/net/torvald/terrarum/SavegameCollection.kt @@ -1,5 +1,6 @@ package net.torvald.terrarum +import net.torvald.terrarum.App.printdbg import net.torvald.terrarum.savegame.DiskSkimmer import java.io.File @@ -34,4 +35,118 @@ class SavegameCollection(files0: List) { return files.first() } +} + +class SavegameCollectionPair(player: SavegameCollection?, world: SavegameCollection?) { + + private lateinit var manualPlayer: DiskSkimmer + private lateinit var manualWorld: DiskSkimmer + private lateinit var autoPlayer: DiskSkimmer + private lateinit var autoWorld: DiskSkimmer + + var status = 0 // 0: none available, 1: loadable manual save is newer than loadable auto; 2: loadable autosave is newer than loadable manual + private set + + var newerSaveIsDamaged = false // only when most recent save is corrupted + private set + + init { + printdbg(this, "init ($player, $world)") + + if (player != null && world != null) { + + printdbg(this, player.files.joinToString { it.diskFile.name }) + printdbg(this, world.files.joinToString { it.diskFile.name }) + + // if a pair of files were saved successfully, they must have identical lastModifiedTime() + var pc = 0; val pt = player.files[0].getLastModifiedTime() + var wc = 0; val wt = world.files[0].getLastModifiedTime() + while (pc < player.files.size && wc < world.files.size) { + val pcf = player.files[pc] + val pcm = pcf.getLastModifiedTime() + val wcf = world.files[wc] + val wcm = wcf.getLastModifiedTime() + + if (playerDiskNotDamaged(pcf) && worldDiskNotDamaged(wcf)) { + when (pcf.isAutosaved().toInt(1) or wcf.isAutosaved().toInt()) { + 3 -> { + autoPlayer = pcf + autoWorld = wcf + pc += 1 + wc += 1 + } + 0 -> { + manualPlayer = pcf + manualWorld = wcf + pc += 1 + wc += 1 + } + else -> { + if (pcm > wcm) + pc += 1 + else if (pcm == wcm) { + pc += 1 + wc += 1 + } + else + wc += 1 + } + } + + } + + + + if (::manualPlayer.isInitialized && ::manualWorld.isInitialized && ::autoPlayer.isInitialized && ::autoWorld.isInitialized) + break + } + + if (::manualPlayer.isInitialized && ::manualWorld.isInitialized && ::autoPlayer.isInitialized && ::autoWorld.isInitialized) { + status = if (manualPlayer.getLastModifiedTime() > autoPlayer.getLastModifiedTime()) 1 else 2 + + printdbg(this, "manualPlayer = ${manualPlayer.diskFile.path}") + printdbg(this, "manualWorld = ${manualWorld.diskFile.path}") + printdbg(this, "autoPlayer = ${autoPlayer.diskFile.path}") + printdbg(this, "autoWorld = ${autoWorld.diskFile.path}") + } + else if (::manualPlayer.isInitialized && ::manualWorld.isInitialized || ::autoPlayer.isInitialized && ::autoWorld.isInitialized) { + status = 1 + if (::manualPlayer.isInitialized) { + printdbg(this, "manualPlayer = ${manualPlayer.diskFile.path}") + printdbg(this, "manualWorld = ${manualWorld.diskFile.path}") + } + else { + printdbg(this, "autoPlayer = ${autoPlayer.diskFile.path}") + printdbg(this, "autoWorld = ${autoWorld.diskFile.path}") + } + } + else { + status = 0 + } + } + } + + private fun DiskSkimmer.isAutosaved() = this.getSaveMode().and(0b0000_0010) != 0 + + private fun playerDiskNotDamaged(disk: DiskSkimmer): Boolean { + return true + } + + private fun worldDiskNotDamaged(disk: DiskSkimmer): Boolean { + return true + } + + fun moreRecentAutosaveAvailable() = (status == 2) + fun saveAvaliable() = (status > 0) + + fun getManualSave(): Pair? { + if (status == 0) return null + return manualPlayer to manualWorld + } + + fun getAutoSave(): Pair? { + if (status != 2) return null + return autoPlayer to autoWorld + } + } \ No newline at end of file diff --git a/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt b/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt index 57a63b99a..7856becf0 100644 --- a/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt +++ b/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt @@ -26,6 +26,7 @@ import net.torvald.terrarum.gameitems.mouseInInteractableRange import net.torvald.terrarum.gameparticles.ParticleBase import net.torvald.terrarum.gameworld.GameWorld import net.torvald.terrarum.gameworld.WorldSimulator +import net.torvald.terrarum.langpack.Lang import net.torvald.terrarum.modulebasegame.gameactors.* import net.torvald.terrarum.modulebasegame.gameactors.physicssolver.CollisionSolver import net.torvald.terrarum.modulebasegame.gameitems.PickaxeCore @@ -716,6 +717,10 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) { gameUpdateGovernor.reset() + if (UILoadGovernor.previousSaveWasLoaded) { + sendNotification(listOf(Lang["GAME_PREV_SAVE_WAS_LOADED1"], Lang["GAME_PREV_SAVE_WAS_LOADED2"])) + } + gameFullyLoaded = true } diff --git a/src/net/torvald/terrarum/modulebasegame/TitleScreen.kt b/src/net/torvald/terrarum/modulebasegame/TitleScreen.kt index 424c2407d..b912ac20e 100644 --- a/src/net/torvald/terrarum/modulebasegame/TitleScreen.kt +++ b/src/net/torvald/terrarum/modulebasegame/TitleScreen.kt @@ -24,6 +24,7 @@ import net.torvald.terrarum.gameworld.GameWorld import net.torvald.terrarum.gameworld.WorldTime import net.torvald.terrarum.gameworld.fmod import net.torvald.terrarum.langpack.Lang +import net.torvald.terrarum.modulebasegame.ui.UILoadGovernor import net.torvald.terrarum.modulebasegame.ui.UIRemoCon import net.torvald.terrarum.modulebasegame.ui.UITitleRemoConYaml import net.torvald.terrarum.realestate.LandUtil @@ -237,6 +238,7 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) { printdbg(this, "update list of savegames") // to show "Continue" and "Load" on the titlescreen, uncomment this line App.updateListOfSavegames() + UILoadGovernor.reset() loadThingsWhileIntroIsVisible() diff --git a/src/net/torvald/terrarum/modulebasegame/ui/UIGraphicsControlPanel.kt b/src/net/torvald/terrarum/modulebasegame/ui/UIGraphicsControlPanel.kt index 7365e5114..221175b0c 100644 --- a/src/net/torvald/terrarum/modulebasegame/ui/UIGraphicsControlPanel.kt +++ b/src/net/torvald/terrarum/modulebasegame/ui/UIGraphicsControlPanel.kt @@ -7,6 +7,7 @@ import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.g2d.SpriteBatch import net.torvald.terrarum.App import net.torvald.terrarum.CommonResourcePool +import net.torvald.terrarum.INGAME import net.torvald.terrarum.ceilInt import net.torvald.terrarum.langpack.Lang import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull.Companion.CELL_COL diff --git a/src/net/torvald/terrarum/modulebasegame/ui/UILoadDemoSavefiles.kt b/src/net/torvald/terrarum/modulebasegame/ui/UILoadDemoSavefiles.kt index 237793d1c..8efd173eb 100644 --- a/src/net/torvald/terrarum/modulebasegame/ui/UILoadDemoSavefiles.kt +++ b/src/net/torvald/terrarum/modulebasegame/ui/UILoadDemoSavefiles.kt @@ -57,6 +57,11 @@ val SAVE_CELL_HEIGHT = 120 * WARNING: the values are not guaranteed to reset when the selector UI is closed! */ object UILoadGovernor { + // used by the default save loader + var playerUUID: UUID? = null + var worldUUID: UUID? = null + var previousSaveWasLoaded = false + // used by the debug save loader var playerDisk: DiskSkimmer? = null set(value) { printdbg(this, "Player selected: ${value?.diskFile?.name}") @@ -73,6 +78,10 @@ object UILoadGovernor { printdbg(this, "Resetting player and world selection") playerDisk = null worldDisk = null + + playerUUID = null + worldUUID = null + previousSaveWasLoaded = false } } @@ -486,6 +495,8 @@ class UIItemPlayerCells( override var clickOnceListener: ((Int, Int) -> Unit)? = { _: Int, _: Int -> UILoadGovernor.playerDisk = skimmer + UILoadGovernor.playerUUID = playerUUID + UILoadGovernor.worldUUID = worldUUID parent.advanceMode() } @@ -494,12 +505,11 @@ class UIItemPlayerCells( private var lastPlayTime: String = "????-??-?? --:--:--" private var totalPlayTime: String = "--h--m--s" - private var playerUUID: UUID? = null + private lateinit var playerUUID: UUID + private lateinit var worldUUID: UUID init { skimmer.getFile(SAVEGAMEINFO)?.bytes?.let { - var playerUUID: UUID? = null - var worldUUID: UUID? = null var lastPlayTime0 = 0L JsonFetcher.readFromJsonString(ByteArray64Reader(it, Common.CHARSET)).forEachSiblings { name, value -> diff --git a/src/net/torvald/terrarum/modulebasegame/ui/UILoadSavegame.kt b/src/net/torvald/terrarum/modulebasegame/ui/UILoadSavegame.kt index ead2772d5..307028feb 100644 --- a/src/net/torvald/terrarum/modulebasegame/ui/UILoadSavegame.kt +++ b/src/net/torvald/terrarum/modulebasegame/ui/UILoadSavegame.kt @@ -134,17 +134,30 @@ class UILoadSavegame(val remoCon: UIRemoCon) : Advanceable() { // look for recently played world if (mode == 1) { - UILoadGovernor.playerDisk!!.getFile(SAVEGAMEINFO)?.bytes?.let { - var worldUUID: UUID? = null - JsonFetcher.readFromJsonString(ByteArray64Reader(it, Common.CHARSET)).forEachSiblings { name, value -> - if (name == "worldCurrentlyPlaying") worldUUID = UUID.fromString(value.asString()) - } - // TODO select the most recent loadable save by comparing manual and autosaves, NOT JUST going with loadable() - UILoadGovernor.worldDisk = App.savegameWorlds[worldUUID!!]!!.loadable() + // select the most recent loadable save by comparing manual and autosaves, NOT JUST going with loadable() + printdbg(this, "Load playerUUID: ${UILoadGovernor.playerUUID}, worldUUID: ${UILoadGovernor.worldUUID}") + val loadables = SavegameCollectionPair(App.savegamePlayers[UILoadGovernor.playerUUID], App.savegameWorlds[UILoadGovernor.worldUUID]) + + var loadAuto = false + if (loadables.moreRecentAutosaveAvailable()) { + // TODO make choice for load manual or auto, if available - mode += 1 } + else if (!loadables.saveAvaliable()) { + // TODO show save is damaged and cannot be loaded + return + } + + val (p, w) = if (loadAuto) loadables.getAutoSave()!! else loadables.getManualSave()!! + UILoadGovernor.playerDisk = p; UILoadGovernor.worldDisk = w + + if (loadables.newerSaveIsDamaged) { + // TODO queue message: GAME_PREV_SAVE_WAS_LOADED + } + + mode += 1 + } }