mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-15 16:16:10 +09:00
seemingly working savewriter with fixed TEVD
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -58,7 +58,7 @@ object CommandDict {
|
|||||||
"imtest" to JavaIMTest,
|
"imtest" to JavaIMTest,
|
||||||
"cheatmotherfuckernootnoot" to CheatWarnTest,
|
"cheatmotherfuckernootnoot" to CheatWarnTest,
|
||||||
"spawnlunarlander" to SpawnPhysTestLunarLander,
|
"spawnlunarlander" to SpawnPhysTestLunarLander,
|
||||||
|
"savetest" to SavegameWriterTest,
|
||||||
|
|
||||||
/* !! */"exportlayer" to ExportLayerData,
|
/* !! */"exportlayer" to ExportLayerData,
|
||||||
/* !! */"importlayer" to ImportLayerData,
|
/* !! */"importlayer" to ImportLayerData,
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package net.torvald.terrarum.modulebasegame.console
|
package net.torvald.terrarum.modulebasegame.console
|
||||||
|
|
||||||
import com.google.gson.GsonBuilder
|
|
||||||
import net.torvald.terrarum.AppLoader
|
import net.torvald.terrarum.AppLoader
|
||||||
import net.torvald.terrarum.Terrarum
|
import net.torvald.terrarum.Terrarum
|
||||||
import net.torvald.terrarum.console.ConsoleCommand
|
import net.torvald.terrarum.console.ConsoleCommand
|
||||||
import net.torvald.terrarum.console.Echo
|
import net.torvald.terrarum.console.Echo
|
||||||
import net.torvald.terrarum.modulebasegame.Ingame
|
import net.torvald.terrarum.modulebasegame.Ingame
|
||||||
|
import net.torvald.terrarum.serialise.SavegameWriter
|
||||||
import java.io.BufferedWriter
|
import java.io.BufferedWriter
|
||||||
import java.io.FileWriter
|
import java.io.FileWriter
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
@@ -17,18 +17,7 @@ internal object GsonTest : ConsoleCommand {
|
|||||||
override fun execute(args: Array<String>) {
|
override fun execute(args: Array<String>) {
|
||||||
if (args.size == 2) {
|
if (args.size == 2) {
|
||||||
|
|
||||||
val jsonBuilder = if (AppLoader.IS_DEVELOPMENT_BUILD) {
|
val jsonBuilder = SavegameWriter.getJsonBuilder()
|
||||||
GsonBuilder()
|
|
||||||
.setPrettyPrinting()
|
|
||||||
|
|
||||||
.serializeNulls()
|
|
||||||
.create()
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
GsonBuilder()
|
|
||||||
.serializeNulls()
|
|
||||||
.create()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
val jsonString = jsonBuilder.toJson((Terrarum.ingame!! as Ingame).actorNowPlaying)
|
val jsonString = jsonBuilder.toJson((Terrarum.ingame!! as Ingame).actorNowPlaying)
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package net.torvald.terrarum.modulebasegame.console
|
||||||
|
|
||||||
|
import net.torvald.terrarum.console.ConsoleCommand
|
||||||
|
import net.torvald.terrarum.console.Echo
|
||||||
|
import net.torvald.terrarum.console.EchoError
|
||||||
|
import net.torvald.terrarum.serialise.SavegameWriter
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2019-02-22.
|
||||||
|
*/
|
||||||
|
internal object SavegameWriterTest: ConsoleCommand {
|
||||||
|
|
||||||
|
override fun execute(args: Array<String>) {
|
||||||
|
val r = SavegameWriter.invoke(args.getOrNull(1))
|
||||||
|
if (!r) {
|
||||||
|
EchoError("Saving failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun printUsage() {
|
||||||
|
Echo("savetest [optional out name}")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package net.torvald.terrarum.serialise
|
package net.torvald.terrarum.serialise
|
||||||
|
|
||||||
import com.badlogic.gdx.Gdx
|
import com.badlogic.gdx.Gdx
|
||||||
import com.google.gson.Gson
|
import com.google.gson.GsonBuilder
|
||||||
import net.torvald.terrarum.AppLoader
|
import net.torvald.terrarum.AppLoader
|
||||||
import net.torvald.terrarum.Terrarum
|
import net.torvald.terrarum.Terrarum
|
||||||
import net.torvald.terrarum.gameactors.AVKey
|
import net.torvald.terrarum.gameactors.AVKey
|
||||||
@@ -24,8 +24,8 @@ object SavegameWriter {
|
|||||||
|
|
||||||
private lateinit var playerName: String
|
private lateinit var playerName: String
|
||||||
|
|
||||||
operator fun invoke(): Boolean {
|
operator fun invoke(pnameOverride: String? = null): Boolean {
|
||||||
playerName = "${Terrarum.ingame!!.actorGamer!!.actorValue[AVKey.NAME]}"
|
playerName = pnameOverride ?: "${Terrarum.ingame!!.actorGamer!!.actorValue[AVKey.NAME]}"
|
||||||
if (playerName.isEmpty()) playerName = "Test subject ${Math.random().times(0x7FFFFFFF).roundInt()}"
|
if (playerName.isEmpty()) playerName = "Test subject ${Math.random().times(0x7FFFFFFF).roundInt()}"
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -58,6 +58,14 @@ object SavegameWriter {
|
|||||||
throw Error("Serialising world failed")
|
throw Error("Serialising world failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!worldBytes.sliceArray(0..3).contentEquals(WriteLayerDataZip.MAGIC)) {
|
||||||
|
worldBytes.forEach {
|
||||||
|
print(it.toUInt().and(255u).toString(16).toUpperCase().padStart(2, '0'))
|
||||||
|
print(' ')
|
||||||
|
}; println()
|
||||||
|
throw Error()
|
||||||
|
}
|
||||||
|
|
||||||
// add current world (stage) to the disk
|
// add current world (stage) to the disk
|
||||||
VDUtil.registerFile(disk, DiskEntry(
|
VDUtil.registerFile(disk, DiskEntry(
|
||||||
gameworld.worldIndex, ROOT,
|
gameworld.worldIndex, ROOT,
|
||||||
@@ -91,7 +99,7 @@ object SavegameWriter {
|
|||||||
// actors
|
// actors
|
||||||
ingame.actorContainerActive.forEach {
|
ingame.actorContainerActive.forEach {
|
||||||
VDUtil.registerFile(disk, DiskEntry(
|
VDUtil.registerFile(disk, DiskEntry(
|
||||||
gameworld.worldIndex, ROOT,
|
it.referenceID!!, ROOT,
|
||||||
it.referenceID!!.toString(16).toUpperCase().toByteArray(charset),
|
it.referenceID!!.toString(16).toUpperCase().toByteArray(charset),
|
||||||
creationDate, creationDate,
|
creationDate, creationDate,
|
||||||
EntryFile(serialiseActor(it))
|
EntryFile(serialiseActor(it))
|
||||||
@@ -99,7 +107,7 @@ object SavegameWriter {
|
|||||||
}
|
}
|
||||||
ingame.actorContainerInactive.forEach {
|
ingame.actorContainerInactive.forEach {
|
||||||
VDUtil.registerFile(disk, DiskEntry(
|
VDUtil.registerFile(disk, DiskEntry(
|
||||||
gameworld.worldIndex, ROOT,
|
it.referenceID!!, ROOT,
|
||||||
it.referenceID!!.toString(16).toUpperCase().toByteArray(charset),
|
it.referenceID!!.toString(16).toUpperCase().toByteArray(charset),
|
||||||
creationDate, creationDate,
|
creationDate, creationDate,
|
||||||
EntryFile(serialiseActor(it))
|
EntryFile(serialiseActor(it))
|
||||||
@@ -109,7 +117,7 @@ object SavegameWriter {
|
|||||||
// items
|
// items
|
||||||
ItemCodex.dynamicItemDescription.forEach { dynamicID, item ->
|
ItemCodex.dynamicItemDescription.forEach { dynamicID, item ->
|
||||||
VDUtil.registerFile(disk, DiskEntry(
|
VDUtil.registerFile(disk, DiskEntry(
|
||||||
gameworld.worldIndex, ROOT,
|
item.dynamicID, ROOT,
|
||||||
dynamicID.toString(16).toUpperCase().toByteArray(charset),
|
dynamicID.toString(16).toUpperCase().toByteArray(charset),
|
||||||
creationDate, creationDate,
|
creationDate, creationDate,
|
||||||
EntryFile(serialiseItem(item))
|
EntryFile(serialiseItem(item))
|
||||||
@@ -125,13 +133,26 @@ object SavegameWriter {
|
|||||||
TODO()
|
TODO()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getJsonBuilder() = if (AppLoader.IS_DEVELOPMENT_BUILD) {
|
||||||
|
GsonBuilder()
|
||||||
|
.setPrettyPrinting()
|
||||||
|
|
||||||
|
.serializeNulls()
|
||||||
|
.create()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
GsonBuilder()
|
||||||
|
.serializeNulls()
|
||||||
|
.create()
|
||||||
|
}
|
||||||
|
|
||||||
private fun serialiseActor(a: Actor): ByteArray64 {
|
private fun serialiseActor(a: Actor): ByteArray64 {
|
||||||
val gson = Gson().toJsonTree(a).toString().toByteArray(charset)
|
val gson = getJsonBuilder().toJson(a).toByteArray(charset)
|
||||||
return ByteArray64.fromByteArray(gson)
|
return ByteArray64.fromByteArray(gson)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun serialiseItem(i: GameItem): ByteArray64 {
|
private fun serialiseItem(i: GameItem): ByteArray64 {
|
||||||
val gson = Gson().toJsonTree(i).toString().toByteArray(charset)
|
val gson = getJsonBuilder().toJson(i).toByteArray(charset)
|
||||||
return ByteArray64.fromByteArray(gson)
|
return ByteArray64.fromByteArray(gson)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,7 +4,6 @@ import net.torvald.terrarum.gameworld.GameWorld
|
|||||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.ByteArray64
|
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.ByteArray64
|
||||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.ByteArray64GrowableOutputStream
|
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.ByteArray64GrowableOutputStream
|
||||||
import net.torvald.terrarum.realestate.LandUtil
|
import net.torvald.terrarum.realestate.LandUtil
|
||||||
import java.io.IOException
|
|
||||||
import java.util.zip.Deflater
|
import java.util.zip.Deflater
|
||||||
import java.util.zip.DeflaterOutputStream
|
import java.util.zip.DeflaterOutputStream
|
||||||
|
|
||||||
@@ -99,12 +98,13 @@ internal object WriteLayerDataZip {
|
|||||||
wi48(LandUtil.getBlockAddr(world, world.spawnX, world.spawnY))
|
wi48(LandUtil.getBlockAddr(world, world.spawnX, world.spawnY))
|
||||||
|
|
||||||
// write payloads //
|
// write payloads //
|
||||||
outputStream.flush()
|
|
||||||
|
|
||||||
// TERR payload
|
// TERR payload
|
||||||
// PRO Debug tip: every deflated bytes must begin with 0x789C or 0x78DA
|
// PRO Debug tip: every deflated bytes must begin with 0x789C or 0x78DA
|
||||||
// Thus, \0pLd + [10] must be either of these.
|
// Thus, \0pLd + [10] must be either of these.
|
||||||
|
|
||||||
|
// TODO serialised payloads have bit too much zeros, should I be worried?
|
||||||
|
|
||||||
wb(PAYLOAD_HEADER); wb("TERR".toByteArray())
|
wb(PAYLOAD_HEADER); wb("TERR".toByteArray())
|
||||||
wi48(world.width * world.height * 3L / 2)
|
wi48(world.width * world.height * 3L / 2)
|
||||||
deflater = DeflaterOutputStream(outputStream, Deflater(Deflater.BEST_COMPRESSION), true)
|
deflater = DeflaterOutputStream(outputStream, Deflater(Deflater.BEST_COMPRESSION), true)
|
||||||
@@ -187,8 +187,6 @@ internal object WriteLayerDataZip {
|
|||||||
wb(PAYLOAD_FOOTER)
|
wb(PAYLOAD_FOOTER)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// write footer
|
// write footer
|
||||||
wb(FILE_FOOTER)
|
wb(FILE_FOOTER)
|
||||||
|
|
||||||
@@ -197,21 +195,10 @@ internal object WriteLayerDataZip {
|
|||||||
// END OF WRITE //
|
// END OF WRITE //
|
||||||
//////////////////
|
//////////////////
|
||||||
|
|
||||||
try {
|
outputStream.flush()
|
||||||
outputStream.flush()
|
outputStream.close()
|
||||||
outputStream.close()
|
|
||||||
|
|
||||||
|
return outputStream.toByteArray64()
|
||||||
return outputStream.toByteArray64()
|
|
||||||
}
|
|
||||||
catch (e: IOException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
outputStream.close()
|
|
||||||
}
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
64
src/net/torvald/terrarum/tests/ByteArray64Test.kt
Normal file
64
src/net/torvald/terrarum/tests/ByteArray64Test.kt
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.ByteArray64GrowableOutputStream
|
||||||
|
import net.torvald.terrarum.serialise.WriteLayerDataZip
|
||||||
|
import net.torvald.terrarum.serialise.toLittle
|
||||||
|
import net.torvald.terrarum.serialise.toULittle48
|
||||||
|
import java.util.zip.Deflater
|
||||||
|
import java.util.zip.DeflaterOutputStream
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2019-02-22.
|
||||||
|
*/
|
||||||
|
object ByteArray64Test {
|
||||||
|
|
||||||
|
val testOut1 = "TESTING ".toByteArray()
|
||||||
|
val testOut2 = byteArrayOf(-1, -2)
|
||||||
|
val testOut3 = """According to all known laws of aviation, there is no way a bee should be able to fly.
|
||||||
|
Its wings are too small to get its fat little body off the ground.
|
||||||
|
The bee, of course, flies anyway because bees don't care what humans think is impossible.
|
||||||
|
Yellow, black. Yellow, black. Yellow, black. Yellow, black.
|
||||||
|
Ooh, black and yellow! Let's shake it up a little.""".trimIndent().toByteArray()
|
||||||
|
|
||||||
|
operator fun invoke() {
|
||||||
|
val outputStream = ByteArray64GrowableOutputStream(16)
|
||||||
|
|
||||||
|
fun wb(byteArray: ByteArray) { outputStream.write(byteArray) }
|
||||||
|
fun wb(byte: Byte) { outputStream.write(byte.toInt()) }
|
||||||
|
//fun wb(byte: Int) { outputStream.write(byte) }
|
||||||
|
fun wi32(int: Int) { wb(int.toLittle()) }
|
||||||
|
fun wi48(long: Long) { wb(long.toULittle48()) }
|
||||||
|
fun wi64(long: Long) { wb(long.toLittle()) }
|
||||||
|
fun wf32(float: Float) { wi32(float.toRawBits()) }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
wb(WriteLayerDataZip.MAGIC); wb(WriteLayerDataZip.VERSION_NUMBER); wb(WriteLayerDataZip.NUMBER_OF_LAYERS); wb(WriteLayerDataZip.NUMBER_OF_PAYLOADS); wb(WriteLayerDataZip.COMPRESSION_ALGORITHM); wb(WriteLayerDataZip.GENERATOR_VERSION)
|
||||||
|
val deflater = DeflaterOutputStream(outputStream, Deflater(Deflater.BEST_COMPRESSION), true)
|
||||||
|
repeat(20001) {
|
||||||
|
deflater.write(Math.random().times(256).toInt().and(255))
|
||||||
|
}
|
||||||
|
deflater.flush(); deflater.finish()
|
||||||
|
wb(testOut2)
|
||||||
|
|
||||||
|
|
||||||
|
outputStream.flush()
|
||||||
|
outputStream.close()
|
||||||
|
|
||||||
|
val osa = outputStream.toByteArray64()
|
||||||
|
|
||||||
|
osa.forEach {
|
||||||
|
print(it.toUInt().and(255u).toString(16).toUpperCase().padStart(2, '0'))
|
||||||
|
print(' ')
|
||||||
|
}
|
||||||
|
println()
|
||||||
|
|
||||||
|
osa.forEach {
|
||||||
|
print(it.toChar())
|
||||||
|
}
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
ByteArray64Test.invoke()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user