diff --git a/src/net/torvald/terrarum/serialise/Common.kt b/src/net/torvald/terrarum/serialise/Common.kt index 4f6f810b4..c840feca7 100644 --- a/src/net/torvald/terrarum/serialise/Common.kt +++ b/src/net/torvald/terrarum/serialise/Common.kt @@ -11,16 +11,12 @@ 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 net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.ByteArray64Reader -import net.torvald.terrarum.tail import net.torvald.terrarum.utils.* import org.apache.commons.codec.digest.DigestUtils +import java.io.InputStream import java.io.Reader import java.io.StringReader -import java.io.Writer import java.math.BigInteger -import java.nio.channels.ClosedChannelException -import java.nio.charset.Charset -import java.nio.charset.UnsupportedCharsetException import java.util.zip.GZIPInputStream import java.util.zip.GZIPOutputStream @@ -216,8 +212,10 @@ object Common { return layer } - fun bytesToZipdStr(byteIterator: Iterator): String { - val sb = StringBuilder() + fun bytesToZipdStr(byteIterator: Iterator): String = enasciiToString(zip(byteIterator)) + + fun zip(ba: ByteArray64) = Common.zip(ba.iterator()) + fun zip(byteIterator: Iterator): ByteArray64 { val bo = ByteArray64GrowableOutputStream() val zo = GZIPOutputStream(bo) @@ -226,9 +224,13 @@ object Common { zo.write(it.toInt()) } zo.flush(); zo.close() + return bo.toByteArray64() + } + fun enasciiToString(ba: ByteArray64): String = enasciiToString(ba.iterator()) + fun enasciiToString(ba: Iterator): String { + val sb = StringBuilder() // enascii - val ba = bo.toByteArray64() var bai = 0 val buf = IntArray(4) { Ascii85.PAD_BYTE } ba.forEach { @@ -245,9 +247,20 @@ object Common { return sb.toString() } - fun strToBytes(reader: Reader): ByteArray64 { - val unasciidBytes = ByteArray64() + fun unzip(bytes: ByteArray64): ByteArray64 { val unzipdBytes = ByteArray64() + val zi = GZIPInputStream(ByteArray64InputStream(bytes)) + while (true) { + val byte = zi.read() + if (byte == -1) break + unzipdBytes.add(byte.toByte()) + } + zi.close() + return unzipdBytes + } + + fun unasciiToBytes(reader: Reader): ByteArray64 { + val unasciidBytes = ByteArray64() // unascii var bai = 0 @@ -265,18 +278,15 @@ object Common { bai += 1 }; Ascii85.decode(buf[0], buf[1], buf[2], buf[3], buf[4]).forEach { unasciidBytes.add(it) } - // unzip - val zi = GZIPInputStream(ByteArray64InputStream(unasciidBytes)) - while (true) { - val byte = zi.read() - if (byte == -1) break - unzipdBytes.add(byte.toByte()) - } - zi.close() - - return unzipdBytes + return unasciidBytes } + fun getUnzipInputStream(bytes: ByteArray64): InputStream { + return GZIPInputStream(ByteArray64InputStream(bytes)) + } + + fun strToBytes(reader: Reader): ByteArray64 = unzip(unasciiToBytes(reader)) + /** * @param [s] a String * @return UTF-8 encoded [s] which are GZip'd then Ascii85-encoded @@ -288,4 +298,5 @@ object Common { fun unasciiAndUnzipStr(s: String): String { return ByteArray64Reader(strToBytes(StringReader(s)), CHARSET).readText() } + } diff --git a/src/net/torvald/terrarum/serialise/WriteSavegame.kt b/src/net/torvald/terrarum/serialise/WriteSavegame.kt index bcf284c1d..b19aa77c3 100644 --- a/src/net/torvald/terrarum/serialise/WriteSavegame.kt +++ b/src/net/torvald/terrarum/serialise/WriteSavegame.kt @@ -4,8 +4,11 @@ import net.torvald.terrarum.* import net.torvald.terrarum.modulebasegame.TerrarumIngame import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.* +import net.torvald.terrarum.serialise.Common.getUnzipInputStream +import net.torvald.terrarum.serialise.Common.zip import net.torvald.terrarum.serialise.WriteWorld.actorAcceptable import java.io.File +import java.io.Reader /** * It's your responsibility to create a new VirtualDisk if your save is new, and create a backup for modifying existing save. @@ -36,32 +39,32 @@ object WriteSavegame { addFile(disk, meta) // Write BlockCodex// - val blockCodexContent = EntryFile(ByteArray64.fromByteArray(Common.jsoner.toJson(BlockCodex).toByteArray(Common.CHARSET))) + val blockCodexContent = EntryFile(zip(ByteArray64.fromByteArray(Common.jsoner.toJson(BlockCodex).toByteArray(Common.CHARSET)))) val blocks = DiskEntry(-16, 0, "blocks".toByteArray(), creation_t, time_t, blockCodexContent) addFile(disk, blocks) // Write ItemCodex// - val itemCodexContent = EntryFile(ByteArray64.fromByteArray(Common.jsoner.toJson(ItemCodex).toByteArray(Common.CHARSET))) + val itemCodexContent = EntryFile(zip(ByteArray64.fromByteArray(Common.jsoner.toJson(ItemCodex).toByteArray(Common.CHARSET)))) val items = DiskEntry(-17, 0, "items".toByteArray(), creation_t, time_t, itemCodexContent) addFile(disk, items) // Write WireCodex// - val wireCodexContent = EntryFile(ByteArray64.fromByteArray(Common.jsoner.toJson(WireCodex).toByteArray(Common.CHARSET))) + val wireCodexContent = EntryFile(zip(ByteArray64.fromByteArray(Common.jsoner.toJson(WireCodex).toByteArray(Common.CHARSET)))) val wires = DiskEntry(-18, 0, "wires".toByteArray(), creation_t, time_t, wireCodexContent) addFile(disk, wires) // Write MaterialCodex// - val materialCodexContent = EntryFile(ByteArray64.fromByteArray(Common.jsoner.toJson(MaterialCodex).toByteArray(Common.CHARSET))) + val materialCodexContent = EntryFile(zip(ByteArray64.fromByteArray(Common.jsoner.toJson(MaterialCodex).toByteArray(Common.CHARSET)))) val materials = DiskEntry(-19, 0, "materials".toByteArray(), creation_t, time_t, materialCodexContent) addFile(disk, materials) // Write FactionCodex// - val factionCodexContent = EntryFile(ByteArray64.fromByteArray(Common.jsoner.toJson(FactionCodex).toByteArray(Common.CHARSET))) + val factionCodexContent = EntryFile(zip(ByteArray64.fromByteArray(Common.jsoner.toJson(FactionCodex).toByteArray(Common.CHARSET)))) val factions = DiskEntry(-20, 0, "factions".toByteArray(), creation_t, time_t, factionCodexContent) addFile(disk, factions) // Write Apocryphas// - val apocryphasContent = EntryFile(ByteArray64.fromByteArray(Common.jsoner.toJson(Apocryphas).toByteArray(Common.CHARSET))) + val apocryphasContent = EntryFile(zip(ByteArray64.fromByteArray(Common.jsoner.toJson(Apocryphas).toByteArray(Common.CHARSET)))) val apocryphas = DiskEntry(-1024, 0, "modprops".toByteArray(), creation_t, time_t, apocryphasContent) addFile(disk, apocryphas) @@ -98,20 +101,23 @@ object WriteSavegame { */ object LoadSavegame { + private fun getFileBytes(disk: VirtualDisk, id: Int): ByteArray64 = VDUtil.getAsNormalFile(disk, id).getContent() + private fun getFileReader(disk: VirtualDisk, id: Int): Reader = ByteArray64Reader(getFileBytes(disk, id), Common.CHARSET) + operator fun invoke(disk: VirtualDisk) { val meta = ReadMeta(disk) - val player = ReadActor.readActorOnly( - ByteArray64Reader(VDUtil.getAsNormalFile(disk, 9545698).getContent(), Common.CHARSET) - ) as IngamePlayer - val world = ReadWorld.readWorldOnly( - ByteArray64Reader(VDUtil.getAsNormalFile(disk, player.worldCurrentlyPlaying).getContent(), Common.CHARSET) - ) - val actors = world.actors.map { - ReadActor.readActorOnly(ByteArray64Reader(VDUtil.getAsNormalFile(disk, it).getContent(), Common.CHARSET)) - } + val player = ReadActor.readActorOnly(getFileReader(disk, 9545698)) as IngamePlayer + val world = ReadWorld.readWorldOnly(getFileReader(disk, player.worldCurrentlyPlaying)) + val actors = world.actors.map { ReadActor.readActorOnly(getFileReader(disk, it)) } + val block = Common.jsoner.fromJson(BlockCodex.javaClass, getUnzipInputStream(getFileBytes(disk, -16))) + val item = Common.jsoner.fromJson(ItemCodex.javaClass, getUnzipInputStream(getFileBytes(disk, -17))) + val wire = Common.jsoner.fromJson(WireCodex.javaClass, getUnzipInputStream(getFileBytes(disk, -18))) + val material = Common.jsoner.fromJson(MaterialCodex.javaClass, getUnzipInputStream(getFileBytes(disk, -19))) + val faction = Common.jsoner.fromJson(FactionCodex.javaClass, getUnzipInputStream(getFileBytes(disk, -20))) + val apocryphas = Common.jsoner.fromJson(Apocryphas.javaClass, getUnzipInputStream(getFileBytes(disk, -1024))) val ingame = TerrarumIngame(AppLoader.batch) - val worldParam = meta + val worldParam = TerrarumIngame.Codices(meta, block, item, wire, material, faction, apocryphas) ingame.world = world ingame.gameLoadInfoPayload = worldParam ingame.gameLoadMode = TerrarumIngame.GameLoadMode.LOAD_FROM @@ -123,4 +129,5 @@ object LoadSavegame { val loadScreen = SanicLoadScreen AppLoader.setLoadScreen(loadScreen) } + } \ No newline at end of file