mirror of
https://github.com/GayPizzaSpecifications/foundation.git
synced 2025-08-02 21:20:55 +00:00
Gjallarhorn: Implement combined chunk format for storing many chunks in one map.
This commit is contained in:
parent
6bcddb15b5
commit
f0c344ca1f
@ -1,17 +1,23 @@
|
||||
package cloud.kubelet.foundation.gjallarhorn.commands
|
||||
|
||||
import cloud.kubelet.foundation.gjallarhorn.export.ChunkExportLoader
|
||||
import cloud.kubelet.foundation.gjallarhorn.export.CombinedChunkFormat
|
||||
import cloud.kubelet.foundation.gjallarhorn.state.BlockExpanse
|
||||
import cloud.kubelet.foundation.gjallarhorn.state.BlockLogTracker
|
||||
import cloud.kubelet.foundation.gjallarhorn.state.ChangelogSlice
|
||||
import cloud.kubelet.foundation.gjallarhorn.state.SparseBlockStateMap
|
||||
import cloud.kubelet.foundation.gjallarhorn.util.savePngFile
|
||||
import com.github.ajalt.clikt.core.CliktCommand
|
||||
import com.github.ajalt.clikt.core.requireObject
|
||||
import com.github.ajalt.clikt.parameters.arguments.argument
|
||||
import com.github.ajalt.clikt.parameters.options.flag
|
||||
import com.github.ajalt.clikt.parameters.options.option
|
||||
import com.github.ajalt.clikt.parameters.types.enum
|
||||
import com.github.ajalt.clikt.parameters.types.int
|
||||
import com.github.ajalt.clikt.parameters.types.path
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.decodeFromStream
|
||||
import kotlinx.serialization.json.encodeToStream
|
||||
import org.jetbrains.exposed.sql.Database
|
||||
|
||||
class ChunkExportLoaderCommand : CliktCommand("Chunk Export Loader", name = "chunk-export-loader") {
|
||||
@ -21,17 +27,35 @@ class ChunkExportLoaderCommand : CliktCommand("Chunk Export Loader", name = "chu
|
||||
private val world by argument("world")
|
||||
private val chunkLoadLimit by option("--chunk-limit", help = "Chunk Limit").int()
|
||||
private val render by option("--render", help = "Render Top Down Image").enum<ImageRenderType> { it.id }
|
||||
private val loadCombinedFormat by option("--load-combined-format").flag()
|
||||
private val saveCombinedFormat by option("--save-combined-format").flag()
|
||||
|
||||
override fun run() {
|
||||
val tracker = BlockLogTracker(isConcurrent = true)
|
||||
val loader = ChunkExportLoader(tracker = tracker)
|
||||
loader.loadAllChunksForWorld(exportDirectoryPath, world, fast = true, limit = chunkLoadLimit)
|
||||
if (render != null) {
|
||||
val format: CombinedChunkFormat
|
||||
|
||||
val combinedFormatFile = exportDirectoryPath.resolve("combined.json").toFile()
|
||||
format = if (loadCombinedFormat) {
|
||||
Json.decodeFromStream(CombinedChunkFormat.serializer(), combinedFormatFile.inputStream())
|
||||
} else {
|
||||
val tracker = BlockLogTracker(isConcurrent = true)
|
||||
val loader = ChunkExportLoader(tracker = tracker)
|
||||
loader.loadAllChunksForWorld(exportDirectoryPath, world, fast = true, limit = chunkLoadLimit)
|
||||
val expanse = BlockExpanse.zeroOffsetAndMax(tracker.calculateZeroBlockOffset(), tracker.calculateMaxBlock())
|
||||
val map = tracker.buildBlockMap(expanse.offset)
|
||||
val renderer = render!!.createNewRenderer(expanse, db)
|
||||
val image = renderer.render(ChangelogSlice.none, map)
|
||||
CombinedChunkFormat(expanse, map)
|
||||
}
|
||||
|
||||
if (render != null) {
|
||||
val renderer = render!!.createNewRenderer(format.expanse, db)
|
||||
val image = renderer.render(ChangelogSlice.none, format.map)
|
||||
image.savePngFile("full.png")
|
||||
}
|
||||
|
||||
if (saveCombinedFormat) {
|
||||
if (combinedFormatFile.exists()) {
|
||||
combinedFormatFile.delete()
|
||||
}
|
||||
Json.encodeToStream(CombinedChunkFormat.serializer(), format, combinedFormatFile.outputStream())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,6 @@
|
||||
package cloud.kubelet.foundation.gjallarhorn.export
|
||||
|
||||
import cloud.kubelet.foundation.gjallarhorn.state.BlockCoordinate
|
||||
import cloud.kubelet.foundation.gjallarhorn.state.BlockLogTracker
|
||||
import cloud.kubelet.foundation.gjallarhorn.state.BlockState
|
||||
import cloud.kubelet.foundation.gjallarhorn.state.SparseBlockStateMap
|
||||
import cloud.kubelet.foundation.gjallarhorn.state.*
|
||||
import cloud.kubelet.foundation.heimdall.export.ExportedChunk
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.decodeFromStream
|
||||
|
@ -0,0 +1,10 @@
|
||||
package cloud.kubelet.foundation.gjallarhorn.export
|
||||
|
||||
import cloud.kubelet.foundation.gjallarhorn.state.BlockExpanse
|
||||
import cloud.kubelet.foundation.gjallarhorn.state.SparseBlockStateMap
|
||||
|
||||
@kotlinx.serialization.Serializable
|
||||
class CombinedChunkFormat(
|
||||
val expanse: BlockExpanse,
|
||||
val map: SparseBlockStateMap
|
||||
)
|
@ -1,7 +1,9 @@
|
||||
package cloud.kubelet.foundation.gjallarhorn.state
|
||||
|
||||
import java.util.*
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class BlockCoordinate(
|
||||
val x: Long,
|
||||
val y: Long,
|
||||
|
@ -5,10 +5,10 @@ import cloud.kubelet.foundation.gjallarhorn.util.minOfAll
|
||||
import java.util.*
|
||||
import kotlin.math.absoluteValue
|
||||
|
||||
open class BlockCoordinateSparseMap<T> : BlockCoordinateStore<T> {
|
||||
private var internalBlocks = TreeMap<Long, TreeMap<Long, TreeMap<Long, T>>>()
|
||||
open class BlockCoordinateSparseMap<T>(blocks: Map<Long, Map<Long, Map<Long, T>>> = mutableMapOf()) : BlockCoordinateStore<T> {
|
||||
private var internalBlocks = blocks
|
||||
|
||||
val blocks: TreeMap<Long, TreeMap<Long, TreeMap<Long, T>>>
|
||||
val blocks: Map<Long, Map<Long, Map<Long, T>>>
|
||||
get() = internalBlocks
|
||||
|
||||
override fun get(position: BlockCoordinate): T? = internalBlocks[position.x]?.get(position.z)?.get(position.z)
|
||||
@ -16,11 +16,11 @@ open class BlockCoordinateSparseMap<T> : BlockCoordinateStore<T> {
|
||||
override fun getXSection(x: Long): Map<Long, Map<Long, T>>? = internalBlocks[x]
|
||||
|
||||
override fun put(position: BlockCoordinate, value: T) {
|
||||
internalBlocks.getOrPut(position.x) {
|
||||
TreeMap()
|
||||
}.getOrPut(position.z) {
|
||||
TreeMap()
|
||||
}[position.y] = value
|
||||
(((internalBlocks as MutableMap).getOrPut(position.x) {
|
||||
mutableMapOf()
|
||||
} as MutableMap).getOrPut(position.z) {
|
||||
mutableMapOf()
|
||||
} as MutableMap)[position.y] = value
|
||||
}
|
||||
|
||||
override fun createOrModify(position: BlockCoordinate, create: () -> T, modify: (T) -> Unit) {
|
||||
@ -52,11 +52,11 @@ open class BlockCoordinateSparseMap<T> : BlockCoordinateStore<T> {
|
||||
}
|
||||
|
||||
fun applyCoordinateOffset(offset: BlockCoordinate) {
|
||||
val root = TreeMap<Long, TreeMap<Long, TreeMap<Long, T>>>()
|
||||
val root = mutableMapOf<Long, MutableMap<Long, MutableMap<Long, T>>>()
|
||||
internalBlocks = internalBlocks.map { xSection ->
|
||||
val zSectionMap = TreeMap<Long, TreeMap<Long, T>>()
|
||||
val zSectionMap = mutableMapOf<Long, MutableMap<Long, T>>()
|
||||
(xSection.key + offset.x) to xSection.value.map { zSection ->
|
||||
val ySectionMap = TreeMap<Long, T>()
|
||||
val ySectionMap = mutableMapOf<Long, T>()
|
||||
(zSection.key + offset.z) to zSection.value.mapKeys {
|
||||
(it.key + offset.y)
|
||||
}.toMap(ySectionMap)
|
||||
|
@ -1,6 +1,9 @@
|
||||
package cloud.kubelet.foundation.gjallarhorn.state
|
||||
|
||||
class BlockExpanse(
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class BlockExpanse(
|
||||
val offset: BlockCoordinate,
|
||||
val size: BlockCoordinate
|
||||
) {
|
||||
|
@ -1,8 +1,10 @@
|
||||
package cloud.kubelet.foundation.gjallarhorn.state
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
class BlockState(val type: String) {
|
||||
@Serializable(BlockStateSerializer::class)
|
||||
data class BlockState(val type: String) {
|
||||
companion object {
|
||||
private val cache = ConcurrentHashMap<String, BlockState>()
|
||||
|
||||
|
@ -0,0 +1,20 @@
|
||||
package cloud.kubelet.foundation.gjallarhorn.state
|
||||
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.builtins.serializer
|
||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||
import kotlinx.serialization.encoding.Decoder
|
||||
import kotlinx.serialization.encoding.Encoder
|
||||
|
||||
class BlockStateSerializer : KSerializer<BlockState> {
|
||||
override val descriptor: SerialDescriptor
|
||||
get() = String.serializer().descriptor
|
||||
|
||||
override fun deserialize(decoder: Decoder): BlockState {
|
||||
return BlockState.cached(decoder.decodeString())
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: BlockState) {
|
||||
encoder.encodeString(value.type)
|
||||
}
|
||||
}
|
@ -1,3 +1,7 @@
|
||||
package cloud.kubelet.foundation.gjallarhorn.state
|
||||
|
||||
class SparseBlockStateMap : BlockCoordinateSparseMap<BlockState>()
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable(SparseBlockStateMapSerializer::class)
|
||||
class SparseBlockStateMap(blocks: Map<Long, Map<Long, Map<Long, BlockState>>> = mutableMapOf()) :
|
||||
BlockCoordinateSparseMap<BlockState>(blocks)
|
||||
|
@ -0,0 +1,23 @@
|
||||
package cloud.kubelet.foundation.gjallarhorn.state
|
||||
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.builtins.MapSerializer
|
||||
import kotlinx.serialization.builtins.serializer
|
||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||
import kotlinx.serialization.encoding.Decoder
|
||||
import kotlinx.serialization.encoding.Encoder
|
||||
|
||||
class SparseBlockStateMapSerializer : KSerializer<SparseBlockStateMap> {
|
||||
private val internal = MapSerializer(Long.serializer(), MapSerializer(Long.serializer(), MapSerializer(Long.serializer(), BlockState.serializer())))
|
||||
override val descriptor: SerialDescriptor
|
||||
get() = internal.descriptor
|
||||
|
||||
override fun deserialize(decoder: Decoder): SparseBlockStateMap {
|
||||
val data = internal.deserialize(decoder)
|
||||
return SparseBlockStateMap(data)
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: SparseBlockStateMap) {
|
||||
internal.serialize(encoder, value.blocks)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user