map data format adds world generator version and fluids

This commit is contained in:
minjaesong
2019-01-14 19:11:04 +09:00
parent edda3b9ff9
commit a7ec3e77b1
8 changed files with 127 additions and 41 deletions

View File

@@ -1,10 +1,8 @@
package net.torvald.terrarum.serialise package net.torvald.terrarum.serialise
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension
import java.io.IOException import java.io.IOException
import java.io.InputStream import java.io.InputStream
import java.lang.IllegalArgumentException
import java.util.* import java.util.*
/** /**
@@ -123,6 +121,16 @@ fun Int.toLittle() = byteArrayOf(
this.ushr(16).and(0xFF).toByte(), this.ushr(16).and(0xFF).toByte(),
this.ushr(24).and(0xFF).toByte() this.ushr(24).and(0xFF).toByte()
) )
/** Converts int as 2-byte array, discarding the sign.*/
fun Int.toULittleShort() = byteArrayOf(
this.and(0xFF).toByte(),
this.ushr(8).and(0xFF).toByte()
)
/** Converts int as 2-byte array, preserving the sign. In other words, it converts int to short. */
fun Int.toLittleShort() = byteArrayOf(
this.and(0xFF).toByte(),
this.shr(8).and(0xFF).toByte()
)
fun Long.toLittle() = byteArrayOf( fun Long.toLittle() = byteArrayOf(
this.and(0xFF).toByte(), this.and(0xFF).toByte(),
this.ushr(8).and(0xFF).toByte(), this.ushr(8).and(0xFF).toByte(),
@@ -133,7 +141,8 @@ fun Long.toLittle() = byteArrayOf(
this.ushr(48).and(0xFF).toByte(), this.ushr(48).and(0xFF).toByte(),
this.ushr(56).and(0xFF).toByte() this.ushr(56).and(0xFF).toByte()
) )
fun Long.toLittle48() = byteArrayOf( /** Converts long as 6-byte array, discarding the sign. */
fun Long.toULittle48() = byteArrayOf(
this.and(0xFF).toByte(), this.and(0xFF).toByte(),
this.ushr(8).and(0xFF).toByte(), this.ushr(8).and(0xFF).toByte(),
this.ushr(16).and(0xFF).toByte(), this.ushr(16).and(0xFF).toByte(),
@@ -150,6 +159,14 @@ fun ByteArray.toLittleInt() =
this[1].toUint().shl(8) or this[1].toUint().shl(8) or
this[2].toUint().shl(16) or this[2].toUint().shl(16) or
this[3].toUint().shl(24) this[3].toUint().shl(24)
fun ByteArray.toULittleShort() =
if (this.size != 4) throw Error("Array not in size of 2")
else this[0].toUint() or
this[1].toUint().shl(8)
fun ByteArray.toLittleShort() =
if (this.size != 4) throw Error("Array not in size of 2")
else this[0].toUint() or
this[1].toInt().shl(8)
fun ByteArray.toLittleLong() = fun ByteArray.toLittleLong() =
if (this.size != 8) throw Error("Array not in size of 8") if (this.size != 8) throw Error("Array not in size of 8")
else this[0].toUlong() or else this[0].toUlong() or
@@ -171,4 +188,6 @@ fun ByteArray.toLittleInt48() =
fun ByteArray.toLittleFloat() = java.lang.Float.intBitsToFloat(this.toLittleInt()) fun ByteArray.toLittleFloat() = java.lang.Float.intBitsToFloat(this.toLittleInt())
fun Byte.toUlong() = java.lang.Byte.toUnsignedLong(this) fun Byte.toUlong() = java.lang.Byte.toUnsignedLong(this)
fun Byte.toUint() = java.lang.Byte.toUnsignedInt(this) fun Byte.toUint() = java.lang.Byte.toUnsignedInt(this)
const val WORLD_GENERATOR_VERSION = 1

View File

@@ -6,13 +6,12 @@ import net.torvald.terrarum.gameworld.BlockAddress
import net.torvald.terrarum.gameworld.FluidType import net.torvald.terrarum.gameworld.FluidType
import net.torvald.terrarum.gameworld.MapLayer import net.torvald.terrarum.gameworld.MapLayer
import net.torvald.terrarum.gameworld.PairedMapLayer import net.torvald.terrarum.gameworld.PairedMapLayer
import net.torvald.terrarum.realestate.LandUtil
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.DiskSkimmer.Companion.read import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.DiskSkimmer.Companion.read
import net.torvald.terrarum.realestate.LandUtil
import net.torvald.terrarum.toHex import net.torvald.terrarum.toHex
import java.io.* import java.io.*
import java.nio.charset.Charset import java.nio.charset.Charset
import java.util.* import java.util.*
import kotlin.IllegalArgumentException
import kotlin.collections.HashMap import kotlin.collections.HashMap
/** /**
@@ -45,6 +44,7 @@ internal object ReadLayerDataLzma {
val layerCount = inputStream.read(1)[0].toUint() val layerCount = inputStream.read(1)[0].toUint()
val payloadCount = inputStream.read(1)[0].toUint() val payloadCount = inputStream.read(1)[0].toUint()
val compression = inputStream.read(1)[0].toUint() val compression = inputStream.read(1)[0].toUint()
val generatorVer = inputStream.read(2).toULittleShort()
val width = inputStream.read(4).toLittleInt() val width = inputStream.read(4).toLittleInt()
val height = inputStream.read(4).toLittleInt() val height = inputStream.read(4).toLittleInt()
val spawnAddress = inputStream.read(6).toLittleInt48() val spawnAddress = inputStream.read(6).toLittleInt48()
@@ -55,6 +55,7 @@ internal object ReadLayerDataLzma {
printdbg(this, "Layers count: $layerCount") printdbg(this, "Layers count: $layerCount")
printdbg(this, "Payloads count: $payloadCount") printdbg(this, "Payloads count: $payloadCount")
printdbg(this, "Compression: $compression") printdbg(this, "Compression: $compression")
printdbg(this, "World generator version: $generatorVer")
printdbg(this, "Dimension: ${width}x$height") printdbg(this, "Dimension: ${width}x$height")
// read payloads // read payloads

View File

@@ -4,14 +4,16 @@ import net.torvald.terrarum.AppLoader.printdbg
import net.torvald.terrarum.gameworld.BlockAddress import net.torvald.terrarum.gameworld.BlockAddress
import net.torvald.terrarum.gameworld.MapLayer import net.torvald.terrarum.gameworld.MapLayer
import net.torvald.terrarum.gameworld.PairedMapLayer import net.torvald.terrarum.gameworld.PairedMapLayer
import net.torvald.terrarum.realestate.LandUtil
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.DiskSkimmer.Companion.read import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.DiskSkimmer.Companion.read
import net.torvald.terrarum.realestate.LandUtil
import net.torvald.terrarum.toHex import net.torvald.terrarum.toHex
import java.io.* import java.io.File
import java.io.FileInputStream
import java.io.IOException
import java.io.InputStream
import java.nio.charset.Charset import java.nio.charset.Charset
import java.util.* import java.util.*
import java.util.zip.Inflater import java.util.zip.Inflater
import kotlin.IllegalArgumentException
import kotlin.collections.HashMap import kotlin.collections.HashMap
/** /**
@@ -44,6 +46,7 @@ internal object ReadLayerDataZip {
val layerCount = inputStream.read(1)[0].toUint() val layerCount = inputStream.read(1)[0].toUint()
val payloadCount = inputStream.read(1)[0].toUint() val payloadCount = inputStream.read(1)[0].toUint()
val compression = inputStream.read(1)[0].toUint() val compression = inputStream.read(1)[0].toUint()
val generatorVer = inputStream.read(2).toULittleShort()
val width = inputStream.read(4).toLittleInt() val width = inputStream.read(4).toLittleInt()
val height = inputStream.read(4).toLittleInt() val height = inputStream.read(4).toLittleInt()
val spawnAddress = inputStream.read(6).toLittleInt48() val spawnAddress = inputStream.read(6).toLittleInt48()
@@ -54,6 +57,7 @@ internal object ReadLayerDataZip {
printdbg(this, "Layers count: $layerCount") printdbg(this, "Layers count: $layerCount")
printdbg(this, "Payloads count: $payloadCount") printdbg(this, "Payloads count: $payloadCount")
printdbg(this, "Compression: $compression") printdbg(this, "Compression: $compression")
printdbg(this, "World generator version: $generatorVer")
printdbg(this, "Dimension: ${width}x$height") printdbg(this, "Dimension: ${width}x$height")
// read payloads // read payloads

View File

@@ -88,3 +88,5 @@ internal object WriteLayerData {
} }
const val WORLD_WRITER_FORMAT_VERSION = 3

View File

@@ -2,12 +2,9 @@ package net.torvald.terrarum.serialise
import com.badlogic.gdx.utils.compression.Lzma import com.badlogic.gdx.utils.compression.Lzma
import net.torvald.terrarum.AppLoader import net.torvald.terrarum.AppLoader
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.Terrarum import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.console.EchoError
import net.torvald.terrarum.realestate.LandUtil import net.torvald.terrarum.realestate.LandUtil
import java.io.* import java.io.*
import java.nio.charset.Charset
import java.util.zip.DeflaterOutputStream import java.util.zip.DeflaterOutputStream
/** /**
@@ -33,10 +30,11 @@ internal object WriteLayerDataLzma {
val LAYERS_FILENAME = "world" val LAYERS_FILENAME = "world"
val MAGIC = byteArrayOf(0x54, 0x45, 0x4D, 0x7A) val MAGIC = byteArrayOf(0x54, 0x45, 0x4D, 0x7A)
val VERSION_NUMBER = 3.toByte() val VERSION_NUMBER = WORLD_WRITER_FORMAT_VERSION.toByte()
val NUMBER_OF_LAYERS = 3.toByte() val NUMBER_OF_LAYERS = 3.toByte()
val NUMBER_OF_PAYLOADS = 5.toByte() val NUMBER_OF_PAYLOADS = 5.toByte()
val COMPRESSION_ALGORITHM = 2.toByte() val COMPRESSION_ALGORITHM = 2.toByte()
val GENERATOR_VERSION = WORLD_GENERATOR_VERSION.toULittleShort()
val PAYLOAD_HEADER = byteArrayOf(0, 0x70, 0x4C, 0x64) val PAYLOAD_HEADER = byteArrayOf(0, 0x70, 0x4C, 0x64)
val PAYLOAD_FOOTER = byteArrayOf(0x45, 0x6E, 0x64, 0x50, 0x59, 0x4C, 0x64, -1) val PAYLOAD_FOOTER = byteArrayOf(0x45, 0x6E, 0x64, 0x50, 0x59, 0x4C, 0x64, -1)
val FILE_FOOTER = byteArrayOf(0x45, 0x6E, 0x64, 0x54, 0x45, 0x4D, -1, -2) val FILE_FOOTER = byteArrayOf(0x45, 0x6E, 0x64, 0x54, 0x45, 0x4D, -1, -2)
@@ -77,7 +75,7 @@ internal object WriteLayerDataLzma {
fun wb(byte: Byte) { outputStream.write(byte.toInt()) } fun wb(byte: Byte) { outputStream.write(byte.toInt()) }
//fun wb(byte: Int) { outputStream.write(byte) } //fun wb(byte: Int) { outputStream.write(byte) }
fun wi32(int: Int) { wb(int.toLittle()) } fun wi32(int: Int) { wb(int.toLittle()) }
fun wi48(long: Long) { wb(long.toLittle48()) } fun wi48(long: Long) { wb(long.toULittle48()) }
fun wi64(long: Long) { wb(long.toLittle()) } fun wi64(long: Long) { wb(long.toLittle()) }
fun wf32(float: Float) { wi32(float.toRawBits()) } fun wf32(float: Float) { wi32(float.toRawBits()) }
@@ -88,7 +86,7 @@ internal object WriteLayerDataLzma {
// all the necessary headers // all the necessary headers
wb(MAGIC); wb(VERSION_NUMBER); wb(NUMBER_OF_LAYERS); wb(NUMBER_OF_PAYLOADS); wb(COMPRESSION_ALGORITHM) wb(MAGIC); wb(VERSION_NUMBER); wb(NUMBER_OF_LAYERS); wb(NUMBER_OF_PAYLOADS); wb(COMPRESSION_ALGORITHM); wb(GENERATOR_VERSION)
// world width, height, and spawn point // world width, height, and spawn point
wi32(world.width); wi32(world.height) wi32(world.width); wi32(world.height)
@@ -122,11 +120,11 @@ internal object WriteLayerDataLzma {
// TdMG payload // TdMG payload
wb(PAYLOAD_HEADER); wb("TdMG".toByteArray()) wb(PAYLOAD_HEADER); wb("TdMG".toByteArray())
wi48(world.terrainDamages.size.toLong()) wi48(world.terrainDamages.size * 10L)
world.terrainDamages.forEach { t, u -> world.terrainDamages.forEach { t, u ->
Lzma.compress(ByteArrayInputStream(t.toLittle48()), outputStream) Lzma.compress(ByteArrayInputStream(t.toULittle48()), outputStream)
Lzma.compress(ByteArrayInputStream(u.toRawBits().toLittle()), outputStream) Lzma.compress(ByteArrayInputStream(u.toRawBits().toLittle()), outputStream)
} }
@@ -134,16 +132,42 @@ internal object WriteLayerDataLzma {
// WdMG payload // WdMG payload
wb(PAYLOAD_HEADER); wb("WdMG".toByteArray()) wb(PAYLOAD_HEADER); wb("WdMG".toByteArray())
wi48(world.wallDamages.size.toLong()) wi48(world.wallDamages.size * 10L)
world.wallDamages.forEach { t, u -> world.wallDamages.forEach { t, u ->
Lzma.compress(ByteArrayInputStream(t.toLittle48()), outputStream) Lzma.compress(ByteArrayInputStream(t.toULittle48()), outputStream)
Lzma.compress(ByteArrayInputStream(u.toRawBits().toLittle()), outputStream) Lzma.compress(ByteArrayInputStream(u.toRawBits().toLittle()), outputStream)
} }
wb(PAYLOAD_FOOTER) wb(PAYLOAD_FOOTER)
// FlTP payload
wb(PAYLOAD_HEADER); wb("FlTP".toByteArray())
wi48(world.fluidTypes.size * 8L)
world.fluidTypes.forEach { t, u ->
Lzma.compress(ByteArrayInputStream(t.toULittle48()), outputStream)
Lzma.compress(ByteArrayInputStream(u.value.toLittleShort()), outputStream)
}
wb(PAYLOAD_FOOTER)
// FlFL payload
wb(PAYLOAD_HEADER); wb("FlFL".toByteArray())
wi48(world.fluidFills.size * 10L)
world.fluidFills.forEach { t, u ->
Lzma.compress(ByteArrayInputStream(t.toULittle48()), outputStream)
Lzma.compress(ByteArrayInputStream(u.toRawBits().toLittle()), outputStream)
}
wb(PAYLOAD_FOOTER)
// write footer // write footer
wb(FILE_FOOTER) wb(FILE_FOOTER)

View File

@@ -1,18 +1,14 @@
package net.torvald.terrarum.serialise package net.torvald.terrarum.serialise
import net.torvald.terrarum.AppLoader import net.torvald.terrarum.AppLoader
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.Terrarum import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.console.EchoError
import net.torvald.terrarum.realestate.LandUtil import net.torvald.terrarum.realestate.LandUtil
import java.io.BufferedOutputStream import java.io.BufferedOutputStream
import java.io.File import java.io.File
import java.io.FileOutputStream import java.io.FileOutputStream
import java.io.IOException import java.io.IOException
import java.nio.charset.Charset
import java.util.zip.Deflater import java.util.zip.Deflater
import java.util.zip.DeflaterOutputStream import java.util.zip.DeflaterOutputStream
import java.util.zip.GZIPOutputStream
/** /**
* This object only writes a file named 'worldinfo1'. * This object only writes a file named 'worldinfo1'.
@@ -39,10 +35,11 @@ internal object WriteLayerDataZip {
val LAYERS_FILENAME = "world" val LAYERS_FILENAME = "world"
val MAGIC = byteArrayOf(0x54, 0x45, 0x4D, 0x7A) val MAGIC = byteArrayOf(0x54, 0x45, 0x4D, 0x7A)
val VERSION_NUMBER = 3.toByte() val VERSION_NUMBER = WORLD_WRITER_FORMAT_VERSION.toByte()
val NUMBER_OF_LAYERS = 3.toByte() val NUMBER_OF_LAYERS = 3.toByte()
val NUMBER_OF_PAYLOADS = 5.toByte() val NUMBER_OF_PAYLOADS = 5.toByte()
val COMPRESSION_ALGORITHM = 1.toByte() val COMPRESSION_ALGORITHM = 1.toByte()
val GENERATOR_VERSION = WORLD_GENERATOR_VERSION.toULittleShort()
val PAYLOAD_HEADER = byteArrayOf(0, 0x70, 0x4C, 0x64) val PAYLOAD_HEADER = byteArrayOf(0, 0x70, 0x4C, 0x64)
val PAYLOAD_FOOTER = byteArrayOf(0x45, 0x6E, 0x64, 0x50, 0x59, 0x4C, 0x64, -1) val PAYLOAD_FOOTER = byteArrayOf(0x45, 0x6E, 0x64, 0x50, 0x59, 0x4C, 0x64, -1)
val FILE_FOOTER = byteArrayOf(0x45, 0x6E, 0x64, 0x54, 0x45, 0x4D, -1, -2) val FILE_FOOTER = byteArrayOf(0x45, 0x6E, 0x64, 0x54, 0x45, 0x4D, -1, -2)
@@ -83,7 +80,7 @@ internal object WriteLayerDataZip {
fun wb(byte: Byte) { outputStream.write(byte.toInt()) } fun wb(byte: Byte) { outputStream.write(byte.toInt()) }
//fun wb(byte: Int) { outputStream.write(byte) } //fun wb(byte: Int) { outputStream.write(byte) }
fun wi32(int: Int) { wb(int.toLittle()) } fun wi32(int: Int) { wb(int.toLittle()) }
fun wi48(long: Long) { wb(long.toLittle48()) } fun wi48(long: Long) { wb(long.toULittle48()) }
fun wi64(long: Long) { wb(long.toLittle()) } fun wi64(long: Long) { wb(long.toLittle()) }
fun wf32(float: Float) { wi32(float.toRawBits()) } fun wf32(float: Float) { wi32(float.toRawBits()) }
@@ -94,7 +91,7 @@ internal object WriteLayerDataZip {
// all the necessary headers // all the necessary headers
wb(MAGIC); wb(VERSION_NUMBER); wb(NUMBER_OF_LAYERS); wb(NUMBER_OF_PAYLOADS); wb(COMPRESSION_ALGORITHM) wb(MAGIC); wb(VERSION_NUMBER); wb(NUMBER_OF_LAYERS); wb(NUMBER_OF_PAYLOADS); wb(COMPRESSION_ALGORITHM); wb(GENERATOR_VERSION)
// world width, height, and spawn point // world width, height, and spawn point
wi32(world.width); wi32(world.height) wi32(world.width); wi32(world.height)
@@ -134,12 +131,12 @@ internal object WriteLayerDataZip {
// TdMG payload // TdMG payload
wb(PAYLOAD_HEADER); wb("TdMG".toByteArray()) wb(PAYLOAD_HEADER); wb("TdMG".toByteArray())
wi48(world.terrainDamages.size.toLong()) wi48(world.terrainDamages.size * 10L)
deflater = DeflaterOutputStream(outputStream, Deflater(Deflater.BEST_COMPRESSION), true) deflater = DeflaterOutputStream(outputStream, Deflater(Deflater.BEST_COMPRESSION), true)
world.terrainDamages.forEach { t, u -> world.terrainDamages.forEach { t, u ->
deflater.write(t.toLittle48()) deflater.write(t.toULittle48())
deflater.write(u.toRawBits().toLittle()) deflater.write(u.toRawBits().toLittle())
} }
@@ -148,18 +145,49 @@ internal object WriteLayerDataZip {
// WdMG payload // WdMG payload
wb(PAYLOAD_HEADER); wb("WdMG".toByteArray()) wb(PAYLOAD_HEADER); wb("WdMG".toByteArray())
wi48(world.wallDamages.size.toLong()) wi48(world.wallDamages.size * 10L)
deflater = DeflaterOutputStream(outputStream, Deflater(Deflater.BEST_COMPRESSION), true) deflater = DeflaterOutputStream(outputStream, Deflater(Deflater.BEST_COMPRESSION), true)
world.wallDamages.forEach { t, u -> world.wallDamages.forEach { t, u ->
deflater.write(t.toLittle48()) deflater.write(t.toULittle48())
deflater.write(u.toRawBits().toLittle()) deflater.write(u.toRawBits().toLittle())
} }
deflater.finish() deflater.finish()
wb(PAYLOAD_FOOTER) wb(PAYLOAD_FOOTER)
// FlTP payload
wb(PAYLOAD_HEADER); wb("FlTP".toByteArray())
wi48(world.fluidTypes.size * 8L)
deflater = DeflaterOutputStream(outputStream, Deflater(Deflater.BEST_COMPRESSION), true)
world.fluidTypes.forEach { t, u ->
deflater.write(t.toULittle48())
deflater.write(u.value.toLittleShort())
}
deflater.finish()
wb(PAYLOAD_FOOTER)
// FlFL payload
wb(PAYLOAD_HEADER); wb("FlFL".toByteArray())
wi48(world.fluidFills.size * 10L)
deflater = DeflaterOutputStream(outputStream, Deflater(Deflater.BEST_COMPRESSION), true)
world.fluidFills.forEach { t, u ->
deflater.write(t.toULittle48())
deflater.write(u.toRawBits().toLittle())
}
deflater.finish()
wb(PAYLOAD_FOOTER)
// write footer // write footer
wb(FILE_FOOTER) wb(FILE_FOOTER)

View File

@@ -1,10 +1,8 @@
package net.torvald.terrarum.serialise package net.torvald.terrarum.serialise
import com.badlogic.gdx.Gdx
import net.torvald.terrarum.AppLoader import net.torvald.terrarum.AppLoader
import net.torvald.terrarum.ModMgr import net.torvald.terrarum.ModMgr
import net.torvald.terrarum.Terrarum import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.modulebasegame.gameactors.PlayerBuilder
import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension
import net.torvald.terrarum.modulebasegame.weather.WeatherMixer import net.torvald.terrarum.modulebasegame.weather.WeatherMixer
import net.torvald.terrarum.modulebasegame.worldgenerator.RoguelikeRandomiser import net.torvald.terrarum.modulebasegame.worldgenerator.RoguelikeRandomiser
@@ -101,11 +99,11 @@ object WriteWorldInfo {
metaOut.write((world as GameWorldExtension).time.TIME_T.toLittle()) metaOut.write((world as GameWorldExtension).time.TIME_T.toLittle())
// creation time (real world time) // creation time (real world time)
metaOut.write(world.creationTime.toLittle48()) metaOut.write(world.creationTime.toULittle48())
// time at save (real world time) // time at save (real world time)
val timeNow = System.currentTimeMillis() / 1000L val timeNow = System.currentTimeMillis() / 1000L
metaOut.write(timeNow.toLittle48()) metaOut.write(timeNow.toULittle48())
// get playtime and save it // get playtime and save it
val timeToAdd = (timeNow - world.loadTime).toInt() val timeToAdd = (timeNow - world.loadTime).toInt()

View File

@@ -8,7 +8,7 @@ Ord Hex Description
02 4D M 02 4D M
03 7A z # 'z' because it's compressed 03 7A z # 'z' because it's compressed
04 03 Version revision number (unreleased numbers also count) 04 03 Version revision number of this format (unreleased numbers also count)
05 03 Number of layers, NOT the number of payload 05 03 Number of layers, NOT the number of payload
@@ -17,22 +17,25 @@ Ord Hex Description
07 01 Compression algorithm, 0 for none, 1 for DEFLATE, 2 for LZMA, otherwise undefined (maybe LZMA2 for the future?) 07 01 Compression algorithm, 0 for none, 1 for DEFLATE, 2 for LZMA, otherwise undefined (maybe LZMA2 for the future?)
Value of 01 (DEFLATE) is recommended for its faster compression Value of 01 (DEFLATE) is recommended for its faster compression
08 World width 08 World generator version. If the generator adds new feature (e.g. new ores, new buildings)
09 World width 09 this number must be incremented by one.
0A World width 0A World width
0B World width 0B World width
0C World width
0D World width
0C World height
0D World height
0E World height 0E World height
0F World height 0F World height
10 World height
11 World height
10 Default spawn coord in Absolute Tile Number
11 Default spawn coord in Absolute Tile Number
12 Default spawn coord in Absolute Tile Number 12 Default spawn coord in Absolute Tile Number
13 Default spawn coord in Absolute Tile Number 13 Default spawn coord in Absolute Tile Number
14 Default spawn coord in Absolute Tile Number 14 Default spawn coord in Absolute Tile Number
15 Default spawn coord in Absolute Tile Number 15 Default spawn coord in Absolute Tile Number
16 Default spawn coord in Absolute Tile Number
17 Default spawn coord in Absolute Tile Number
# Payload # Payload
# #
@@ -62,6 +65,13 @@ Payload "TdMG" -- world terrain damage data, array of: (Int48 tileAddress, Float
Payload "WdMG" -- world walls damage data, array of: (Int48 tileAddress, Float32 damage) Payload "WdMG" -- world walls damage data, array of: (Int48 tileAddress, Float32 damage)
Uncompressed size will be arbitrary (multiple of tens) Uncompressed size will be arbitrary (multiple of tens)
Payload "FlTP" -- world fluid types, array of: (Int48 tileAddress, Signed Int16 type)
Uncompressed size will be arbitrary (multiple of eights)
Payload "FlFL" -- world fluid fills, array of: (Int48 tileAddress, Float32 amount)
Uncompressed size will be arbitrary (multiple of tens)
If the 'amount' < 0.0001f (WorldSimulator.FLUID_MIN_MASS), the entry must be discarded
EOF 45 E EOF 45 E
EOF 6E n EOF 6E n
EOF 64 d EOF 64 d