mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-12 11:34:05 +09:00
save juggling for autosaves
This commit is contained in:
@@ -410,14 +410,14 @@ open class IngameInstance(val batch: FlippingSpriteBatch, val isMultiplayer: Boo
|
|||||||
/**
|
/**
|
||||||
* Copies most recent `save` to `save.1`, leaving `save` for overwriting, previous `save.1` will be copied to `save.2`
|
* Copies most recent `save` to `save.1`, leaving `save` for overwriting, previous `save.1` will be copied to `save.2`
|
||||||
*/
|
*/
|
||||||
fun makeSavegameBackupCopy(file: File, isAuto: Boolean) {
|
fun makeSavegameBackupCopy(file: File) {
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val file1 = File("${file.absolutePath}.${if (isAuto) "a" else "1"}")
|
val file1 = File("${file.absolutePath}.1")
|
||||||
val file2 = File("${file.absolutePath}.${if (isAuto) "b" else "1"}")
|
val file2 = File("${file.absolutePath}.2")
|
||||||
val file3 = File("${file.absolutePath}.${if (isAuto) "c" else "1"}")
|
val file3 = File("${file.absolutePath}.3")
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// do not overwrite clean .2 with dirty .1
|
// do not overwrite clean .2 with dirty .1
|
||||||
@@ -442,6 +442,30 @@ open class IngameInstance(val batch: FlippingSpriteBatch, val isMultiplayer: Boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun makeSavegameBackupCopyAuto(file0: File): File {
|
||||||
|
val file1 = File("${file0.absolutePath}.a")
|
||||||
|
val file2 = File("${file0.absolutePath}.b")
|
||||||
|
val file3 = File("${file0.absolutePath}.c")
|
||||||
|
|
||||||
|
try {
|
||||||
|
// do not overwrite clean .2 with dirty .1
|
||||||
|
val flags3 = FileInputStream(file3).let { it.skip(49L); val r = it.read(); it.close(); r }
|
||||||
|
val flags2 = FileInputStream(file2).let { it.skip(49L); val r = it.read(); it.close(); r }
|
||||||
|
if (!(flags3 == 0 && flags2 != 0) || !file3.exists()) file1.copyTo(file3, true)
|
||||||
|
} catch (e: NoSuchFileException) {} catch (e: FileNotFoundException) {}
|
||||||
|
try {
|
||||||
|
if (file2.exists() && !file3.exists())
|
||||||
|
file2.copyTo(file3, true)
|
||||||
|
if (file1.exists() && !file2.exists())
|
||||||
|
file1.copyTo(file2, true)
|
||||||
|
|
||||||
|
file0.copyTo(file1, true)
|
||||||
|
} catch (e: IOException) {}
|
||||||
|
|
||||||
|
return file1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// simple euclidean norm, squared
|
// simple euclidean norm, squared
|
||||||
private val actorDistanceCalculator = DistanceCalculator<ActorWithBody> { t: ActorWithBody, p: PointND ->
|
private val actorDistanceCalculator = DistanceCalculator<ActorWithBody> { t: ActorWithBody, p: PointND ->
|
||||||
|
|||||||
@@ -421,10 +421,10 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
uiAutosaveNotifier.setAsOpen()
|
uiAutosaveNotifier.setAsOpen()
|
||||||
val saveTime_t = App.getTIME_T()
|
val saveTime_t = App.getTIME_T()
|
||||||
WriteSavegame.immediate(saveTime_t, WriteSavegame.SaveMode.PLAYER, playerDisk, getPlayerSaveFiledesc(playerSavefileName), this, true, autosaveOnErrorAction) {
|
WriteSavegame.immediate(saveTime_t, WriteSavegame.SaveMode.PLAYER, playerDisk, getPlayerSaveFiledesc(playerSavefileName), this, true, autosaveOnErrorAction) {
|
||||||
makeSavegameBackupCopy(getPlayerSaveFiledesc(playerSavefileName), true)
|
makeSavegameBackupCopy(getPlayerSaveFiledesc(playerSavefileName))
|
||||||
|
|
||||||
WriteSavegame.immediate(saveTime_t, WriteSavegame.SaveMode.WORLD, worldDisk, getWorldSaveFiledesc(worldSavefileName), this, true, autosaveOnErrorAction) {
|
WriteSavegame.immediate(saveTime_t, WriteSavegame.SaveMode.WORLD, worldDisk, getWorldSaveFiledesc(worldSavefileName), this, true, autosaveOnErrorAction) {
|
||||||
makeSavegameBackupCopy(getWorldSaveFiledesc(worldSavefileName), true) // don't put it on the postInit() or render(); must be called using callback
|
makeSavegameBackupCopy(getWorldSaveFiledesc(worldSavefileName)) // don't put it on the postInit() or render(); must be called using callback
|
||||||
uiAutosaveNotifier.setAsClose()
|
uiAutosaveNotifier.setAsClose()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1113,13 +1113,13 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
uiAutosaveNotifier.setAsOpen()
|
uiAutosaveNotifier.setAsOpen()
|
||||||
|
|
||||||
val saveTime_t = App.getTIME_T()
|
val saveTime_t = App.getTIME_T()
|
||||||
val playerSavefile = getPlayerSaveFiledesc(INGAME.playerSavefileName)
|
val playerSavefile0 = getPlayerSaveFiledesc(INGAME.playerSavefileName)
|
||||||
val worldSavefile = getWorldSaveFiledesc(INGAME.worldSavefileName)
|
val worldSavefile0 = getWorldSaveFiledesc(INGAME.worldSavefileName)
|
||||||
|
|
||||||
INGAME.makeSavegameBackupCopy(playerSavefile, true)
|
val playerSavefile = INGAME.makeSavegameBackupCopyAuto(playerSavefile0)
|
||||||
WriteSavegame(saveTime_t, WriteSavegame.SaveMode.PLAYER, INGAME.playerDisk, playerSavefile, INGAME as TerrarumIngame, true, autosaveOnErrorAction) {
|
WriteSavegame(saveTime_t, WriteSavegame.SaveMode.PLAYER, INGAME.playerDisk, playerSavefile, INGAME as TerrarumIngame, true, autosaveOnErrorAction) {
|
||||||
|
|
||||||
INGAME.makeSavegameBackupCopy(worldSavefile, true)
|
val worldSavefile = INGAME.makeSavegameBackupCopyAuto(worldSavefile0)
|
||||||
WriteSavegame(saveTime_t, WriteSavegame.SaveMode.QUICK_WORLD, INGAME.worldDisk, worldSavefile, INGAME as TerrarumIngame, true, autosaveOnErrorAction) {
|
WriteSavegame(saveTime_t, WriteSavegame.SaveMode.QUICK_WORLD, INGAME.worldDisk, worldSavefile, INGAME as TerrarumIngame, true, autosaveOnErrorAction) {
|
||||||
// callback:
|
// callback:
|
||||||
// rebuild the disk skimmers
|
// rebuild the disk skimmers
|
||||||
|
|||||||
@@ -46,6 +46,8 @@ class QuickSingleplayerWorldSavingThread(
|
|||||||
|
|
||||||
|
|
||||||
override fun save() {
|
override fun save() {
|
||||||
|
printdbg(this, "Quicksaveworld has thumbnail: $hasThumbnail")
|
||||||
|
|
||||||
val skimmer = DiskSkimmer(outFile)
|
val skimmer = DiskSkimmer(outFile)
|
||||||
|
|
||||||
if (hasThumbnail) {
|
if (hasThumbnail) {
|
||||||
|
|||||||
@@ -110,10 +110,10 @@ class UIInventoryEscMenu(val full: UIInventoryFull) : UICanvas() {
|
|||||||
val worldSavefile = getWorldSaveFiledesc(INGAME.worldSavefileName)
|
val worldSavefile = getWorldSaveFiledesc(INGAME.worldSavefileName)
|
||||||
|
|
||||||
|
|
||||||
INGAME.makeSavegameBackupCopy(playerSavefile, false)
|
INGAME.makeSavegameBackupCopy(playerSavefile)
|
||||||
WriteSavegame(saveTime_t, WriteSavegame.SaveMode.PLAYER, INGAME.playerDisk, playerSavefile, INGAME as TerrarumIngame, false, onError) {
|
WriteSavegame(saveTime_t, WriteSavegame.SaveMode.PLAYER, INGAME.playerDisk, playerSavefile, INGAME as TerrarumIngame, false, onError) {
|
||||||
|
|
||||||
INGAME.makeSavegameBackupCopy(worldSavefile, false)
|
INGAME.makeSavegameBackupCopy(worldSavefile)
|
||||||
WriteSavegame(saveTime_t, WriteSavegame.SaveMode.WORLD, INGAME.worldDisk, worldSavefile, INGAME as TerrarumIngame, false, onError) {
|
WriteSavegame(saveTime_t, WriteSavegame.SaveMode.WORLD, INGAME.worldDisk, worldSavefile, INGAME as TerrarumIngame, false, onError) {
|
||||||
// callback:
|
// callback:
|
||||||
// rebuild the disk skimmers
|
// rebuild the disk skimmers
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ class UIPerformanceControlPanel(remoCon: UIRemoCon?) : UICanvas() {
|
|||||||
|
|
||||||
private val options = arrayOf(
|
private val options = arrayOf(
|
||||||
arrayOf("", { Lang["MENU_OPTIONS_GAMEPLAY"] }, "h1"),
|
arrayOf("", { Lang["MENU_OPTIONS_GAMEPLAY"] }, "h1"),
|
||||||
arrayOf("autosaveinterval", { Lang["MENU_OPTIONS_AUTOSAVE"] + " (${Lang["CONTEXT_TIME_MINUTE_PLURAL"]})" }, "spinnerimul,5,120,5,60000"),
|
arrayOf("autosaveinterval", { Lang["MENU_OPTIONS_AUTOSAVE"] + " (${Lang["CONTEXT_TIME_MINUTE_PLURAL"]})" }, "spinnerimul,1,120,1,60000"),
|
||||||
arrayOf("notificationshowuptime", { Lang["MENU_OPTIONS_NOTIFICATION_DISPLAY_DURATION"] + " (${Lang["CONTEXT_TIME_SECOND_PLURAL"]})" }, "spinnerimul,2,10,1,1000"),
|
arrayOf("notificationshowuptime", { Lang["MENU_OPTIONS_NOTIFICATION_DISPLAY_DURATION"] + " (${Lang["CONTEXT_TIME_SECOND_PLURAL"]})" }, "spinnerimul,2,10,1,1000"),
|
||||||
arrayOf("", { Lang["MENU_LABEL_JVM_DNT"] }, "h1"),
|
arrayOf("", { Lang["MENU_LABEL_JVM_DNT"] }, "h1"),
|
||||||
arrayOf("jvm_xmx", { Lang["MENU_OPTIONS_JVM_HEAP_MAX"] + " (GB)" }, "spinner,2,32,1"),
|
arrayOf("jvm_xmx", { Lang["MENU_OPTIONS_JVM_HEAP_MAX"] + " (GB)" }, "spinner,2,32,1"),
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ Version 254 is a customised version of TEVD tailored to be used as a savegame fo
|
|||||||
Int8 Disk properties flag 1
|
Int8 Disk properties flag 1
|
||||||
0th bit: readonly
|
0th bit: readonly
|
||||||
Int8 Save type (0b 0000 00ab)
|
Int8 Save type (0b 0000 00ab)
|
||||||
b: unset - full save; set - quick save
|
b: unset - full save; set - quicksave (only applicable to worlds -- quicksave just means the disk is in dirty state)
|
||||||
a: set - generated by autosave
|
a: set - generated by autosave
|
||||||
Int8 Kind of the Save file
|
Int8 Kind of the Save file
|
||||||
0: Undefined (or very old version of the game)
|
0: Undefined (or very old version of the game)
|
||||||
|
|||||||
Reference in New Issue
Block a user