mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-13 03:54:06 +09:00
finally working again: create new character
todo: make delete character work
This commit is contained in:
@@ -1,36 +1,5 @@
|
||||
package net.torvald.terrarum.modulebasegame.serialise
|
||||
|
||||
import net.torvald.gdx.graphics.PixmapIO2
|
||||
import net.torvald.terrarum.App.printdbg
|
||||
import net.torvald.terrarum.ItemCodex
|
||||
import net.torvald.terrarum.ModMgr
|
||||
import net.torvald.terrarum.ReferencingRanges.PREFIX_DYNAMICITEM
|
||||
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.FixtureBase
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
|
||||
import net.torvald.terrarum.realestate.LandUtil
|
||||
import net.torvald.terrarum.toInt
|
||||
import net.torvald.terrarum.savegame.*
|
||||
import net.torvald.terrarum.savegame.VDFileID.LOADORDER
|
||||
import net.torvald.terrarum.savegame.VDFileID.PLAYER_SCREENSHOT
|
||||
import net.torvald.terrarum.savegame.VDFileID.ROOT
|
||||
import net.torvald.terrarum.savegame.VDFileID.SAVEGAMEINFO
|
||||
import net.torvald.terrarum.savegame.VDFileID.THUMBNAIL
|
||||
import net.torvald.terrarum.serialise.Common
|
||||
import java.io.File
|
||||
import java.util.zip.GZIPOutputStream
|
||||
|
||||
/**
|
||||
* Will happily overwrite existing entry
|
||||
*/
|
||||
private fun addFile(disk: VirtualDisk, file: DiskEntry) {
|
||||
disk.entries[file.entryID] = file
|
||||
file.parentEntryID = 0
|
||||
val dir = VDUtil.getAsDirectory(disk, 0)
|
||||
if (!dir.contains(file.entryID)) dir.add(file.entryID)
|
||||
}
|
||||
|
||||
abstract class SavingThread(private val errorHandler: (Throwable) -> Unit) : Runnable {
|
||||
abstract fun save()
|
||||
@@ -46,211 +15,4 @@ abstract class SavingThread(private val errorHandler: (Throwable) -> Unit) : Run
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2021-09-14.
|
||||
*/
|
||||
class WorldSavingThread(
|
||||
val time_t: Long,
|
||||
val disk: VirtualDisk,
|
||||
val outFile: File,
|
||||
val ingame: TerrarumIngame,
|
||||
val isAuto: Boolean,
|
||||
val callback: () -> Unit,
|
||||
val errorHandler: (Throwable) -> Unit
|
||||
) : SavingThread(errorHandler) {
|
||||
|
||||
override fun save() {
|
||||
|
||||
disk.saveMode = 2 * isAuto.toInt() // no quick
|
||||
disk.saveKind = VDSaveKind.WORLD_DATA
|
||||
|
||||
while (!IngameRenderer.fboRGBexportedLatch) {
|
||||
Thread.sleep(1L)
|
||||
}
|
||||
|
||||
val allTheActors = ingame.actorContainerActive.cloneToList() + ingame.actorContainerInactive.cloneToList()
|
||||
|
||||
val playersList: List<IngamePlayer> = allTheActors.filterIsInstance<IngamePlayer>()
|
||||
val actorsList = allTheActors.filter { WriteWorld.actorAcceptable(it) }
|
||||
val layers = intArrayOf(0,1).map { ingame.world.getLayer(it) }
|
||||
val cw = ingame.world.width / LandUtil.CHUNK_W
|
||||
val ch = ingame.world.height / LandUtil.CHUNK_H
|
||||
|
||||
WriteSavegame.saveProgress = 0f
|
||||
WriteSavegame.saveProgressMax = 3f + (cw * ch * layers.size) + actorsList.size
|
||||
|
||||
|
||||
val tgaout = ByteArray64GrowableOutputStream()
|
||||
val gzout = GZIPOutputStream(tgaout)
|
||||
|
||||
printdbg(this, "Writing metadata...")
|
||||
|
||||
val creation_t = ingame.world.creationTime
|
||||
|
||||
|
||||
// Write subset of Ingame.ItemCodex
|
||||
// The existing ItemCodex must be rewritten to clear out obsolete records
|
||||
|
||||
// We're assuming the dynamic item generated by players does exist in the world, and it's recorded
|
||||
// into the world's dynamicToStaticTable, therefore every item recorded into the world's dynamicToStaticTable
|
||||
// can be found in this world without need to look up the players
|
||||
ingame.world.dynamicToStaticTable.clear()
|
||||
ingame.world.dynamicItemInventory.clear()
|
||||
actorsList.filterIsInstance<Pocketed>().forEach { actor ->
|
||||
actor.inventory.forEach { (itemid, _) ->
|
||||
|
||||
printdbg(this, "World side dynamicitem: $itemid contained in $actor")
|
||||
|
||||
if (itemid.startsWith("$PREFIX_DYNAMICITEM:")) {
|
||||
ingame.world.dynamicToStaticTable[itemid] = ItemCodex.dynamicToStaticID(itemid)
|
||||
ingame.world.dynamicItemInventory[itemid] = ItemCodex[itemid]!!
|
||||
}
|
||||
}
|
||||
}
|
||||
actorsList.filterIsInstance<FixtureBase>().forEach { fixture ->
|
||||
fixture.inventory?.forEach { (itemid, _) ->
|
||||
|
||||
printdbg(this, "World side dynamicitem: $itemid contained in $fixture")
|
||||
|
||||
if (itemid.startsWith("$PREFIX_DYNAMICITEM:")) {
|
||||
ingame.world.dynamicToStaticTable[itemid] = ItemCodex.dynamicToStaticID(itemid)
|
||||
ingame.world.dynamicItemInventory[itemid] = ItemCodex[itemid]!!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
PixmapIO2._writeTGA(gzout, IngameRenderer.fboRGBexport, true, true)
|
||||
IngameRenderer.fboRGBexport.dispose()
|
||||
|
||||
val thumbContent = EntryFile(tgaout.toByteArray64())
|
||||
val thumb = DiskEntry(THUMBNAIL, ROOT, creation_t, time_t, thumbContent)
|
||||
addFile(disk, thumb)
|
||||
|
||||
|
||||
|
||||
WriteSavegame.saveProgress += 1f
|
||||
|
||||
// Write World //
|
||||
|
||||
val worldMeta = EntryFile(WriteWorld.encodeToByteArray64(ingame, time_t, actorsList, playersList))
|
||||
val world = DiskEntry(SAVEGAMEINFO, ROOT, creation_t, time_t, worldMeta)
|
||||
addFile(disk, world)
|
||||
|
||||
WriteSavegame.saveProgress += 1f
|
||||
|
||||
|
||||
for (layer in layers.indices) {
|
||||
for (cx in 0 until cw) {
|
||||
for (cy in 0 until ch) {
|
||||
val chunkNumber = LandUtil.chunkXYtoChunkNum(ingame.world, cx, cy).toLong()
|
||||
|
||||
// Echo("Writing chunks... ${(cw*ch*layer) + chunkNumber + 1}/${cw*ch*layers.size}")
|
||||
|
||||
val chunkBytes = WriteWorld.encodeChunk(layers[layer]!!, cx, cy)
|
||||
val entryID = 0x1_0000_0000L or layer.toLong().shl(24) or chunkNumber
|
||||
|
||||
val entryContent = EntryFile(chunkBytes)
|
||||
val entry = DiskEntry(entryID, ROOT, creation_t, time_t, entryContent)
|
||||
// "W1L0-92,15"
|
||||
addFile(disk, entry)
|
||||
|
||||
WriteSavegame.saveProgress += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Write Actors //
|
||||
actorsList.forEachIndexed { count, it ->
|
||||
// Echo("Writing actors... ${count+1}/${actorsList.size}")
|
||||
|
||||
val actorContent = EntryFile(WriteActor.encodeToByteArray64(it))
|
||||
val actor = DiskEntry(it.referenceID.toLong(), ROOT, creation_t, time_t, actorContent)
|
||||
addFile(disk, actor)
|
||||
|
||||
WriteSavegame.saveProgress += 1
|
||||
}
|
||||
|
||||
|
||||
// write loadorder //
|
||||
val loadOrderBa64Writer = ByteArray64Writer(Common.CHARSET)
|
||||
loadOrderBa64Writer.write(ModMgr.loadOrder.joinToString("\n"))
|
||||
loadOrderBa64Writer.flush(); loadOrderBa64Writer.close()
|
||||
val loadOrderText = loadOrderBa64Writer.toByteArray64()
|
||||
val loadOrderContents = EntryFile(loadOrderText)
|
||||
addFile(disk, DiskEntry(LOADORDER, ROOT, creation_t, time_t, loadOrderContents))
|
||||
|
||||
|
||||
|
||||
// Echo("Writing file to disk...")
|
||||
|
||||
disk.entries[0]!!.modificationDate = time_t
|
||||
// entry zero MUST NOT be used to get lastPlayDate, but we'll update it anyway
|
||||
// use entry -1 for that purpose!
|
||||
disk.capacity = 0
|
||||
VDUtil.dumpToRealMachine(disk, outFile)
|
||||
|
||||
|
||||
|
||||
printdbg(this, "Game saved with size of ${outFile.length()} bytes")
|
||||
|
||||
|
||||
IngameRenderer.fboRGBexportedLatch = false
|
||||
WriteSavegame.savingStatus = 255
|
||||
|
||||
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function called means the "Avatar" was not externally created and thus has no sprite-bodypart-name-to-entry-number-map
|
||||
*
|
||||
* Created by minjaesong on 2021-10-08
|
||||
*/
|
||||
class PlayerSavingThread(
|
||||
val time_t: Long,
|
||||
val disk: VirtualDisk,
|
||||
val outFile: File,
|
||||
val ingame: TerrarumIngame,
|
||||
val isAuto: Boolean,
|
||||
val callback: () -> Unit,
|
||||
val errorHandler: (Throwable) -> Unit
|
||||
) : SavingThread(errorHandler) {
|
||||
|
||||
override fun save() {
|
||||
disk.saveMode = 2 * isAuto.toInt() // no quick
|
||||
disk.saveKind = VDSaveKind.PLAYER_DATA
|
||||
disk.capacity = 0L
|
||||
|
||||
WriteSavegame.saveProgress = 0f
|
||||
|
||||
// wait for screencap
|
||||
while (!IngameRenderer.fboRGBexportedLatch) {
|
||||
Thread.sleep(1L)
|
||||
}
|
||||
|
||||
// write screencap
|
||||
val tgaout = ByteArray64GrowableOutputStream()
|
||||
val gzout = GZIPOutputStream(tgaout)
|
||||
PixmapIO2._writeTGA(gzout, IngameRenderer.fboRGBexport, true, true)
|
||||
IngameRenderer.fboRGBexport.dispose()
|
||||
val thumbContent = EntryFile(tgaout.toByteArray64())
|
||||
val thumb = DiskEntry(PLAYER_SCREENSHOT, ROOT, ingame.world.creationTime, time_t, thumbContent)
|
||||
addFile(disk, thumb)
|
||||
|
||||
|
||||
|
||||
printdbg(this, "Writing The Player...")
|
||||
WritePlayer(ingame.actorGamer, disk, ingame, time_t)
|
||||
disk.entries[0]!!.modificationDate = time_t
|
||||
VDUtil.dumpToRealMachine(disk, outFile)
|
||||
|
||||
|
||||
IngameRenderer.fboRGBexportedLatch = false
|
||||
|
||||
callback()
|
||||
}
|
||||
}
|
||||
const val SCREENCAP_WAIT_TRY_MAX = 256
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
package net.torvald.terrarum.modulebasegame.serialise
|
||||
|
||||
import net.torvald.gdx.graphics.PixmapIO2
|
||||
import net.torvald.terrarum.App
|
||||
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||
import net.torvald.terrarum.savegame.*
|
||||
import net.torvald.terrarum.toInt
|
||||
import java.io.File
|
||||
import java.util.zip.GZIPOutputStream
|
||||
|
||||
/**
|
||||
* This function called means the "Avatar" was not externally created and thus has no sprite-bodypart-name-to-entry-number-map
|
||||
*
|
||||
* Created by minjaesong on 2021-10-08
|
||||
*/
|
||||
class PlayerSavingThread(
|
||||
val time_t: Long,
|
||||
val disk: VirtualDisk,
|
||||
val outFile: File,
|
||||
val ingame: TerrarumIngame,
|
||||
val isAuto: Boolean,
|
||||
val callback: () -> Unit,
|
||||
val errorHandler: (Throwable) -> Unit
|
||||
) : SavingThread(errorHandler) {
|
||||
/**
|
||||
* Will happily overwrite existing entry
|
||||
*/
|
||||
private fun addFile(disk: VirtualDisk, file: DiskEntry) {
|
||||
disk.entries[file.entryID] = file
|
||||
file.parentEntryID = 0
|
||||
val dir = VDUtil.getAsDirectory(disk, 0)
|
||||
if (!dir.contains(file.entryID)) dir.add(file.entryID)
|
||||
}
|
||||
|
||||
|
||||
override fun save() {
|
||||
App.printdbg(this, "outFile: ${outFile.path}")
|
||||
|
||||
disk.saveMode = 2 * isAuto.toInt() // no quick
|
||||
disk.saveKind = VDSaveKind.PLAYER_DATA
|
||||
disk.capacity = 0L
|
||||
|
||||
WriteSavegame.saveProgress = 0f
|
||||
|
||||
// wait for screencap
|
||||
var emergencyStopCnt = 0
|
||||
while (IngameRenderer.screencapBusy) {
|
||||
// printdbg(this, "spinning for screencap to be taken")
|
||||
Thread.sleep(4L)
|
||||
emergencyStopCnt += 1
|
||||
if (emergencyStopCnt >= SCREENCAP_WAIT_TRY_MAX) throw InterruptedException("Waiting screencap to be taken for too long")
|
||||
}
|
||||
|
||||
// write screencap
|
||||
val tgaout = ByteArray64GrowableOutputStream()
|
||||
val gzout = GZIPOutputStream(tgaout)
|
||||
PixmapIO2._writeTGA(gzout, IngameRenderer.fboRGBexport, true, true)
|
||||
IngameRenderer.fboRGBexport.dispose()
|
||||
val thumbContent = EntryFile(tgaout.toByteArray64())
|
||||
val thumb =
|
||||
DiskEntry(VDFileID.PLAYER_SCREENSHOT, VDFileID.ROOT, ingame.world.creationTime, time_t, thumbContent)
|
||||
addFile(disk, thumb)
|
||||
|
||||
|
||||
|
||||
App.printdbg(this, "Writing The Player...")
|
||||
WritePlayer(ingame.actorGamer, disk, ingame, time_t)
|
||||
disk.entries[0]!!.modificationDate = time_t
|
||||
VDUtil.dumpToRealMachine(disk, outFile)
|
||||
|
||||
|
||||
// IngameRenderer.screencapBusy = false
|
||||
|
||||
callback()
|
||||
}
|
||||
}
|
||||
@@ -45,10 +45,17 @@ class QuickSingleplayerWorldSavingThread(
|
||||
|
||||
|
||||
override fun save() {
|
||||
printdbg(this, "outFile: ${outFile.path}")
|
||||
|
||||
val skimmer = DiskSkimmer(outFile)
|
||||
|
||||
while (!IngameRenderer.fboRGBexportedLatch) {
|
||||
Thread.sleep(1L)
|
||||
// wait for screencap
|
||||
var emergencyStopCnt = 0
|
||||
while (IngameRenderer.screencapBusy) {
|
||||
// printdbg(this, "spinning for screencap to be taken")
|
||||
Thread.sleep(4L)
|
||||
emergencyStopCnt += 1
|
||||
if (emergencyStopCnt >= SCREENCAP_WAIT_TRY_MAX) throw InterruptedException("Waiting screencap to be taken for too long")
|
||||
}
|
||||
|
||||
val allTheActors = ingame.actorContainerActive.cloneToList() + ingame.actorContainerInactive.cloneToList()
|
||||
@@ -147,7 +154,7 @@ class QuickSingleplayerWorldSavingThread(
|
||||
printdbg(this, "Game saved with size of ${outFile.length()} bytes")
|
||||
|
||||
|
||||
IngameRenderer.fboRGBexportedLatch = false
|
||||
// IngameRenderer.screencapBusy = false
|
||||
WriteSavegame.savingStatus = 255
|
||||
ingame.clearModifiedChunks()
|
||||
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
package net.torvald.terrarum.modulebasegame.serialise
|
||||
|
||||
import net.torvald.gdx.graphics.PixmapIO2
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.FixtureBase
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
|
||||
import net.torvald.terrarum.realestate.LandUtil
|
||||
import net.torvald.terrarum.savegame.*
|
||||
import net.torvald.terrarum.serialise.Common
|
||||
import java.io.File
|
||||
import java.util.zip.GZIPOutputStream
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2021-09-14.
|
||||
*/
|
||||
class WorldSavingThread(
|
||||
val time_t: Long,
|
||||
val disk: VirtualDisk,
|
||||
val outFile: File,
|
||||
val ingame: TerrarumIngame,
|
||||
val isAuto: Boolean,
|
||||
val callback: () -> Unit,
|
||||
val errorHandler: (Throwable) -> Unit
|
||||
) : SavingThread(errorHandler) {
|
||||
/**
|
||||
* Will happily overwrite existing entry
|
||||
*/
|
||||
private fun addFile(disk: VirtualDisk, file: DiskEntry) {
|
||||
disk.entries[file.entryID] = file
|
||||
file.parentEntryID = 0
|
||||
val dir = VDUtil.getAsDirectory(disk, 0)
|
||||
if (!dir.contains(file.entryID)) dir.add(file.entryID)
|
||||
}
|
||||
|
||||
|
||||
override fun save() {
|
||||
App.printdbg(this, "outFile: ${outFile.path}")
|
||||
|
||||
disk.saveMode = 2 * isAuto.toInt() // no quick
|
||||
disk.saveKind = VDSaveKind.WORLD_DATA
|
||||
|
||||
// wait for screencap
|
||||
var emergencyStopCnt = 0
|
||||
while (IngameRenderer.screencapBusy) {
|
||||
// printdbg(this, "spinning for screencap to be taken")
|
||||
Thread.sleep(4L)
|
||||
emergencyStopCnt += 1
|
||||
if (emergencyStopCnt >= SCREENCAP_WAIT_TRY_MAX) throw InterruptedException("Waiting screencap to be taken for too long")
|
||||
}
|
||||
|
||||
val allTheActors = ingame.actorContainerActive.cloneToList() + ingame.actorContainerInactive.cloneToList()
|
||||
|
||||
val playersList: List<IngamePlayer> = allTheActors.filterIsInstance<IngamePlayer>()
|
||||
val actorsList = allTheActors.filter { WriteWorld.actorAcceptable(it) }
|
||||
val layers = intArrayOf(0,1).map { ingame.world.getLayer(it) }
|
||||
val cw = ingame.world.width / LandUtil.CHUNK_W
|
||||
val ch = ingame.world.height / LandUtil.CHUNK_H
|
||||
|
||||
WriteSavegame.saveProgress = 0f
|
||||
WriteSavegame.saveProgressMax = 3f + (cw * ch * layers.size) + actorsList.size
|
||||
|
||||
|
||||
val tgaout = ByteArray64GrowableOutputStream()
|
||||
val gzout = GZIPOutputStream(tgaout)
|
||||
|
||||
App.printdbg(this, "Writing metadata...")
|
||||
|
||||
val creation_t = ingame.world.creationTime
|
||||
|
||||
|
||||
// Write subset of Ingame.ItemCodex
|
||||
// The existing ItemCodex must be rewritten to clear out obsolete records
|
||||
|
||||
// We're assuming the dynamic item generated by players does exist in the world, and it's recorded
|
||||
// into the world's dynamicToStaticTable, therefore every item recorded into the world's dynamicToStaticTable
|
||||
// can be found in this world without need to look up the players
|
||||
ingame.world.dynamicToStaticTable.clear()
|
||||
ingame.world.dynamicItemInventory.clear()
|
||||
actorsList.filterIsInstance<Pocketed>().forEach { actor ->
|
||||
actor.inventory.forEach { (itemid, _) ->
|
||||
|
||||
App.printdbg(this, "World side dynamicitem: $itemid contained in $actor")
|
||||
|
||||
if (itemid.startsWith("${ReferencingRanges.PREFIX_DYNAMICITEM}:")) {
|
||||
ingame.world.dynamicToStaticTable[itemid] = ItemCodex.dynamicToStaticID(itemid)
|
||||
ingame.world.dynamicItemInventory[itemid] = ItemCodex[itemid]!!
|
||||
}
|
||||
}
|
||||
}
|
||||
actorsList.filterIsInstance<FixtureBase>().forEach { fixture ->
|
||||
fixture.inventory?.forEach { (itemid, _) ->
|
||||
|
||||
App.printdbg(this, "World side dynamicitem: $itemid contained in $fixture")
|
||||
|
||||
if (itemid.startsWith("${ReferencingRanges.PREFIX_DYNAMICITEM}:")) {
|
||||
ingame.world.dynamicToStaticTable[itemid] = ItemCodex.dynamicToStaticID(itemid)
|
||||
ingame.world.dynamicItemInventory[itemid] = ItemCodex[itemid]!!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
PixmapIO2._writeTGA(gzout, IngameRenderer.fboRGBexport, true, true)
|
||||
IngameRenderer.fboRGBexport.dispose()
|
||||
|
||||
val thumbContent = EntryFile(tgaout.toByteArray64())
|
||||
val thumb = DiskEntry(VDFileID.THUMBNAIL, VDFileID.ROOT, creation_t, time_t, thumbContent)
|
||||
addFile(disk, thumb)
|
||||
|
||||
|
||||
|
||||
WriteSavegame.saveProgress += 1f
|
||||
|
||||
// Write World //
|
||||
|
||||
val worldMeta = EntryFile(WriteWorld.encodeToByteArray64(ingame, time_t, actorsList, playersList))
|
||||
val world = DiskEntry(VDFileID.SAVEGAMEINFO, VDFileID.ROOT, creation_t, time_t, worldMeta)
|
||||
addFile(disk, world)
|
||||
|
||||
WriteSavegame.saveProgress += 1f
|
||||
|
||||
|
||||
for (layer in layers.indices) {
|
||||
for (cx in 0 until cw) {
|
||||
for (cy in 0 until ch) {
|
||||
val chunkNumber = LandUtil.chunkXYtoChunkNum(ingame.world, cx, cy).toLong()
|
||||
|
||||
// Echo("Writing chunks... ${(cw*ch*layer) + chunkNumber + 1}/${cw*ch*layers.size}")
|
||||
|
||||
val chunkBytes = WriteWorld.encodeChunk(layers[layer]!!, cx, cy)
|
||||
val entryID = 0x1_0000_0000L or layer.toLong().shl(24) or chunkNumber
|
||||
|
||||
val entryContent = EntryFile(chunkBytes)
|
||||
val entry = DiskEntry(entryID, VDFileID.ROOT, creation_t, time_t, entryContent)
|
||||
// "W1L0-92,15"
|
||||
addFile(disk, entry)
|
||||
|
||||
WriteSavegame.saveProgress += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Write Actors //
|
||||
actorsList.forEachIndexed { count, it ->
|
||||
// Echo("Writing actors... ${count+1}/${actorsList.size}")
|
||||
|
||||
val actorContent = EntryFile(WriteActor.encodeToByteArray64(it))
|
||||
val actor = DiskEntry(it.referenceID.toLong(), VDFileID.ROOT, creation_t, time_t, actorContent)
|
||||
addFile(disk, actor)
|
||||
|
||||
WriteSavegame.saveProgress += 1
|
||||
}
|
||||
|
||||
|
||||
// write loadorder //
|
||||
val loadOrderBa64Writer = ByteArray64Writer(Common.CHARSET)
|
||||
loadOrderBa64Writer.write(ModMgr.loadOrder.joinToString("\n"))
|
||||
loadOrderBa64Writer.flush(); loadOrderBa64Writer.close()
|
||||
val loadOrderText = loadOrderBa64Writer.toByteArray64()
|
||||
val loadOrderContents = EntryFile(loadOrderText)
|
||||
addFile(disk, DiskEntry(VDFileID.LOADORDER, VDFileID.ROOT, creation_t, time_t, loadOrderContents))
|
||||
|
||||
|
||||
|
||||
// Echo("Writing file to disk...")
|
||||
|
||||
disk.entries[0]!!.modificationDate = time_t
|
||||
// entry zero MUST NOT be used to get lastPlayDate, but we'll update it anyway
|
||||
// use entry -1 for that purpose!
|
||||
disk.capacity = 0
|
||||
VDUtil.dumpToRealMachine(disk, outFile)
|
||||
|
||||
|
||||
|
||||
App.printdbg(this, "Game saved with size of ${outFile.length()} bytes")
|
||||
|
||||
|
||||
// IngameRenderer.screencapBusy = false
|
||||
WriteSavegame.savingStatus = 255
|
||||
|
||||
|
||||
callback()
|
||||
}
|
||||
}
|
||||
@@ -43,10 +43,7 @@ object WriteSavegame {
|
||||
else -> throw IllegalArgumentException("$mode")
|
||||
}
|
||||
|
||||
operator fun invoke(time_t: Long, mode: SaveMode, disk: VirtualDisk, outFile: File, ingame: TerrarumIngame, isAuto: Boolean, errorHandler: (Throwable) -> Unit, callback: () -> Unit) {
|
||||
savingStatus = 0
|
||||
printdbg(this, "Save queued")
|
||||
|
||||
private fun installScreencap() {
|
||||
IngameRenderer.screencapExportCallback = { fb ->
|
||||
printdbg(this, "Generating thumbnail...")
|
||||
|
||||
@@ -63,11 +60,19 @@ object WriteSavegame {
|
||||
IngameRenderer.fboRGBexport = p
|
||||
//PixmapIO2._writeTGA(gzout, p, true, true)
|
||||
//p.dispose()
|
||||
IngameRenderer.fboRGBexportedLatch = true
|
||||
|
||||
printdbg(this, "Done thumbnail generation")
|
||||
}
|
||||
IngameRenderer.screencapRequested = true
|
||||
}
|
||||
|
||||
operator fun invoke(time_t: Long, mode: SaveMode, disk: VirtualDisk, outFile: File, ingame: TerrarumIngame, isAuto: Boolean, errorHandler: (Throwable) -> Unit, callback: () -> Unit) {
|
||||
savingStatus = 0
|
||||
printdbg(this, "Save queued")
|
||||
|
||||
installScreencap()
|
||||
try { printdbg(this, "ScreencapExport installed: ${IngameRenderer.screencapExportCallback}") }
|
||||
catch (e: UninitializedPropertyAccessException) { printdbg(this, "ScreencapExport installed: no") }
|
||||
IngameRenderer.requestScreencap()
|
||||
|
||||
val savingThread = Thread(getSaveThread(time_t, mode, disk, outFile, ingame, isAuto, errorHandler, callback), "TerrarumBasegameGameSaveThread")
|
||||
savingThread.start()
|
||||
@@ -78,11 +83,14 @@ object WriteSavegame {
|
||||
|
||||
|
||||
fun immediate(time_t: Long, mode: SaveMode, disk: VirtualDisk, outFile: File, ingame: TerrarumIngame, isAuto: Boolean, errorHandler: (Throwable) -> Unit, callback: () -> Unit) {
|
||||
|
||||
savingStatus = 0
|
||||
|
||||
printdbg(this, "Immediate save fired")
|
||||
|
||||
installScreencap()
|
||||
try { printdbg(this, "ScreencapExport installed: ${IngameRenderer.screencapExportCallback}") }
|
||||
catch (e: UninitializedPropertyAccessException) { printdbg(this, "ScreencapExport installed: no") }
|
||||
IngameRenderer.requestScreencap()
|
||||
|
||||
val savingThread = Thread(getSaveThread(time_t, mode, disk, outFile, ingame, isAuto, errorHandler, callback), "TerrarumBasegameGameSaveThread")
|
||||
savingThread.start()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user