diff --git a/src/main/java/de/bixilon/minosoft/data/world/container/palette/PalettedContainerReader.kt b/src/main/java/de/bixilon/minosoft/data/world/container/palette/PalettedContainerReader.kt index 0ed3ce407..7e91f29c4 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/container/palette/PalettedContainerReader.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/container/palette/PalettedContainerReader.kt @@ -15,6 +15,7 @@ package de.bixilon.minosoft.data.world.container.palette import de.bixilon.minosoft.data.registries.registries.registry.AbstractRegistry import de.bixilon.minosoft.data.world.container.palette.data.PaletteData +import de.bixilon.minosoft.data.world.container.palette.palettes.BlockStatePaletteFactory import de.bixilon.minosoft.data.world.container.palette.palettes.PaletteFactory import de.bixilon.minosoft.protocol.protocol.buffers.play.PlayInByteBuffer @@ -41,16 +42,27 @@ object PalettedContainerReader { val data = PaletteData.create(buffer.versionId, palette.bits, factory.containerSize) try { data.read(buffer) + if (factory == BlockStatePaletteFactory && data.isEmpty) { // id 0 is air + return null + } val container = PalettedContainer(factory.edgeBits, palette, data) if (container.isEmpty) return null val unpacked = container.unpack() - if (unpacked.isEmpty()) return null + if (unpacked.isAllNull()) return null return unpacked } finally { data.free() } } + + fun Array.isAllNull(): Boolean { + for (entry in this) { + if (entry == null) continue + return false + } + return true + } } diff --git a/src/main/java/de/bixilon/minosoft/data/world/container/palette/data/EmptyPaletteData.kt b/src/main/java/de/bixilon/minosoft/data/world/container/palette/data/EmptyPaletteData.kt index a1d0c1599..6e02df236 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/container/palette/data/EmptyPaletteData.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/container/palette/data/EmptyPaletteData.kt @@ -16,6 +16,7 @@ package de.bixilon.minosoft.data.world.container.palette.data import de.bixilon.minosoft.protocol.protocol.buffers.play.PlayInByteBuffer class EmptyPaletteData(override val size: Int) : PaletteData { + override val isEmpty: Boolean get() = true override fun free() = Unit diff --git a/src/main/java/de/bixilon/minosoft/data/world/container/palette/data/PaletteData.kt b/src/main/java/de/bixilon/minosoft/data/world/container/palette/data/PaletteData.kt index 3d85c7698..d124be644 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/container/palette/data/PaletteData.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/container/palette/data/PaletteData.kt @@ -17,6 +17,7 @@ import de.bixilon.minosoft.data.world.container.palette.data.array.ArrayPaletteD import de.bixilon.minosoft.protocol.protocol.buffers.play.PlayInByteBuffer interface PaletteData { + val isEmpty: Boolean val size: Int fun get(index: Int): Int diff --git a/src/main/java/de/bixilon/minosoft/data/world/container/palette/data/array/ArrayPaletteData.kt b/src/main/java/de/bixilon/minosoft/data/world/container/palette/data/array/ArrayPaletteData.kt index 5daf4039b..e04237bb5 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/container/palette/data/array/ArrayPaletteData.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/container/palette/data/array/ArrayPaletteData.kt @@ -27,25 +27,40 @@ class ArrayPaletteData( private val valuesPerLong = Long.SIZE_BITS / elementBits private lateinit var data: LongArray + override var isEmpty = true + init { check(elementBits in 0..32) } - override fun read(buffer: PlayInByteBuffer) { - val packetSize = buffer.readVarInt() - val size: Int = if (versionId < LONG_BIT_SPLITTING_VERSION) { + private fun calculateLongs(): Int { + if (versionId < LONG_BIT_SPLITTING_VERSION) { val bits = this.size * elementBits - (bits + (Long.SIZE_BITS - 1)) / Long.SIZE_BITS // divide up - } else { - (this.size + valuesPerLong - 1) / valuesPerLong + return (bits + (Long.SIZE_BITS - 1)) / Long.SIZE_BITS // divide up } - this.data = ALLOCATOR.allocate(this.size) - if (packetSize != size) { + return (this.size + valuesPerLong - 1) / valuesPerLong + } + + private fun checkEmpty(size: Int): Boolean { + for (i in 0 until size) { + if (this.data[i] != 0L) { + return false + } + } + return true + } + + override fun read(buffer: PlayInByteBuffer) { + val packetSize = buffer.readVarInt() + val longs = calculateLongs() + this.data = ALLOCATOR.allocate(longs) + if (packetSize != longs) { buffer.pointer += packetSize * Long.SIZE_BYTES // data is ignored return } - buffer.readLongArray(this.data, size) + buffer.readLongArray(this.data, longs) + this.isEmpty = checkEmpty(longs) } override operator fun get(index: Int): Int { diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/block/chunk/ChunkUtil.kt b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/block/chunk/ChunkUtil.kt index 16114cdcf..77e436f6a 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/block/chunk/ChunkUtil.kt +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/block/chunk/ChunkUtil.kt @@ -305,12 +305,4 @@ object ChunkUtil { fun ChunkPosition.isInViewDistance(viewDistance: Int, cameraPosition: ChunkPosition): Boolean { return abs(this.x - cameraPosition.x) <= viewDistance && abs(this.y - cameraPosition.y) <= viewDistance } - - private fun Array.isEmpty(): Boolean { - for (entry in this) { - if (entry == null) continue - return false - } - return true - } }