diff --git a/lib/TerranVirtualDisk.jar b/lib/TerranVirtualDisk.jar index 9a9981c7b..b6af461a4 100644 Binary files a/lib/TerranVirtualDisk.jar and b/lib/TerranVirtualDisk.jar differ diff --git a/lib/source/TerranVirtualDisk-src.jar b/lib/source/TerranVirtualDisk-src.jar index a88b2c608..355c7200c 100644 Binary files a/lib/source/TerranVirtualDisk-src.jar and b/lib/source/TerranVirtualDisk-src.jar differ diff --git a/src/net/torvald/terrarum/console/CommandDict.kt b/src/net/torvald/terrarum/console/CommandDict.kt index 275e7dcc6..d17cedc61 100644 --- a/src/net/torvald/terrarum/console/CommandDict.kt +++ b/src/net/torvald/terrarum/console/CommandDict.kt @@ -58,7 +58,7 @@ object CommandDict { "imtest" to JavaIMTest, "cheatmotherfuckernootnoot" to CheatWarnTest, "spawnlunarlander" to SpawnPhysTestLunarLander, - + "savetest" to SavegameWriterTest, /* !! */"exportlayer" to ExportLayerData, /* !! */"importlayer" to ImportLayerData, diff --git a/src/net/torvald/terrarum/modulebasegame/console/GsonTest.kt b/src/net/torvald/terrarum/modulebasegame/console/GsonTest.kt index 408b0c371..7e5c20502 100644 --- a/src/net/torvald/terrarum/modulebasegame/console/GsonTest.kt +++ b/src/net/torvald/terrarum/modulebasegame/console/GsonTest.kt @@ -1,11 +1,11 @@ package net.torvald.terrarum.modulebasegame.console -import com.google.gson.GsonBuilder import net.torvald.terrarum.AppLoader import net.torvald.terrarum.Terrarum import net.torvald.terrarum.console.ConsoleCommand import net.torvald.terrarum.console.Echo import net.torvald.terrarum.modulebasegame.Ingame +import net.torvald.terrarum.serialise.SavegameWriter import java.io.BufferedWriter import java.io.FileWriter import java.io.IOException @@ -17,18 +17,7 @@ internal object GsonTest : ConsoleCommand { override fun execute(args: Array) { if (args.size == 2) { - val jsonBuilder = if (AppLoader.IS_DEVELOPMENT_BUILD) { - GsonBuilder() - .setPrettyPrinting() - - .serializeNulls() - .create() - } - else { - GsonBuilder() - .serializeNulls() - .create() - } + val jsonBuilder = SavegameWriter.getJsonBuilder() val jsonString = jsonBuilder.toJson((Terrarum.ingame!! as Ingame).actorNowPlaying) diff --git a/src/net/torvald/terrarum/modulebasegame/console/SavegameWriterTest.kt b/src/net/torvald/terrarum/modulebasegame/console/SavegameWriterTest.kt new file mode 100644 index 000000000..77530057f --- /dev/null +++ b/src/net/torvald/terrarum/modulebasegame/console/SavegameWriterTest.kt @@ -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) { + val r = SavegameWriter.invoke(args.getOrNull(1)) + if (!r) { + EchoError("Saving failed") + } + } + + override fun printUsage() { + Echo("savetest [optional out name}") + } +} \ No newline at end of file diff --git a/src/net/torvald/terrarum/serialise/SavegameWriter.kt b/src/net/torvald/terrarum/serialise/SavegameWriter.kt index d900dd4cc..9b61b27bb 100644 --- a/src/net/torvald/terrarum/serialise/SavegameWriter.kt +++ b/src/net/torvald/terrarum/serialise/SavegameWriter.kt @@ -1,7 +1,7 @@ package net.torvald.terrarum.serialise import com.badlogic.gdx.Gdx -import com.google.gson.Gson +import com.google.gson.GsonBuilder import net.torvald.terrarum.AppLoader import net.torvald.terrarum.Terrarum import net.torvald.terrarum.gameactors.AVKey @@ -24,8 +24,8 @@ object SavegameWriter { private lateinit var playerName: String - operator fun invoke(): Boolean { - playerName = "${Terrarum.ingame!!.actorGamer!!.actorValue[AVKey.NAME]}" + operator fun invoke(pnameOverride: String? = null): Boolean { + playerName = pnameOverride ?: "${Terrarum.ingame!!.actorGamer!!.actorValue[AVKey.NAME]}" if (playerName.isEmpty()) playerName = "Test subject ${Math.random().times(0x7FFFFFFF).roundInt()}" try { @@ -58,6 +58,14 @@ object SavegameWriter { 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 VDUtil.registerFile(disk, DiskEntry( gameworld.worldIndex, ROOT, @@ -91,7 +99,7 @@ object SavegameWriter { // actors ingame.actorContainerActive.forEach { VDUtil.registerFile(disk, DiskEntry( - gameworld.worldIndex, ROOT, + it.referenceID!!, ROOT, it.referenceID!!.toString(16).toUpperCase().toByteArray(charset), creationDate, creationDate, EntryFile(serialiseActor(it)) @@ -99,7 +107,7 @@ object SavegameWriter { } ingame.actorContainerInactive.forEach { VDUtil.registerFile(disk, DiskEntry( - gameworld.worldIndex, ROOT, + it.referenceID!!, ROOT, it.referenceID!!.toString(16).toUpperCase().toByteArray(charset), creationDate, creationDate, EntryFile(serialiseActor(it)) @@ -109,7 +117,7 @@ object SavegameWriter { // items ItemCodex.dynamicItemDescription.forEach { dynamicID, item -> VDUtil.registerFile(disk, DiskEntry( - gameworld.worldIndex, ROOT, + item.dynamicID, ROOT, dynamicID.toString(16).toUpperCase().toByteArray(charset), creationDate, creationDate, EntryFile(serialiseItem(item)) @@ -125,13 +133,26 @@ object SavegameWriter { TODO() } + fun getJsonBuilder() = if (AppLoader.IS_DEVELOPMENT_BUILD) { + GsonBuilder() + .setPrettyPrinting() + + .serializeNulls() + .create() + } + else { + GsonBuilder() + .serializeNulls() + .create() + } + 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) } 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) } } \ No newline at end of file diff --git a/src/net/torvald/terrarum/serialise/WriteLayerDataZip.kt b/src/net/torvald/terrarum/serialise/WriteLayerDataZip.kt index 7b5b8bc7d..14e0097c7 100644 --- a/src/net/torvald/terrarum/serialise/WriteLayerDataZip.kt +++ b/src/net/torvald/terrarum/serialise/WriteLayerDataZip.kt @@ -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.ByteArray64GrowableOutputStream import net.torvald.terrarum.realestate.LandUtil -import java.io.IOException import java.util.zip.Deflater import java.util.zip.DeflaterOutputStream @@ -99,12 +98,13 @@ internal object WriteLayerDataZip { wi48(LandUtil.getBlockAddr(world, world.spawnX, world.spawnY)) // write payloads // - outputStream.flush() // TERR payload // PRO Debug tip: every deflated bytes must begin with 0x789C or 0x78DA // 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()) wi48(world.width * world.height * 3L / 2) deflater = DeflaterOutputStream(outputStream, Deflater(Deflater.BEST_COMPRESSION), true) @@ -187,8 +187,6 @@ internal object WriteLayerDataZip { wb(PAYLOAD_FOOTER) - - // write footer wb(FILE_FOOTER) @@ -197,21 +195,10 @@ internal object WriteLayerDataZip { // END OF WRITE // ////////////////// - try { - outputStream.flush() - outputStream.close() + outputStream.flush() + outputStream.close() - - return outputStream.toByteArray64() - } - catch (e: IOException) { - e.printStackTrace() - } - finally { - outputStream.close() - } - - return null + return outputStream.toByteArray64() } diff --git a/src/net/torvald/terrarum/tests/ByteArray64Test.kt b/src/net/torvald/terrarum/tests/ByteArray64Test.kt new file mode 100644 index 000000000..6bca648ee --- /dev/null +++ b/src/net/torvald/terrarum/tests/ByteArray64Test.kt @@ -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() +} \ No newline at end of file