mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-12 19:44:05 +09:00
new player save format writing
This commit is contained in:
@@ -43,6 +43,9 @@ object Common {
|
||||
|
||||
// install custom (de)serialiser
|
||||
init {
|
||||
jsoner.ignoreUnknownFields = true
|
||||
|
||||
|
||||
// BigInteger
|
||||
jsoner.setSerializer(BigInteger::class.java, object : Json.Serializer<BigInteger> {
|
||||
override fun write(json: Json, obj: BigInteger?, knownType: Class<*>?) {
|
||||
|
||||
@@ -3,36 +3,31 @@ package net.torvald.terrarum.serialise
|
||||
import net.torvald.gdx.graphics.PixmapIO2
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.console.Echo
|
||||
import net.torvald.terrarum.gameworld.PhysicalStatus
|
||||
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
||||
import net.torvald.terrarum.realestate.LandUtil
|
||||
import net.torvald.terrarum.tvda.*
|
||||
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)
|
||||
}
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2021-09-14.
|
||||
*/
|
||||
class GameSavingThread(val disk: VirtualDisk, val outFile: File, val ingame: TerrarumIngame, val hasThumbnail: Boolean, val isAuto: Boolean, val callback: () -> Unit) : Runnable {
|
||||
|
||||
/**
|
||||
* 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)
|
||||
}
|
||||
|
||||
private val chunkProgressMultiplier = 1f
|
||||
private val actorProgressMultiplier = 1f
|
||||
class WorldSavingThread(val disk: VirtualDisk, val outFile: File, val ingame: TerrarumIngame, val hasThumbnail: Boolean, val isAuto: Boolean, val callback: () -> Unit) : Runnable {
|
||||
|
||||
override fun run() {
|
||||
callback()
|
||||
return
|
||||
|
||||
// TODO //
|
||||
|
||||
disk.saveMode = 2 * isAuto.toInt() // no quick
|
||||
|
||||
@@ -42,15 +37,14 @@ class GameSavingThread(val disk: VirtualDisk, val outFile: File, val ingame: Ter
|
||||
}
|
||||
}
|
||||
|
||||
val playersList: List<IngamePlayer> = listOf(ingame.actorContainerActive, ingame.actorContainerInactive).flatMap{ it.filter { it is IngamePlayer } } as List<IngamePlayer>
|
||||
val actorsList = listOf(ingame.actorContainerActive, ingame.actorContainerInactive).flatMap { it.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 = 2f +
|
||||
(cw * ch * layers.size) * chunkProgressMultiplier +
|
||||
actorsList.size * actorProgressMultiplier
|
||||
WriteSavegame.saveProgressMax = 2f + (cw * ch * layers.size) + actorsList.size
|
||||
|
||||
|
||||
val tgaout = ByteArray64GrowableOutputStream()
|
||||
@@ -62,11 +56,6 @@ class GameSavingThread(val disk: VirtualDisk, val outFile: File, val ingame: Ter
|
||||
val time_t = App.getTIME_T()
|
||||
|
||||
|
||||
// Write Meta //
|
||||
val metaContent = EntryFile(WriteMeta.encodeToByteArray64(ingame, time_t))
|
||||
val meta = DiskEntry(-1, 0, creation_t, time_t, metaContent)
|
||||
addFile(disk, meta)
|
||||
|
||||
if (hasThumbnail) {
|
||||
PixmapIO2._writeTGA(gzout, IngameRenderer.fboRGBexport, true, true)
|
||||
IngameRenderer.fboRGBexport.dispose()
|
||||
@@ -114,10 +103,13 @@ class GameSavingThread(val disk: VirtualDisk, val outFile: File, val ingame: Ter
|
||||
// addFile(disk, apocryphas)
|
||||
|
||||
// Write World //
|
||||
// val worldNum = ingame.world.worldIndex
|
||||
// val worldMeta = EntryFile(WriteWorld.encodeToByteArray64(ingame, time_t))
|
||||
// val world = DiskEntry(worldNum.toLong(), 0, creation_t, time_t, worldMeta)
|
||||
// addFile(disk, world)
|
||||
// record all player's last position
|
||||
playersList.forEach {
|
||||
ingame.world.playersLastStatus[it.uuid] = PhysicalStatus(it)
|
||||
}
|
||||
val worldMeta = EntryFile(WriteWorld.encodeToByteArray64(ingame, time_t))
|
||||
val world = DiskEntry(-1L, 0, creation_t, time_t, worldMeta)
|
||||
addFile(disk, world)
|
||||
|
||||
WriteSavegame.saveProgress += 1f
|
||||
|
||||
@@ -137,7 +129,7 @@ class GameSavingThread(val disk: VirtualDisk, val outFile: File, val ingame: Ter
|
||||
// "W1L0-92,15"
|
||||
addFile(disk, entry)
|
||||
|
||||
WriteSavegame.saveProgress += chunkProgressMultiplier
|
||||
WriteSavegame.saveProgress += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -151,7 +143,7 @@ class GameSavingThread(val disk: VirtualDisk, val outFile: File, val ingame: Ter
|
||||
val actor = DiskEntry(it.referenceID.toLong(), 0, creation_t, time_t, actorContent)
|
||||
addFile(disk, actor)
|
||||
|
||||
WriteSavegame.saveProgress += actorProgressMultiplier
|
||||
WriteSavegame.saveProgress += 1
|
||||
}
|
||||
|
||||
|
||||
@@ -174,4 +166,23 @@ class GameSavingThread(val disk: VirtualDisk, val outFile: File, val ingame: Ter
|
||||
|
||||
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 disk: VirtualDisk, val outFile: File, val ingame: TerrarumIngame, val hasThumbnail: Boolean, val isAuto: Boolean, val callback: () -> Unit) : Runnable {
|
||||
|
||||
override fun run() {
|
||||
disk.saveMode = 2 * isAuto.toInt() // no quick
|
||||
disk.capacity = 0L
|
||||
|
||||
Echo("Writing The Player...")
|
||||
WritePlayer(ingame.actorGamer, disk)
|
||||
VDUtil.dumpToRealMachine(disk, outFile)
|
||||
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ object WriteActor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Player-specific [WriteActor].
|
||||
* Player-specific [WriteActor]. Will write JSON and Animation Description Languages
|
||||
*
|
||||
* Created by minjaesong on 2021-10-07.
|
||||
*/
|
||||
@@ -74,12 +74,12 @@ object WritePlayer {
|
||||
|
||||
val adlContents = EntryFile(ByteArray64.fromByteArray(adl.toByteArray(Common.CHARSET)))
|
||||
val adlCreationDate = playerDisk.getEntry(-2)?.creationDate ?: time_t
|
||||
addFile(playerDisk, DiskEntry(-1L, 0L, adlCreationDate, time_t, adlContents))
|
||||
addFile(playerDisk, DiskEntry(-2L, 0L, adlCreationDate, time_t, adlContents))
|
||||
|
||||
if (adlGlow != null) {
|
||||
val adlGlowContents = EntryFile(ByteArray64.fromByteArray(adlGlow.toByteArray(Common.CHARSET)))
|
||||
val adlGlowCreationDate = playerDisk.getEntry(-3)?.creationDate ?: time_t
|
||||
addFile(playerDisk, DiskEntry(-1L, 0L, adlGlowCreationDate, time_t, adlGlowContents))
|
||||
addFile(playerDisk, DiskEntry(-3L, 0L, adlGlowCreationDate, time_t, adlGlowContents))
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -23,11 +23,21 @@ import java.io.Reader
|
||||
*/
|
||||
object WriteSavegame {
|
||||
|
||||
enum class SaveMode {
|
||||
META, PLAYER, WORLD, SHARED
|
||||
}
|
||||
|
||||
@Volatile var savingStatus = -1 // -1: not started, 0: saving in progress, 255: saving finished
|
||||
@Volatile var saveProgress = 0f
|
||||
@Volatile var saveProgressMax = 1f
|
||||
|
||||
operator fun invoke(disk: VirtualDisk, outFile: File, ingame: TerrarumIngame, isAuto: Boolean, callback: () -> Unit = {}) {
|
||||
private fun getSaveThread(mode: SaveMode, disk: VirtualDisk, outFile: File, ingame: TerrarumIngame, hasThumbnail: Boolean, isAuto: Boolean, callback: () -> Unit = {}) = when (mode) {
|
||||
SaveMode.WORLD -> WorldSavingThread(disk, outFile, ingame, hasThumbnail, isAuto, callback)
|
||||
SaveMode.PLAYER -> PlayerSavingThread(disk, outFile, ingame, hasThumbnail, isAuto, callback)
|
||||
else -> throw IllegalArgumentException("$mode")
|
||||
}
|
||||
|
||||
operator fun invoke(mode: SaveMode, disk: VirtualDisk, outFile: File, ingame: TerrarumIngame, isAuto: Boolean, callback: () -> Unit = {}) {
|
||||
savingStatus = 0
|
||||
|
||||
Echo("Save queued")
|
||||
@@ -47,7 +57,7 @@ object WriteSavegame {
|
||||
}
|
||||
IngameRenderer.screencapRequested = true
|
||||
|
||||
val savingThread = Thread(GameSavingThread(disk, outFile, ingame, true, isAuto, callback), "TerrarumBasegameGameSaveThread")
|
||||
val savingThread = Thread(getSaveThread(mode, disk, outFile, ingame, true, isAuto, callback), "TerrarumBasegameGameSaveThread")
|
||||
savingThread.start()
|
||||
|
||||
// it is caller's job to keep the game paused or keep a "save in progress" ui up
|
||||
@@ -55,16 +65,13 @@ object WriteSavegame {
|
||||
}
|
||||
|
||||
|
||||
fun immediate(disk: VirtualDisk, outFile: File, ingame: TerrarumIngame, isAuto: Boolean, callback: () -> Unit = {}) {
|
||||
return
|
||||
|
||||
// TODO //
|
||||
fun immediate(mode: SaveMode, disk: VirtualDisk, outFile: File, ingame: TerrarumIngame, hasThumbnail: Boolean, isAuto: Boolean, callback: () -> Unit = {}) {
|
||||
|
||||
savingStatus = 0
|
||||
|
||||
Echo("Immediate save fired")
|
||||
|
||||
val savingThread = Thread(GameSavingThread(disk, outFile, ingame, false, isAuto, callback), "TerrarumBasegameGameSaveThread")
|
||||
val savingThread = Thread(getSaveThread(mode, disk, outFile, ingame, false, isAuto, callback), "TerrarumBasegameGameSaveThread")
|
||||
savingThread.start()
|
||||
|
||||
// it is caller's job to keep the game paused or keep a "save in progress" ui up
|
||||
@@ -134,7 +141,6 @@ object LoadSavegame {
|
||||
world.layerTerrain = BlockLayer(world.width, world.height)
|
||||
world.layerWall = BlockLayer(world.width, world.height)
|
||||
|
||||
newIngame.savegameArchive = disk
|
||||
newIngame.creationTime = meta.creation_t
|
||||
newIngame.lastPlayTime = meta.lastplay_t
|
||||
newIngame.totalPlayTime = meta.playtime_t
|
||||
|
||||
@@ -9,6 +9,7 @@ import net.torvald.terrarum.gameworld.BlockLayer
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.gameworld.GameWorldTitleScreen
|
||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
||||
import net.torvald.terrarum.realestate.LandUtil
|
||||
import net.torvald.terrarum.tvda.ByteArray64
|
||||
import net.torvald.terrarum.tvda.ByteArray64Writer
|
||||
@@ -22,7 +23,8 @@ object WriteWorld {
|
||||
fun actorAcceptable(actor: Actor): Boolean {
|
||||
return actor.referenceID !in ReferencingRanges.ACTORS_WIRES &&
|
||||
actor.referenceID !in ReferencingRanges.ACTORS_WIRES_HELPER &&
|
||||
actor != (CommonResourcePool.get("blockmarking_actor") as BlockMarkerActor)
|
||||
actor != (CommonResourcePool.get("blockmarking_actor") as BlockMarkerActor) &&
|
||||
actor !is IngamePlayer // IngamePlayers must not be saved with the world
|
||||
}
|
||||
|
||||
private fun preWrite(ingame: TerrarumIngame, time_t: Long): GameWorld {
|
||||
|
||||
Reference in New Issue
Block a user