chunk section: only keep track if section has fluids and not how many, improvements

A lot faster now and the count is not really needed, it will change rarely.
This commit is contained in:
Moritz Zwerger 2025-02-06 21:37:15 +01:00
parent d2d83d85dc
commit c6892e4bd3
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
5 changed files with 68 additions and 23 deletions

View File

@ -1,6 +1,6 @@
/*
* Minosoft
* Copyright (C) 2020-2023 Moritz Zwerger
* Copyright (C) 2020-2025 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
@ -14,6 +14,7 @@
package de.bixilon.minosoft.data.world.container.block
import de.bixilon.kotlinglm.vec3.Vec3i
import de.bixilon.minosoft.data.registries.blocks.WaterTest0
import de.bixilon.minosoft.data.registries.blocks.types.stone.StoneTest0
import de.bixilon.minosoft.data.world.chunk.ChunkSection
import de.bixilon.minosoft.test.ITUtil.allocate
@ -31,7 +32,7 @@ class BlockSectionDataProviderTest {
fun `initial empty`() {
val blocks = create()
assertTrue(blocks.isEmpty)
assertEquals(blocks.fluidCount, 0)
assertFalse(blocks.hasFluid)
assertEquals(blocks.count, 0)
}
@ -40,7 +41,7 @@ class BlockSectionDataProviderTest {
blocks[0] = StoneTest0.state
blocks[0] = null
assertTrue(blocks.isEmpty)
assertEquals(blocks.fluidCount, 0)
assertFalse(blocks.hasFluid)
assertEquals(blocks.count, 0)
}
@ -48,7 +49,15 @@ class BlockSectionDataProviderTest {
val blocks = create()
blocks[0] = StoneTest0.state
assertFalse(blocks.isEmpty)
assertEquals(blocks.fluidCount, 0)
assertFalse(blocks.hasFluid)
assertEquals(blocks.count, 1)
}
fun `single water set`() {
val blocks = create()
blocks[0] = WaterTest0.state
assertFalse(blocks.isEmpty)
assertTrue(blocks.hasFluid)
assertEquals(blocks.count, 1)
}
@ -91,5 +100,30 @@ class BlockSectionDataProviderTest {
assertEquals(blocks.maxPosition, Vec3i(3, 5, 12))
}
/*
fun benchmark() {
val water = WaterTest0.state
val stone = StoneTest0.state
val random = Random(12)
val data = create()
for (i in 0 until ProtocolDefinition.BLOCKS_PER_SECTION) {
if (random.nextBoolean()) {
data[i] = water
} else if (random.nextBoolean()) {
data[i] = stone
}
}
val time = measureTime {
for (i in 0 until 1999_999) {
data.recalculate(false)
}
}
println("Took: ${time.inWholeNanoseconds.formatNanos()}")
}
*/
// TODO: test initial block set
}

View File

@ -1,6 +1,6 @@
/*
* Minosoft
* Copyright (C) 2020-2023 Moritz Zwerger
* Copyright (C) 2020-2025 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
@ -63,7 +63,7 @@ class BlockStateSettings(
val data = this["properties"]?.toJsonObject() ?: return null
if (data.isEmpty()) return null
val properties: MutableMap<BlockProperty<*>, Any> = HashMap()
val properties: MutableMap<BlockProperty<*>, Any> = HashMap(data.size)
for ((group, json) in data) {
try {

View File

@ -1,6 +1,6 @@
/*
* Minosoft
* Copyright (C) 2020-2024 Moritz Zwerger
* Copyright (C) 2020-2025 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
@ -152,8 +152,8 @@ class WaterFluid(resourceLocation: ResourceLocation = identifier) : Fluid(resour
fun BlockState.isWaterlogged(): Boolean {
if (block is PixLyzerBlock && !block.waterloggable) return false
if (this.block !is WaterloggableBlock) return false
if (this !is PropertyBlockState) return false
if (this.block !is WaterloggableBlock) return false // check for interfaces is rather slow, so do it after class checking
return properties[BlockProperties.WATERLOGGED]?.toBoolean() ?: return false
}
}

View File

@ -1,6 +1,6 @@
/*
* Minosoft
* Copyright (C) 2020-2023 Moritz Zwerger
* Copyright (C) 2020-2025 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
@ -26,7 +26,7 @@ class BlockSectionDataProvider(
val section: ChunkSection,
) : SectionDataProvider<BlockState?>(lock, true) {
val occlusion = SectionOcclusion(this)
var fluidCount = 0
var hasFluid = false
private set
init {
@ -37,22 +37,33 @@ class BlockSectionDataProvider(
recalculate(true)
}
fun recalculate(notify: Boolean) {
super.recalculate()
private fun recalculateFluid() {
val data: Array<Any?> = data ?: return
if (isEmpty) {
fluidCount = 0
occlusion.clear(notify)
this.hasFluid = false
return
}
fluidCount = 0
for (blockState in data) {
blockState as BlockState?
if (blockState.isFluid()) {
fluidCount++
var hasFluid = false
for (state in data) {
if (state !is BlockState?) continue
if (state.isFluid()) {
hasFluid = true
break
}
}
this.hasFluid = hasFluid
}
fun recalculate(notify: Boolean) {
super.recalculate()
if (isEmpty) {
hasFluid = false
occlusion.clear(notify)
return
}
recalculateFluid()
occlusion.recalculate(notify)
}
@ -63,9 +74,9 @@ class BlockSectionDataProvider(
val valueFluid = value.isFluid()
if (!previousFluid && valueFluid) {
fluidCount++
hasFluid = true
} else if (previousFluid && !valueFluid) {
fluidCount--
recalculateFluid()
}
return previous

View File

@ -1,6 +1,6 @@
/*
* Minosoft
* Copyright (C) 2020-2023 Moritz Zwerger
* Copyright (C) 2020-2025 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
@ -42,7 +42,7 @@ class ChunkMesher(
try {
solid.mesh(item.chunkPosition, item.sectionHeight, item.chunk, item.section, neighbours, sectionNeighbours, mesh)
if (item.section.blocks.fluidCount > 0) {
if (item.section.blocks.hasFluid) {
fluid.mesh(item.chunkPosition, item.sectionHeight, item.chunk, item.section, neighbours, sectionNeighbours, mesh)
}
} catch (exception: Exception) {