Skip to content

Commit

Permalink
chore: build data section tree from map file
Browse files Browse the repository at this point in the history
  • Loading branch information
DarkAtra committed Jun 27, 2023
1 parent f80537e commit 7e7e260
Show file tree
Hide file tree
Showing 35 changed files with 296 additions and 133 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package de.darkatra.bfme2.map.serialization
package de.darkatra.bfme2.map

enum class MapFileCompression(
internal val fourCC: String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package de.darkatra.bfme2.map.riverarea

import de.darkatra.bfme2.Color
import de.darkatra.bfme2.Line2D
import de.darkatra.bfme2.map.serialization.ByteColorSerde
import de.darkatra.bfme2.map.serialization.FourByteColorSerde
import de.darkatra.bfme2.map.serialization.Serialize

data class RiverArea(
Expand All @@ -15,7 +15,7 @@ data class RiverArea(
val noiseTexture: String,
val alphaEdgeTexture: String,
val sparkleTexture: String,
val color: @Serialize(using = ByteColorSerde::class) Color,
val color: @Serialize(using = FourByteColorSerde::class) Color,
val alpha: Float,
val waterHeight: UInt,
val minimumWaterLod: String,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
package de.darkatra.bfme2.map.serialization

import com.google.common.io.CountingInputStream
import de.darkatra.bfme2.map.serialization.model.DataSection
import de.darkatra.bfme2.map.serialization.model.DataSectionHolder
import de.darkatra.bfme2.map.serialization.postprocessing.PostProcessor
import de.darkatra.bfme2.map.serialization.preprocessing.PreProcessor
import java.io.OutputStream

internal class AssetListSerde<T>(
internal class AssetListSerde<T : Any>(
private val serializationContext: SerializationContext,
private val entrySerde: Serde<T>,
private val preProcessor: PreProcessor<List<T>>,
private val postProcessor: PostProcessor<List<T>>
) : Serde<List<T>> {

override fun calculateByteCount(data: List<T>): Long {
return data.sumOf {
4 + 2 + 4 + entrySerde.calculateByteCount(it)
}
override fun collectDataSections(data: List<T>): DataSection {
return DataSectionHolder(
containingData = data.map {
entrySerde.collectDataSections(it)
}
)
}

override fun serialize(outputStream: OutputStream, data: List<T>) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package de.darkatra.bfme2.map.serialization

import com.google.common.io.CountingInputStream
import de.darkatra.bfme2.map.serialization.model.DataSection
import de.darkatra.bfme2.map.serialization.postprocessing.NoopPostProcessor
import de.darkatra.bfme2.map.serialization.postprocessing.PostProcessor
import de.darkatra.bfme2.map.serialization.preprocessing.NoopPreProcessor
Expand All @@ -15,7 +16,9 @@ internal class BlendCountSerde(

private val uIntSerde = UIntSerde(context, NoopPreProcessor(), NoopPostProcessor())

override fun calculateByteCount(data: UInt): Long = uIntSerde.calculateByteCount(data)
override fun collectDataSections(data: UInt): DataSection {
return uIntSerde.collectDataSections(data)
}

override fun serialize(outputStream: OutputStream, data: UInt) {
uIntSerde.serialize(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package de.darkatra.bfme2.map.serialization

import de.darkatra.bfme2.map.serialization.model.DataSection
import de.darkatra.bfme2.map.serialization.model.DataSectionLeaf
import de.darkatra.bfme2.map.serialization.postprocessing.PostProcessor
import de.darkatra.bfme2.map.serialization.preprocessing.PreProcessor
import de.darkatra.bfme2.readBoolean
Expand All @@ -19,5 +21,5 @@ internal class BooleanSerde(
postProcessor
) {

override fun calculateByteCount(data: Boolean): Long = 1
override fun collectDataSections(data: Boolean): DataSection = DataSectionLeaf.BOOLEAN
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package de.darkatra.bfme2.map.serialization

import de.darkatra.bfme2.map.serialization.model.DataSection
import de.darkatra.bfme2.map.serialization.model.DataSectionLeaf
import de.darkatra.bfme2.map.serialization.postprocessing.PostProcessor
import de.darkatra.bfme2.map.serialization.preprocessing.PreProcessor
import de.darkatra.bfme2.readByte
Expand All @@ -19,5 +21,5 @@ internal class ByteSerde(
postProcessor
) {

override fun calculateByteCount(data: Byte): Long = 1
override fun collectDataSections(data: Byte): DataSection = DataSectionLeaf.BYTE
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ package de.darkatra.bfme2.map.serialization

import com.google.common.io.CountingInputStream
import de.darkatra.bfme2.Color
import de.darkatra.bfme2.map.serialization.model.DataSection
import de.darkatra.bfme2.map.serialization.postprocessing.NoopPostProcessor
import de.darkatra.bfme2.map.serialization.postprocessing.PostProcessor
import de.darkatra.bfme2.map.serialization.preprocessing.NoopPreProcessor
import de.darkatra.bfme2.map.serialization.preprocessing.PreProcessor
import de.darkatra.bfme2.readUInt
import de.darkatra.bfme2.writeUInt
import java.io.OutputStream

internal class ColorSerde(
Expand All @@ -14,17 +15,19 @@ internal class ColorSerde(
private val postProcessor: PostProcessor<Color>
) : Serde<Color> {

override fun calculateByteCount(data: Color): Long = 4
private val uIntSerde = UIntSerde(context, NoopPreProcessor(), NoopPostProcessor())

override fun collectDataSections(data: Color): DataSection = uIntSerde.collectDataSections(data.rgba)

override fun serialize(outputStream: OutputStream, data: Color) {
preProcessor.preProcess(data, context).let {
outputStream.writeUInt(it.rgba)
uIntSerde.serialize(outputStream, it.rgba)
}
}

override fun deserialize(inputStream: CountingInputStream): Color {
return Color(
rgba = inputStream.readUInt()
rgba = uIntSerde.deserialize(inputStream)
).also {
postProcessor.postProcess(it, context)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package de.darkatra.bfme2.map.serialization
import com.google.common.io.CountingInputStream
import de.darkatra.bfme2.InvalidDataException
import de.darkatra.bfme2.map.Asset
import de.darkatra.bfme2.map.serialization.model.DataSection
import de.darkatra.bfme2.map.serialization.postprocessing.PostProcessor
import de.darkatra.bfme2.map.serialization.preprocessing.PreProcessor
import java.io.OutputStream
Expand Down Expand Up @@ -37,12 +38,12 @@ internal class ConditionalSerde(
Pair(assetName.name, serdeFactory.getSerde(assetType))
}

override fun calculateByteCount(data: Any): Long {
// TODO: validate that the serializationContext is updated during byte count calculation and peek() behaves as expected
val assetName = serializationContext.peek().assetName
val serde = serdes[assetName]
?: throw IllegalStateException("Could not find serde for '$assetName' calculating byte count for $currentElementName. Expected one of: ${serdes.keys}")
return serde.calculateByteCount(data)
override fun collectDataSections(data: Any): DataSection {
val asset = data::class.findAnnotation<Asset>()
?: throw IllegalStateException("Could not find asset annotation for $currentElementName. Expected one of: ${serdes.keys}")
val serde = serdes[asset.name]
?: throw IllegalStateException("Could not find serde for '${asset.name}' calculating byte count for $currentElementName. Expected one of: ${serdes.keys}")
return serde.collectDataSections(data)
}

override fun serialize(outputStream: OutputStream, data: Any) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package de.darkatra.bfme2.map.serialization

import com.google.common.io.CountingInputStream
import de.darkatra.bfme2.ConversionException
import de.darkatra.bfme2.map.serialization.model.DataSection
import de.darkatra.bfme2.map.serialization.postprocessing.PostProcessor
import de.darkatra.bfme2.map.serialization.preprocessing.PreProcessor
import java.io.OutputStream
Expand Down Expand Up @@ -33,8 +34,8 @@ internal class EnumSerde<T : Enum<*>>(
}
}

override fun calculateByteCount(data: T): Long {
return serde.calculateByteCount(enumValueGetter.call(data)!!)
override fun collectDataSections(data: T): DataSection {
return serde.collectDataSections(enumValueGetter.call(data)!!)
}

override fun serialize(outputStream: OutputStream, data: T) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package de.darkatra.bfme2.map.serialization

import de.darkatra.bfme2.map.serialization.model.DataSection
import de.darkatra.bfme2.map.serialization.model.DataSectionLeaf
import de.darkatra.bfme2.map.serialization.postprocessing.PostProcessor
import de.darkatra.bfme2.map.serialization.preprocessing.PreProcessor
import de.darkatra.bfme2.readFloat
Expand All @@ -19,5 +21,5 @@ internal class FloatSerde(
postProcessor
) {

override fun calculateByteCount(data: Float): Long = 4
override fun collectDataSections(data: Float): DataSection = DataSectionLeaf.FLOAT
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,21 @@ package de.darkatra.bfme2.map.serialization
import com.google.common.io.CountingInputStream
import de.darkatra.bfme2.Color
import de.darkatra.bfme2.InvalidDataException
import de.darkatra.bfme2.map.serialization.model.DataSection
import de.darkatra.bfme2.map.serialization.model.DataSectionLeaf
import de.darkatra.bfme2.map.serialization.postprocessing.PostProcessor
import de.darkatra.bfme2.map.serialization.preprocessing.PreProcessor
import de.darkatra.bfme2.readByte
import de.darkatra.bfme2.writeByte
import java.io.OutputStream

internal class ByteColorSerde(
internal class FourByteColorSerde(
private val context: SerializationContext,
private val preProcessor: PreProcessor<Color>,
private val postProcessor: PostProcessor<Color>
) : Serde<Color> {

override fun calculateByteCount(data: Color): Long = 4
override fun collectDataSections(data: Color): DataSection = DataSectionLeaf(4)

override fun serialize(outputStream: OutputStream, data: Color) {
preProcessor.preProcess(data, context).let {
Expand All @@ -34,7 +36,7 @@ internal class ByteColorSerde(

val unusedAlpha = inputStream.readByte()
if (unusedAlpha != 0.toByte()) {
throw InvalidDataException("Expected unusedAlpha to be 0 using ${ByteColorSerde::class.simpleName}.")
throw InvalidDataException("Expected unusedAlpha to be 0 using ${FourByteColorSerde::class.simpleName}.")
}

return Color(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package de.darkatra.bfme2.map.serialization

import com.google.common.io.CountingInputStream
import de.darkatra.bfme2.InvalidDataException
import de.darkatra.bfme2.map.serialization.model.DataSection
import de.darkatra.bfme2.map.serialization.model.DataSectionLeaf
import de.darkatra.bfme2.map.serialization.postprocessing.PostProcessor
import de.darkatra.bfme2.map.serialization.preprocessing.PreProcessor
import java.io.OutputStream
Expand All @@ -13,7 +15,7 @@ internal class FourByteStringSerde(
private val postProcessor: PostProcessor<String>
) : Serde<String> {

override fun calculateByteCount(data: String): Long = 4
override fun collectDataSections(data: String): DataSection = DataSectionLeaf(4)

override fun serialize(outputStream: OutputStream, data: String) {
preProcessor.preProcess(data, context).let {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import com.google.common.collect.HashBasedTable
import com.google.common.collect.Table
import com.google.common.io.CountingInputStream
import de.darkatra.bfme2.map.heightmap.HeightMap
import de.darkatra.bfme2.map.serialization.model.DataSection
import de.darkatra.bfme2.map.serialization.model.DataSectionHolder
import de.darkatra.bfme2.map.serialization.model.DataSectionLeaf
import de.darkatra.bfme2.map.serialization.postprocessing.PostProcessor
import de.darkatra.bfme2.map.serialization.preprocessing.PreProcessor
import de.darkatra.bfme2.readByte
Expand Down Expand Up @@ -36,22 +39,25 @@ internal class HeightMapDependentMapSerde<V : Any>(
SAGE_BOOLEAN
}

override fun calculateByteCount(data: Table<UInt, UInt, V>): Long {
override fun collectDataSections(data: Table<UInt, UInt, V>): DataSection {

val width = data.rowKeySet().size.toUInt()
val height = data.columnKeySet().size.toUInt()

return (0u until width step 1).sumOf { x ->
(0u until height step 1).sumOf { y ->
when (mode) {
Mode.DEFAULT -> valueSerde.calculateByteCount(data[x, y]!!)
else -> when (x % 8u == 0u) {
true -> 1
else -> 0
return DataSectionHolder(
containingData = (0u until width step 1).map { x ->
DataSectionHolder(
containingData = buildList {
(0u until height step 1).forEach { y ->
when {
mode == Mode.DEFAULT -> add(valueSerde.collectDataSections(data[x, y]!!))
x % 8u == 0u -> add(DataSectionLeaf(1))
}
}
}
}
)
}
}
)
}

override fun serialize(outputStream: OutputStream, data: Table<UInt, UInt, V>) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package de.darkatra.bfme2.map.serialization

import de.darkatra.bfme2.map.serialization.model.DataSection
import de.darkatra.bfme2.map.serialization.model.DataSectionLeaf
import de.darkatra.bfme2.map.serialization.postprocessing.PostProcessor
import de.darkatra.bfme2.map.serialization.preprocessing.PreProcessor
import de.darkatra.bfme2.readInt
Expand All @@ -19,5 +21,5 @@ internal class IntSerde(
postProcessor
) {

override fun calculateByteCount(data: Int): Long = 4
override fun collectDataSections(data: Int): DataSection = DataSectionLeaf.INT
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package de.darkatra.bfme2.map.serialization

import com.google.common.io.CountingInputStream
import de.darkatra.bfme2.map.serialization.model.DataSection
import de.darkatra.bfme2.map.serialization.model.DataSectionHolder
import de.darkatra.bfme2.map.serialization.model.DataSectionLeaf
import de.darkatra.bfme2.map.serialization.postprocessing.PostProcessor
import de.darkatra.bfme2.map.serialization.preprocessing.PreProcessor
import de.darkatra.bfme2.readByte
Expand Down Expand Up @@ -57,18 +60,21 @@ internal class ListSerde<T>(
BYTE
}

override fun calculateByteCount(data: List<T>): Long {
return when (mode) {
Mode.DEFAULT -> when (sizeType) {
SizeType.UINT -> 4
SizeType.USHORT -> 2
SizeType.BYTE -> 1
override fun collectDataSections(data: List<T>): DataSection {
return DataSectionHolder(
containingData = buildList {
if (mode == Mode.DEFAULT) {
add(
when (sizeType) {
SizeType.UINT -> DataSectionLeaf.INT
SizeType.USHORT -> DataSectionLeaf.SHORT
SizeType.BYTE -> DataSectionLeaf.BYTE
}
)
}
addAll(data.map { entrySerde.collectDataSections(it) })
}

else -> 0
} + data.sumOf {
entrySerde.calculateByteCount(it)
}
)
}

override fun serialize(outputStream: OutputStream, data: List<T>) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import com.google.common.io.CountingInputStream
import de.darkatra.bfme2.InvalidDataException
import de.darkatra.bfme2.SkippingInputStream
import de.darkatra.bfme2.map.MapFile
import de.darkatra.bfme2.map.MapFileCompression
import de.darkatra.bfme2.map.serialization.model.AssetEntry
import de.darkatra.bfme2.read7BitIntPrefixedString
import de.darkatra.bfme2.readUInt
import de.darkatra.bfme2.readUShort
Expand Down Expand Up @@ -46,7 +48,7 @@ class MapFileReader {
serializationContext.pop()

val currentEndPosition = inputStream.count
val expectedEndPosition = currentAsset.endPosition
val expectedEndPosition = serializationContext.currentEndPosition
if (!serializationContext.debugMode && currentEndPosition != expectedEndPosition) {
throw InvalidDataException("Error reading '${currentAsset.assetName}'. Expected reader to be at position $expectedEndPosition, but was at $currentEndPosition.")
}
Expand Down
Loading

0 comments on commit 7e7e260

Please sign in to comment.