mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-09 07:20:04 -04:00
chunk reading: check early if data is empty
Now it does not allocate chunk data when the section is truly empty (servers sometimes send the opposite and then it turns out that they are empty)
This commit is contained in:
parent
1b869e4761
commit
d3dfcb2a92
@ -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<T>()
|
||||
|
||||
if (unpacked.isEmpty()) return null
|
||||
if (unpacked.isAllNull()) return null
|
||||
|
||||
return unpacked
|
||||
} finally {
|
||||
data.free()
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> Array<T>.isAllNull(): Boolean {
|
||||
for (entry in this) {
|
||||
if (entry == null) continue
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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<BlockState?>.isEmpty(): Boolean {
|
||||
for (entry in this) {
|
||||
if (entry == null) continue
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user