diff --git a/src/main/java/de/bixilon/minosoft/data/world/ChunkData.kt b/src/main/java/de/bixilon/minosoft/data/world/ChunkData.kt index eb3472b4a..20f227793 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/ChunkData.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/ChunkData.kt @@ -14,13 +14,12 @@ package de.bixilon.minosoft.data.world import de.bixilon.minosoft.data.entities.block.BlockEntity -import de.bixilon.minosoft.data.registries.blocks.BlockState import de.bixilon.minosoft.data.world.biome.source.BiomeSource -import de.bixilon.minosoft.data.world.container.SectionDataProvider +import de.bixilon.minosoft.data.world.container.BlockSectionDataProvider import glm_.vec3.Vec3i class ChunkData( - var blocks: Array?>? = null, + var blocks: Array? = null, var blockEntities: Map? = null, var biomeSource: BiomeSource? = null, var light: Array? = null, diff --git a/src/main/java/de/bixilon/minosoft/data/world/ChunkSection.kt b/src/main/java/de/bixilon/minosoft/data/world/ChunkSection.kt index 4749667d0..c6a1fc112 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/ChunkSection.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/ChunkSection.kt @@ -14,8 +14,8 @@ package de.bixilon.minosoft.data.world import de.bixilon.minosoft.data.entities.block.BlockEntity import de.bixilon.minosoft.data.registries.biomes.Biome -import de.bixilon.minosoft.data.registries.blocks.BlockState import de.bixilon.minosoft.data.world.biome.accessor.NoiseBiomeAccessor +import de.bixilon.minosoft.data.world.container.BlockSectionDataProvider import de.bixilon.minosoft.data.world.container.SectionDataProvider import de.bixilon.minosoft.gui.rendering.util.VecUtil.of import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection @@ -28,7 +28,7 @@ import glm_.vec3.Vec3i * Collection of 16x16x16 blocks */ class ChunkSection( - var blocks: SectionDataProvider = SectionDataProvider(checkSize = true), + var blocks: BlockSectionDataProvider = BlockSectionDataProvider(), var biomes: SectionDataProvider = SectionDataProvider(checkSize = false), var blockEntities: SectionDataProvider = SectionDataProvider(checkSize = false), var light: ByteArray = ByteArray(ProtocolDefinition.BLOCKS_PER_SECTION), // packed (skyLight: 0xF0, blockLight: 0x0F) diff --git a/src/main/java/de/bixilon/minosoft/data/world/container/BlockSectionDataProvider.kt b/src/main/java/de/bixilon/minosoft/data/world/container/BlockSectionDataProvider.kt new file mode 100644 index 000000000..c10448033 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/data/world/container/BlockSectionDataProvider.kt @@ -0,0 +1,36 @@ +package de.bixilon.minosoft.data.world.container + +import de.bixilon.minosoft.data.registries.blocks.BlockState +import de.bixilon.minosoft.data.registries.blocks.types.FluidBlock +import de.bixilon.minosoft.util.KUtil.unsafeCast + +class BlockSectionDataProvider( + data: Array? = null, +) : SectionDataProvider(data, true) { + var fluidCount = 0 + private set + + override fun recalculate() { + super.recalculate() + val data: Array = data?.unsafeCast() ?: return + + fluidCount = 0 + for (blockState in data) { + if (blockState?.block is FluidBlock) { + fluidCount++ + } + } + } + + override fun set(index: Int, value: BlockState?): BlockState? { + val previous = super.set(index, value) + + if (previous?.block !is FluidBlock && value?.block is FluidBlock) { + fluidCount++ + } else if (previous?.block is FluidBlock && value?.block !is FluidBlock) { + fluidCount-- + } + + return previous + } +} diff --git a/src/main/java/de/bixilon/minosoft/data/world/container/SectionDataProvider.kt b/src/main/java/de/bixilon/minosoft/data/world/container/SectionDataProvider.kt index 409daa5d2..079cb8356 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/container/SectionDataProvider.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/container/SectionDataProvider.kt @@ -19,7 +19,7 @@ import de.bixilon.minosoft.util.KUtil.unsafeCast import de.bixilon.minosoft.util.ReadWriteLock import glm_.vec3.Vec3i -class SectionDataProvider( +open class SectionDataProvider( data: Array? = null, val checkSize: Boolean = false, ) : Iterable { @@ -63,7 +63,7 @@ class SectionDataProvider( } - private fun recalculate() { + protected open fun recalculate() { val data = data if (data == null) { count = 0 @@ -129,20 +129,20 @@ class SectionDataProvider( set(y shl 8 or (z shl 4) or x, value) } - operator fun set(index: Int, value: T) { + open operator fun set(index: Int, value: T): T? { lock() var data = data val previous = data?.get(index) if (value == null) { if (previous == null) { unlock() - return + return null } count-- if (count == 0) { this.data = null unlock() - return + return previous as T? } } else if (previous == null) { count++ @@ -163,6 +163,7 @@ class SectionDataProvider( } } unlock() + return previous as T? } fun acquire() { diff --git a/src/main/java/de/bixilon/minosoft/util/chunk/ChunkUtil.kt b/src/main/java/de/bixilon/minosoft/util/chunk/ChunkUtil.kt index 25cb87881..c52993cb5 100644 --- a/src/main/java/de/bixilon/minosoft/util/chunk/ChunkUtil.kt +++ b/src/main/java/de/bixilon/minosoft/util/chunk/ChunkUtil.kt @@ -22,7 +22,7 @@ import de.bixilon.minosoft.data.world.ChunkData import de.bixilon.minosoft.data.world.ChunkSection import de.bixilon.minosoft.data.world.biome.source.PalettedBiomeArray import de.bixilon.minosoft.data.world.biome.source.XZBiomeArray -import de.bixilon.minosoft.data.world.container.SectionDataProvider +import de.bixilon.minosoft.data.world.container.BlockSectionDataProvider import de.bixilon.minosoft.data.world.container.palette.PalettedContainer import de.bixilon.minosoft.data.world.container.palette.PalettedContainerReader import de.bixilon.minosoft.data.world.container.palette.palettes.BiomePaletteFactory @@ -67,7 +67,7 @@ object ChunkUtil { // parse data var arrayPosition = 0 - val sectionBlocks: Array?> = arrayOfNulls(dimension.sections) + val sectionBlocks: Array = arrayOfNulls(dimension.sections) for ((sectionIndex, sectionHeight) in (dimension.lowestSection until dimension.highestSection).withIndex()) { if (!sectionBitMask[sectionIndex]) { continue @@ -99,7 +99,7 @@ object ChunkUtil { blocks[blockNumber] = buffer.connection.registries.blockStateRegistry[blockId] ?: continue } - sectionBlocks[sectionHeight] = SectionDataProvider(blocks, true) + sectionBlocks[sectionHeight] = BlockSectionDataProvider(blocks) } chunkData.blocks = sectionBlocks return chunkData @@ -133,7 +133,7 @@ object ChunkUtil { } var arrayPos = 0 - val sectionBlocks: Array?> = arrayOfNulls(dimension.sections) + val sectionBlocks: Array = arrayOfNulls(dimension.sections) for ((sectionIndex, sectionHeight) in (dimension.lowestSection until dimension.highestSection).withIndex()) { // max sections per chunks in chunk column if (!sectionBitMask[sectionIndex]) { continue @@ -144,7 +144,7 @@ object ChunkUtil { val block = buffer.connection.registries.blockStateRegistry[blockId] ?: continue blocks[blockNumber] = block } - sectionBlocks[sectionHeight] = SectionDataProvider(blocks, true) + sectionBlocks[sectionHeight] = BlockSectionDataProvider(blocks) } chunkData.blocks = sectionBlocks return chunkData @@ -152,7 +152,7 @@ object ChunkUtil { fun readPaletteChunk(buffer: PlayInByteBuffer, dimension: DimensionProperties, sectionBitMask: BitSet?, isFullChunk: Boolean, containsSkyLight: Boolean = false): ChunkData { val chunkData = ChunkData() - val sectionBlocks: Array?> = arrayOfNulls(dimension.sections) + val sectionBlocks: Array = arrayOfNulls(dimension.sections) val light: Array = arrayOfNulls(dimension.sections) var lightReceived = 0 val biomes: Array?> = arrayOfNulls(dimension.sections) @@ -169,7 +169,7 @@ object ChunkUtil { val blockContainer: PalettedContainer = PalettedContainerReader.read(buffer, buffer.connection.registries.blockStateRegistry, paletteFactory = BlockStatePaletteFactory) if (blockContainer.palette !is SingularPalette<*> || blockContainer.palette.item != null) { - sectionBlocks[sectionHeight - dimension.lowestSection] = SectionDataProvider(blockContainer.unpack(), checkSize = true) + sectionBlocks[sectionHeight - dimension.lowestSection] = BlockSectionDataProvider(blockContainer.unpack()) } if (buffer.versionId >= V_21W37A) { val biomeContainer: PalettedContainer = PalettedContainerReader.read(buffer, buffer.connection.registries.biomeRegistry, paletteFactory = BiomePaletteFactory)