diff --git a/src/main/java/de/bixilon/minosoft/data/world/container/block/SectionOcclusion.kt b/src/main/java/de/bixilon/minosoft/data/world/container/block/SectionOcclusion.kt
index 3edbb8ae5..fd0787116 100644
--- a/src/main/java/de/bixilon/minosoft/data/world/container/block/SectionOcclusion.kt
+++ b/src/main/java/de/bixilon/minosoft/data/world/container/block/SectionOcclusion.kt
@@ -20,6 +20,7 @@ import de.bixilon.minosoft.data.registries.blocks.state.BlockState
import de.bixilon.minosoft.data.registries.blocks.state.BlockStateFlags
import de.bixilon.minosoft.data.registries.blocks.types.properties.shape.special.FullOpaqueBlock
import de.bixilon.minosoft.data.registries.blocks.types.properties.shape.special.PotentialFullOpaqueBlock
+import de.bixilon.minosoft.gui.rendering.util.allocator.ShortAllocator
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import it.unimi.dsi.fastutil.ints.IntOpenHashSet
import java.util.*
@@ -29,7 +30,6 @@ class SectionOcclusion(
) {
private var occlusion = EMPTY
private var calculate = false
- private val regions by lazy { ShortArray(ProtocolDefinition.BLOCKS_PER_SECTION) }
fun clear(notify: Boolean) {
update(EMPTY, notify)
@@ -49,7 +49,13 @@ class SectionOcclusion(
clear(notify)
return
}
- update(calculateOcclusion(floodFill()), notify)
+ val array = ALLOCATOR.allocate(ProtocolDefinition.BLOCKS_PER_SECTION)
+ try {
+ val regions = floodFill(array)
+ update(calculateOcclusion(regions), notify)
+ } finally {
+ ALLOCATOR.free(array)
+ }
}
private inline fun ShortArray.updateRegion(x: Int, y: Int, z: Int, id: Short): Boolean {
@@ -85,20 +91,20 @@ class SectionOcclusion(
if (y < ProtocolDefinition.SECTION_MAX_Y) trace(regions, x, y + 1, z, nextId)
}
- private fun floodFill(): ShortArray {
+ private fun floodFill(array: ShortArray): ShortArray {
// mark regions and check direct neighbours
- Arrays.fill(regions, 0.toShort())
+ Arrays.fill(array, 0.toShort())
var next: Short = 0
for (y in 0 until ProtocolDefinition.SECTION_HEIGHT_Y) {
for (z in 0 until ProtocolDefinition.SECTION_WIDTH_Z) {
for (x in 0 until ProtocolDefinition.SECTION_WIDTH_X) {
- startTrace(regions, x, y, z, ++next)
+ startTrace(array, x, y, z, ++next)
}
}
}
- return regions
+ return array
}
private fun calculateOcclusion(regions: ShortArray): BooleanArray {
@@ -198,6 +204,7 @@ class SectionOcclusion(
companion object {
private val EMPTY = BooleanArray(CubeDirections.CUBE_DIRECTION_COMBINATIONS)
+ private val ALLOCATOR = ShortAllocator()
fun BlockState?._isFullyOpaque(): Boolean {
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 a5aec90a2..5daf4039b 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
@@ -14,6 +14,7 @@
package de.bixilon.minosoft.data.world.container.palette.data.array
import de.bixilon.minosoft.data.world.container.palette.data.PaletteData
+import de.bixilon.minosoft.gui.rendering.util.allocator.LongAllocator
import de.bixilon.minosoft.protocol.protocol.ProtocolVersions.V_1_16
import de.bixilon.minosoft.protocol.protocol.buffers.play.PlayInByteBuffer
@@ -39,7 +40,7 @@ class ArrayPaletteData(
} else {
(this.size + valuesPerLong - 1) / valuesPerLong
}
- this.data = LongArrayAllocator.claim(this.size)
+ this.data = ALLOCATOR.allocate(this.size)
if (packetSize != size) {
buffer.pointer += packetSize * Long.SIZE_BYTES // data is ignored
return
@@ -69,10 +70,12 @@ class ArrayPaletteData(
}
override fun free() {
- LongArrayAllocator.free(data)
+ ALLOCATOR.free(data)
}
companion object {
+ private val ALLOCATOR = LongAllocator()
const val LONG_BIT_SPLITTING_VERSION = V_1_16 // ToDo: When did this changed? is just a guess
+
}
}
diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/util/allocator/LongAllocator.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/util/allocator/LongAllocator.kt
new file mode 100644
index 000000000..94ed24064
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/gui/rendering/util/allocator/LongAllocator.kt
@@ -0,0 +1,22 @@
+/*
+ * Minosoft
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.gui.rendering.util.allocator
+
+@Deprecated("kutil 1.27.1")
+class LongAllocator : TemporaryAllocator() {
+
+ override fun getSize(value: LongArray) = value.size
+
+ override fun create(size: Int) = LongArray(size)
+}
diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/util/allocator/ShortAllocator.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/util/allocator/ShortAllocator.kt
new file mode 100644
index 000000000..2d390b6da
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/gui/rendering/util/allocator/ShortAllocator.kt
@@ -0,0 +1,22 @@
+/*
+ * Minosoft
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.gui.rendering.util.allocator
+
+@Deprecated("kutil 1.27.1")
+class ShortAllocator : TemporaryAllocator() {
+
+ override fun getSize(value: ShortArray) = value.size
+
+ override fun create(size: Int) = ShortArray(size)
+}
diff --git a/src/main/java/de/bixilon/minosoft/data/world/container/palette/data/array/LongArrayAllocator.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/util/allocator/TemporaryAllocator.kt
similarity index 72%
rename from src/main/java/de/bixilon/minosoft/data/world/container/palette/data/array/LongArrayAllocator.kt
rename to src/main/java/de/bixilon/minosoft/gui/rendering/util/allocator/TemporaryAllocator.kt
index 36a3fe496..2b5855c6e 100644
--- a/src/main/java/de/bixilon/minosoft/data/world/container/palette/data/array/LongArrayAllocator.kt
+++ b/src/main/java/de/bixilon/minosoft/gui/rendering/util/allocator/TemporaryAllocator.kt
@@ -11,15 +11,16 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
-package de.bixilon.minosoft.data.world.container.palette.data.array
+package de.bixilon.minosoft.gui.rendering.util.allocator
import de.bixilon.kutil.concurrent.lock.locks.reentrant.ReentrantLock
import java.lang.ref.WeakReference
-object LongArrayAllocator {
+@Deprecated("kutil 1.27.1")
+abstract class TemporaryAllocator {
private val lock = ReentrantLock()
- private val list: ArrayList> = ArrayList()
+ private val list: ArrayList> = ArrayList()
private fun cleanup() {
lock.lock()
@@ -33,36 +34,41 @@ object LongArrayAllocator {
lock.unlock()
}
- fun free(array: LongArray) {
+ fun free(array: T) {
lock.lock()
cleanup()
list.add(0, WeakReference(array))
lock.unlock()
}
- fun claim(size: Int): LongArray {
+ fun allocate(size: Int): T {
lock.lock()
- var array: LongArray? = null
+ var array: T? = null
val iterator = list.iterator()
while (iterator.hasNext()) {
val reference = iterator.next()
- array = reference.get()
- if (array == null) {
+ val entry = reference.get()
+ if (entry == null) {
iterator.remove()
continue
}
- if (array.size >= size) {
+ if (getSize(entry) >= size) {
+ array = entry
iterator.remove()
break
}
}
lock.unlock()
- if (array != null && array.size >= size) return array
+ if (array != null) return array
- // println("Allocating long array of size $size")
+ // println("Allocating array of size $size")
- return LongArray(size)
+ return create(size)
}
+
+ protected abstract fun getSize(value: T): Int
+
+ abstract fun create(size: Int): T
}