mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-19 15:04:05 +09:00
gson test in progress
This commit is contained in:
@@ -1,11 +1,15 @@
|
||||
package net.torvald.terrarum.serialise
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.google.gson.Gson
|
||||
import net.torvald.terrarum.AppLoader
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension
|
||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.DiskEntry
|
||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.DiskSkimmer
|
||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.VDUtil
|
||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.VirtualDisk
|
||||
import net.torvald.terrarum.gameactors.AVKey
|
||||
import net.torvald.terrarum.gameactors.Actor
|
||||
import net.torvald.terrarum.itemproperties.GameItem
|
||||
import net.torvald.terrarum.itemproperties.ItemCodex
|
||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.*
|
||||
import net.torvald.terrarum.roundInt
|
||||
import java.io.File
|
||||
import java.nio.charset.Charset
|
||||
|
||||
@@ -18,43 +22,116 @@ object SavegameWriter {
|
||||
|
||||
private val charset = Charset.forName("UTF-8")
|
||||
|
||||
private lateinit var playerName: String
|
||||
|
||||
operator fun invoke(): Boolean {
|
||||
val diskImage = generateDiskImage(null)
|
||||
playerName = "${Terrarum.ingame!!.actorGamer!!.actorValue[AVKey.NAME]}"
|
||||
if (playerName.isEmpty()) playerName = "Test subject ${Math.random().times(0x7FFFFFFF).roundInt()}"
|
||||
|
||||
try {
|
||||
val diskImage = generateNewDiskImage()
|
||||
val outFile = File("${AppLoader.defaultSaveDir}/$playerName")
|
||||
VDUtil.dumpToRealMachine(diskImage, outFile)
|
||||
|
||||
return true
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
private fun generateDiskImage(oldDiskFile: File?): VirtualDisk {
|
||||
val disk = VDUtil.createNewDisk(0x7FFFFFFFFFFFFFFFL, "TerrarumSave", charset)
|
||||
val oldDiskSkimmer = oldDiskFile?.let { DiskSkimmer(oldDiskFile) }
|
||||
|
||||
val ROOT = disk.root.entryID
|
||||
fun generateNewDiskImage(): VirtualDisk {
|
||||
val creationDate = System.currentTimeMillis() / 1000L
|
||||
val ingame = Terrarum.ingame!!
|
||||
val gameworld = ingame.world
|
||||
val player = ingame.actorGamer!!
|
||||
val disk = VDUtil.createNewDisk(0x7FFFFFFFFFFFFFFFL, "Tesv-$playerName", charset)
|
||||
val ROOT = disk.root.entryID
|
||||
|
||||
// serialise current world (stage)
|
||||
val world = WriteLayerDataZip() // filename can be anything that is "tmp_world[n]" where [n] is any number
|
||||
val worldFile = VDUtil.importFile(world!!, gameworld.worldIndex, charset)
|
||||
|
||||
val worldBytes = WriteLayerDataZip(gameworld) // filename can be anything that is "world[n]" where [n] is any number
|
||||
if (worldBytes == null) {
|
||||
throw Error("Serialising world failed")
|
||||
}
|
||||
|
||||
// add current world (stage) to the disk
|
||||
VDUtil.addFile(disk, ROOT, worldFile)
|
||||
VDUtil.registerFile(disk, DiskEntry(
|
||||
gameworld.worldIndex, ROOT,
|
||||
"world${gameworld.worldIndex}".toByteArray(charset),
|
||||
creationDate, creationDate,
|
||||
EntryFile(worldBytes)
|
||||
))
|
||||
|
||||
|
||||
// put other worlds (stages) to the disk (without loading whole oldDiskFile onto the disk)
|
||||
oldDiskSkimmer?.let {
|
||||
// skim-and-write other worlds
|
||||
for (c in 1..ingame.gameworldCount) {
|
||||
if (c != gameworld.worldIndex) {
|
||||
val oldWorldFile = oldDiskSkimmer.requestFile(c)
|
||||
VDUtil.addFile(disk, ROOT, oldWorldFile!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO world[n] is done, needs whole other things
|
||||
|
||||
|
||||
// worldinfo0..3
|
||||
val worldinfoBytes = WriteWorldInfo(gameworld)
|
||||
worldinfoBytes?.forEachIndexed { index, bytes ->
|
||||
VDUtil.registerFile(disk, DiskEntry(
|
||||
32766 - index, ROOT, "worldinfo$index".toByteArray(charset),
|
||||
creationDate, creationDate,
|
||||
EntryFile(bytes)
|
||||
))
|
||||
} ?: throw Error("Serialising worldinfo failed")
|
||||
|
||||
// loadorder.txt
|
||||
VDUtil.registerFile(disk, DiskEntry(
|
||||
32767, ROOT, "load_order.txt".toByteArray(charset),
|
||||
creationDate, creationDate,
|
||||
EntryFile(ByteArray64.fromByteArray(Gdx.files.internal("./assets/mods/LoadOrder.csv").readBytes()))
|
||||
))
|
||||
|
||||
// actors
|
||||
ingame.actorContainerActive.forEach {
|
||||
VDUtil.registerFile(disk, DiskEntry(
|
||||
gameworld.worldIndex, ROOT,
|
||||
it.referenceID!!.toString(16).toUpperCase().toByteArray(charset),
|
||||
creationDate, creationDate,
|
||||
EntryFile(serialiseActor(it))
|
||||
))
|
||||
}
|
||||
ingame.actorContainerInactive.forEach {
|
||||
VDUtil.registerFile(disk, DiskEntry(
|
||||
gameworld.worldIndex, ROOT,
|
||||
it.referenceID!!.toString(16).toUpperCase().toByteArray(charset),
|
||||
creationDate, creationDate,
|
||||
EntryFile(serialiseActor(it))
|
||||
))
|
||||
}
|
||||
|
||||
// items
|
||||
ItemCodex.dynamicItemDescription.forEach { dynamicID, item ->
|
||||
VDUtil.registerFile(disk, DiskEntry(
|
||||
gameworld.worldIndex, ROOT,
|
||||
dynamicID.toString(16).toUpperCase().toByteArray(charset),
|
||||
creationDate, creationDate,
|
||||
EntryFile(serialiseItem(item))
|
||||
))
|
||||
}
|
||||
|
||||
System.gc()
|
||||
|
||||
return disk
|
||||
}
|
||||
|
||||
fun modifyExistingSave(savefile: File): VirtualDisk {
|
||||
TODO()
|
||||
}
|
||||
|
||||
private fun serialiseActor(a: Actor): ByteArray64 {
|
||||
val gson = Gson().toJsonTree(a).toString().toByteArray(charset)
|
||||
return ByteArray64.fromByteArray(gson)
|
||||
}
|
||||
|
||||
private fun serialiseItem(i: GameItem): ByteArray64 {
|
||||
val gson = Gson().toJsonTree(i).toString().toByteArray(charset)
|
||||
return ByteArray64.fromByteArray(gson)
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,9 @@
|
||||
package net.torvald.terrarum.serialise
|
||||
|
||||
import net.torvald.terrarum.AppLoader
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.ByteArray64
|
||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.ByteArray64GrowableOutputStream
|
||||
import net.torvald.terrarum.realestate.LandUtil
|
||||
import java.io.BufferedOutputStream
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
import java.util.zip.Deflater
|
||||
import java.util.zip.DeflaterOutputStream
|
||||
@@ -48,14 +46,16 @@ internal object WriteLayerDataZip {
|
||||
|
||||
|
||||
/**
|
||||
* TODO currently it'll dump the temporary file (tmp_worldinfo1) onto the disk and will return the temp file.
|
||||
* @param world The world to serialise
|
||||
* @param path The directory where the temporary file goes, in relative to the AppLoader.defaultSaveDir. Should NOT start with slashed
|
||||
*
|
||||
* @return File on success; `null` on failure
|
||||
*/
|
||||
internal operator fun invoke(): File? {
|
||||
val world = (Terrarum.ingame!!.world)
|
||||
internal operator fun invoke(world: GameWorld): ByteArray64? {
|
||||
//val sanitisedPath = path.replace('\\', '/').removePrefix("/").replace("../", "")
|
||||
|
||||
val path = "${AppLoader.defaultSaveDir}/tmp_$LAYERS_FILENAME${world.worldIndex}"
|
||||
//val path = "${AppLoader.defaultSaveDir}/$sanitisedPath/tmp_$LAYERS_FILENAME${world.worldIndex}"
|
||||
//val path = "${AppLoader.defaultSaveDir}/tmp_$LAYERS_FILENAME${world.worldIndex}"
|
||||
|
||||
// TODO let's try dump-on-the-disk-then-pack method...
|
||||
|
||||
@@ -69,11 +69,12 @@ internal object WriteLayerDataZip {
|
||||
}*/
|
||||
|
||||
|
||||
val outFile = File(path)
|
||||
if (outFile.exists()) outFile.delete()
|
||||
outFile.createNewFile()
|
||||
//val outFile = File(path)
|
||||
//if (outFile.exists()) outFile.delete()
|
||||
//outFile.createNewFile()
|
||||
|
||||
val outputStream = BufferedOutputStream(FileOutputStream(outFile), 8192)
|
||||
//val outputStream = BufferedOutputStream(FileOutputStream(outFile), 8192)
|
||||
val outputStream = ByteArray64GrowableOutputStream()
|
||||
var deflater: DeflaterOutputStream // couldn't really use one outputstream for all the files.
|
||||
|
||||
fun wb(byteArray: ByteArray) { outputStream.write(byteArray) }
|
||||
@@ -196,15 +197,12 @@ internal object WriteLayerDataZip {
|
||||
// END OF WRITE //
|
||||
//////////////////
|
||||
|
||||
|
||||
|
||||
// replace savemeta with tempfile
|
||||
try {
|
||||
outputStream.flush()
|
||||
outputStream.close()
|
||||
|
||||
|
||||
return outFile
|
||||
return outputStream.toByteArray64()
|
||||
}
|
||||
catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
package net.torvald.terrarum.serialise
|
||||
|
||||
import net.torvald.terrarum.AppLoader
|
||||
import net.torvald.terrarum.ModMgr
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension
|
||||
import net.torvald.terrarum.modulebasegame.weather.WeatherMixer
|
||||
import net.torvald.terrarum.modulebasegame.worldgenerator.RoguelikeRandomiser
|
||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.ByteArray64
|
||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.ByteArray64GrowableOutputStream
|
||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.ByteArray64InputStream
|
||||
import org.apache.commons.codec.digest.DigestUtils
|
||||
import java.io.BufferedOutputStream
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileOutputStream
|
||||
|
||||
object WriteWorldInfo {
|
||||
|
||||
@@ -23,12 +22,11 @@ object WriteWorldInfo {
|
||||
/**
|
||||
* TODO currently it'll dump the temporary file (tmp_worldinfo1) onto the disk and will return the temp file.
|
||||
*
|
||||
* @return File on success; `null` on failure
|
||||
* @return List of ByteArray64, worldinfo0..worldinfo3; `null` on failure
|
||||
*/
|
||||
internal operator fun invoke(): List<File>? {
|
||||
val world = (Terrarum.ingame!!.world)
|
||||
internal operator fun invoke(world: GameWorld): List<ByteArray64>? {
|
||||
|
||||
val path = "${AppLoader.defaultSaveDir}/tmp_worldinfo"
|
||||
//val path = "${AppLoader.defaultSaveDir}/tmp_worldinfo"
|
||||
|
||||
val infileList = arrayOf(
|
||||
ModMgr.getGdxFilesFromEveryMod("blocks/blocks.csv"),
|
||||
@@ -36,40 +34,34 @@ object WriteWorldInfo {
|
||||
ModMgr.getGdxFilesFromEveryMod("materials/materials.csv")
|
||||
)
|
||||
|
||||
val metaFile = File(path + "0")
|
||||
|
||||
val outFiles = ArrayList<File>()
|
||||
outFiles.add(metaFile)
|
||||
|
||||
val outFiles = ArrayList<ByteArray64>() // for worldinfo1-3 only
|
||||
val worldInfoHash = ArrayList<ByteArray>() // hash of worldinfo1-3
|
||||
// try to write worldinfo1-3
|
||||
|
||||
for (filenum in 1..HASHED_FILES_COUNT) {
|
||||
val outFile = File(path + filenum.toString())
|
||||
if (outFile.exists()) outFile.delete()
|
||||
outFile.createNewFile()
|
||||
|
||||
val outputStream = BufferedOutputStream(FileOutputStream(outFile), 256)
|
||||
val outputStream = ByteArray64GrowableOutputStream()
|
||||
val infile = infileList[filenum - 1]
|
||||
|
||||
infile.forEach {
|
||||
outputStream.write("## from file: ${it.nameWithoutExtension()} ##############################\n".toByteArray())
|
||||
val readBytes = it.readBytes()
|
||||
outputStream.write(readBytes)
|
||||
outputStream.write("\n".toByteArray())
|
||||
}
|
||||
|
||||
outputStream.flush()
|
||||
outputStream.close()
|
||||
|
||||
|
||||
outFiles.add(outFile)
|
||||
outFiles.add(outputStream.toByteArray64())
|
||||
|
||||
|
||||
worldInfoHash.add(DigestUtils.sha256(FileInputStream(outFile)))
|
||||
worldInfoHash.add(DigestUtils.sha256(ByteArray64InputStream(outputStream.toByteArray64())))
|
||||
}
|
||||
|
||||
|
||||
// compose save meta (actual writing part)
|
||||
val metaOut = BufferedOutputStream(FileOutputStream(metaFile), 256)
|
||||
val metaOut = ByteArray64GrowableOutputStream()
|
||||
|
||||
|
||||
metaOut.write(META_MAGIC)
|
||||
@@ -78,8 +70,11 @@ object WriteWorldInfo {
|
||||
|
||||
// world name
|
||||
val worldNameBytes = world.worldName.toByteArray(Charsets.UTF_8)
|
||||
metaOut.write(worldNameBytes)
|
||||
if (worldNameBytes.last() != NULL) metaOut.write(NULL.toInt())
|
||||
//metaOut.write(worldNameBytes)
|
||||
worldNameBytes.forEach {
|
||||
if (it != 0.toByte()) metaOut.write(it.toInt())
|
||||
}
|
||||
metaOut.write(NULL.toInt())
|
||||
|
||||
// terrain seed
|
||||
metaOut.write(world.generatorSeed.toLittle())
|
||||
@@ -125,7 +120,7 @@ object WriteWorldInfo {
|
||||
|
||||
|
||||
|
||||
return outFiles.toList()
|
||||
return listOf(metaOut.toByteArray64()) + outFiles.toList()
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user