mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-09 15:29:20 -04:00
improve performance of some biome stuff, improve performance of new chunk format
This commit is contained in:
parent
74791305f6
commit
7249367b04
@ -1 +0,0 @@
|
|||||||
--enable-preview
|
|
@ -169,6 +169,7 @@ class Chunk(
|
|||||||
|
|
||||||
fun buildBiomeCache() {
|
fun buildBiomeCache() {
|
||||||
val cacheBiomeAccessor = connection.world.cacheBiomeAccessor ?: return
|
val cacheBiomeAccessor = connection.world.cacheBiomeAccessor ?: return
|
||||||
|
check(!biomesInitialized) { "Biome cache already initialized!" }
|
||||||
check(neighboursLoaded)
|
check(neighboursLoaded)
|
||||||
// val neighbours = connection.world.getChunkNeighbours(chunkPosition)
|
// val neighbours = connection.world.getChunkNeighbours(chunkPosition)
|
||||||
for ((sectionIndex, section) in sections!!.withIndex()) {
|
for ((sectionIndex, section) in sections!!.withIndex()) {
|
||||||
@ -186,8 +187,17 @@ class Chunk(
|
|||||||
|
|
||||||
override fun getBiome(blockPosition: Vec3i): Biome? {
|
override fun getBiome(blockPosition: Vec3i): Biome? {
|
||||||
if (connection.world.cacheBiomeAccessor != null) {
|
if (connection.world.cacheBiomeAccessor != null) {
|
||||||
return get(blockPosition.sectionHeight)?.biomes?.get(blockPosition.x, blockPosition.sectionHeight, blockPosition.z)
|
val sectionHeight = blockPosition.sectionHeight
|
||||||
|
return get(sectionHeight)?.biomes?.get(blockPosition.x, sectionHeight, blockPosition.z)
|
||||||
}
|
}
|
||||||
return biomeSource?.getBiome(blockPosition.inChunkPosition)
|
return biomeSource?.getBiome(blockPosition.inChunkPosition)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getBiome(x: Int, y: Int, z: Int): Biome? {
|
||||||
|
if (connection.world.cacheBiomeAccessor != null) {
|
||||||
|
val sectionHeight = y.sectionHeight
|
||||||
|
return get(sectionHeight)?.biomes?.get(x, sectionHeight, z)
|
||||||
|
}
|
||||||
|
return biomeSource?.getBiome(x and 0x0F, y, z and 0x0F)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,9 +39,13 @@ class ChunkSection(
|
|||||||
constructor(registries: Registries) : this(RegistrySectionDataProvider<BlockState?>(registries.blockStateRegistry.unsafeCast()), RegistrySectionDataProvider(registries.biomeRegistry), SectionDataProvider(), IntArray(ProtocolDefinition.BLOCKS_PER_SECTION))
|
constructor(registries: Registries) : this(RegistrySectionDataProvider<BlockState?>(registries.blockStateRegistry.unsafeCast()), RegistrySectionDataProvider(registries.biomeRegistry), SectionDataProvider(), IntArray(ProtocolDefinition.BLOCKS_PER_SECTION))
|
||||||
|
|
||||||
fun tick(connection: PlayConnection, chunkPosition: Vec2i, sectionHeight: Int) {
|
fun tick(connection: PlayConnection, chunkPosition: Vec2i, sectionHeight: Int) {
|
||||||
|
if (blockEntities.isEmpty) {
|
||||||
|
return
|
||||||
|
}
|
||||||
acquire()
|
acquire()
|
||||||
for ((index, blockEntity) in blockEntities.withIndex()) {
|
var blockEntity: BlockEntity?
|
||||||
blockEntity ?: continue
|
for (index in 0 until ProtocolDefinition.BLOCKS_PER_SECTION) {
|
||||||
|
blockEntity = blockEntities[index] ?: continue
|
||||||
val position = Vec3i.of(chunkPosition, sectionHeight, index.indexPosition)
|
val position = Vec3i.of(chunkPosition, sectionHeight, index.indexPosition)
|
||||||
val blockState = blocks[index] ?: continue
|
val blockState = blocks[index] ?: continue
|
||||||
blockEntity.tick(connection, blockState, position)
|
blockEntity.tick(connection, blockState, position)
|
||||||
@ -86,8 +90,14 @@ class ChunkSection(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun buildBiomeCache(chunkPosition: Vec2i, sectionHeight: Int, biomeAccessor: BiomeAccessor) {
|
fun buildBiomeCache(chunkPosition: Vec2i, sectionHeight: Int, biomeAccessor: BiomeAccessor) {
|
||||||
for (blockIndex in 0 until ProtocolDefinition.BLOCKS_PER_SECTION) {
|
val blockOffset = Vec3i.of(chunkPosition, sectionHeight)
|
||||||
biomes[blockIndex] = biomeAccessor.getBiome(Vec3i.of(chunkPosition, sectionHeight, blockIndex.indexPosition))!!
|
val x = blockOffset.x
|
||||||
|
val y = blockOffset.y
|
||||||
|
val z = blockOffset.z
|
||||||
|
val biomes: Array<Biome?> = arrayOfNulls(ProtocolDefinition.BLOCKS_PER_SECTION)
|
||||||
|
for (index in 0 until ProtocolDefinition.BLOCKS_PER_SECTION) {
|
||||||
|
biomes[index] = biomeAccessor.getBiome(x + (index and 0x0F), y + ((index shr 8) and 0x0F), z + ((index shr 4) and 0x0F)) //!!
|
||||||
}
|
}
|
||||||
|
this.biomes.setData(biomes.unsafeCast())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -149,6 +149,10 @@ class World(
|
|||||||
return biomeAccessor.getBiome(blockPosition)
|
return biomeAccessor.getBiome(blockPosition)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getBiome(x: Int, y: Int, z: Int): Biome? {
|
||||||
|
return biomeAccessor.getBiome(x, y, z)
|
||||||
|
}
|
||||||
|
|
||||||
fun tick() {
|
fun tick() {
|
||||||
for ((chunkPosition, chunk) in chunks.toSynchronizedMap()) {
|
for ((chunkPosition, chunk) in chunks.toSynchronizedMap()) {
|
||||||
chunk.tick(connection, chunkPosition)
|
chunk.tick(connection, chunkPosition)
|
||||||
|
@ -19,5 +19,9 @@ import glm_.vec3.Vec3i
|
|||||||
|
|
||||||
interface BiomeAccessor {
|
interface BiomeAccessor {
|
||||||
|
|
||||||
fun getBiome(blockPosition: Vec3i): Biome?
|
fun getBiome(blockPosition: Vec3i): Biome? {
|
||||||
|
return getBiome(blockPosition.x, blockPosition.y, blockPosition.z)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getBiome(x: Int, y: Int, z: Int): Biome?
|
||||||
}
|
}
|
||||||
|
@ -13,22 +13,19 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.data.world.biome.accessor
|
package de.bixilon.minosoft.data.world.biome.accessor
|
||||||
|
|
||||||
import de.bixilon.minosoft.Minosoft
|
|
||||||
import de.bixilon.minosoft.data.registries.biomes.Biome
|
import de.bixilon.minosoft.data.registries.biomes.Biome
|
||||||
import de.bixilon.minosoft.data.world.World
|
import de.bixilon.minosoft.data.world.World
|
||||||
import de.bixilon.minosoft.data.world.biome.noise.FuzzyNoiseBiomeCalculator
|
import de.bixilon.minosoft.data.world.biome.noise.FuzzyNoiseBiomeCalculator
|
||||||
import de.bixilon.minosoft.data.world.biome.source.SpatialBiomeArray
|
|
||||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil.chunkPosition
|
|
||||||
import glm_.vec3.Vec3i
|
|
||||||
|
|
||||||
class NoiseBiomeAccessor(private val world: World) : BiomeAccessor {
|
class NoiseBiomeAccessor(private val world: World) : BiomeAccessor {
|
||||||
|
|
||||||
override fun getBiome(blockPosition: Vec3i): Biome? {
|
override fun getBiome(x: Int, y: Int, z: Int): Biome? {
|
||||||
val y = if (world.dimension?.supports3DBiomes == true) {
|
val biomeY = if (world.dimension?.supports3DBiomes == true) {
|
||||||
blockPosition.y
|
y
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
if (Minosoft.config.config.game.graphics.fastBiomeNoise) {
|
if (Minosoft.config.config.game.graphics.fastBiomeNoise) {
|
||||||
world[blockPosition.chunkPosition]?.biomeSource?.let {
|
world[blockPosition.chunkPosition]?.biomeSource?.let {
|
||||||
if (it !is SpatialBiomeArray) {
|
if (it !is SpatialBiomeArray) {
|
||||||
@ -37,10 +34,12 @@ class NoiseBiomeAccessor(private val world: World) : BiomeAccessor {
|
|||||||
val x: Int = (blockPosition.x and 0x0F) / 4
|
val x: Int = (blockPosition.x and 0x0F) / 4
|
||||||
val z: Int = (blockPosition.z and 0x0F) / 4
|
val z: Int = (blockPosition.z and 0x0F) / 4
|
||||||
|
|
||||||
return it.data[(y / 4) * 16 + (z * 4 + x)]
|
return it.data[(biomeY / 4) * 16 + (z * 4 + x)]
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
return FuzzyNoiseBiomeCalculator.getBiome(world.hashedSeed, blockPosition.x, y, blockPosition.z, world)
|
|
||||||
|
*/
|
||||||
|
return FuzzyNoiseBiomeCalculator.getBiome(world.hashedSeed, x, biomeY, z, world)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,4 +22,8 @@ object NullBiomeAccessor : BiomeAccessor {
|
|||||||
override fun getBiome(blockPosition: Vec3i): Biome? {
|
override fun getBiome(blockPosition: Vec3i): Biome? {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getBiome(x: Int, y: Int, z: Int): Biome? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,10 @@ import glm_.vec3.Vec3i
|
|||||||
|
|
||||||
class WorldBiomeAccessor(val world: World) : BiomeAccessor {
|
class WorldBiomeAccessor(val world: World) : BiomeAccessor {
|
||||||
|
|
||||||
|
override fun getBiome(x: Int, y: Int, z: Int): Biome? {
|
||||||
|
return getBiome(Vec3i(x, y, z)) // ToDo
|
||||||
|
}
|
||||||
|
|
||||||
override fun getBiome(blockPosition: Vec3i): Biome? {
|
override fun getBiome(blockPosition: Vec3i): Biome? {
|
||||||
return world[blockPosition.chunkPosition]?.getBiome(blockPosition.inChunkPosition)
|
return world[blockPosition.chunkPosition]?.getBiome(blockPosition.inChunkPosition)
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
package de.bixilon.minosoft.data.world.biome.noise
|
package de.bixilon.minosoft.data.world.biome.noise
|
||||||
|
|
||||||
import de.bixilon.minosoft.data.registries.biomes.Biome
|
import de.bixilon.minosoft.data.registries.biomes.Biome
|
||||||
|
|
||||||
import de.bixilon.minosoft.data.world.World
|
import de.bixilon.minosoft.data.world.World
|
||||||
import de.bixilon.minosoft.util.MMath.square
|
import de.bixilon.minosoft.util.MMath.square
|
||||||
import glm_.vec2.Vec2i
|
import glm_.vec2.Vec2i
|
||||||
import glm_.vec3.Vec3i
|
|
||||||
|
|
||||||
object FuzzyNoiseBiomeCalculator {
|
object FuzzyNoiseBiomeCalculator {
|
||||||
|
|
||||||
@ -25,27 +23,27 @@ object FuzzyNoiseBiomeCalculator {
|
|||||||
var s = 0
|
var s = 0
|
||||||
var g = Double.POSITIVE_INFINITY
|
var g = Double.POSITIVE_INFINITY
|
||||||
|
|
||||||
fun calculateFraction(a: Int, mask: Int, first: Int, second: Double): Pair<Int, Double> {
|
|
||||||
(a and mask == 0).let {
|
|
||||||
return Pair(
|
|
||||||
if (it) first else first + 1,
|
|
||||||
if (it) second else second - 1.0
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun checkMask(mask: Int, value: Int): Int {
|
|
||||||
return if (s and mask == 0) {
|
|
||||||
value
|
|
||||||
} else {
|
|
||||||
value + 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i in 0 until 8) {
|
for (i in 0 until 8) {
|
||||||
val (u, xFraction) = calculateFraction(i, 0x04, p, d)
|
var u = p
|
||||||
val (v, yFraction) = calculateFraction(i, 0x02, q, e)
|
var xFraction = d
|
||||||
val (w, zFraction) = calculateFraction(i, 0x01, r, f)
|
if (i and 0x04 != 0) {
|
||||||
|
u++
|
||||||
|
xFraction -= 1.0
|
||||||
|
}
|
||||||
|
|
||||||
|
var v = q
|
||||||
|
var yFraction = e
|
||||||
|
if (i and 0x02 != 0) {
|
||||||
|
v++
|
||||||
|
yFraction -= 1.0
|
||||||
|
}
|
||||||
|
|
||||||
|
var w = r
|
||||||
|
var zFraction = f
|
||||||
|
if (i and 0x01 != 0) {
|
||||||
|
w++
|
||||||
|
zFraction -= 1.0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
val d3 = calculateFiddle(seed, u, v, w, xFraction, yFraction, zFraction)
|
val d3 = calculateFiddle(seed, u, v, w, xFraction, yFraction, zFraction)
|
||||||
@ -55,11 +53,20 @@ object FuzzyNoiseBiomeCalculator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val biomeX = checkMask(0x04, p)
|
var biomeX = p
|
||||||
val biomeY = checkMask(0x02, q)
|
if (s and 0x04 != 0) {
|
||||||
val biomeZ = checkMask(0x01, r)
|
biomeX++
|
||||||
|
}
|
||||||
|
var biomeY = q
|
||||||
|
if (s and 0x02 != 0) {
|
||||||
|
biomeY++
|
||||||
|
}
|
||||||
|
var biomeZ = r
|
||||||
|
if (s and 0x01 != 0) {
|
||||||
|
biomeZ++
|
||||||
|
}
|
||||||
|
|
||||||
return world[Vec2i(biomeX shr 2, biomeZ shr 2)]?.biomeSource?.getBiome(Vec3i(biomeX, biomeY, biomeZ))
|
return world[Vec2i(biomeX shr 2, biomeZ shr 2)]?.biomeSource?.getBiome(biomeX, biomeY, biomeZ)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun calculateFiddle(seed: Long, x: Int, y: Int, z: Int, xFraction: Double, yFraction: Double, zFraction: Double): Double {
|
private fun calculateFiddle(seed: Long, x: Int, y: Int, z: Int, xFraction: Double, yFraction: Double, zFraction: Double): Double {
|
||||||
|
@ -18,5 +18,9 @@ import glm_.vec3.Vec3i
|
|||||||
|
|
||||||
interface BiomeSource {
|
interface BiomeSource {
|
||||||
|
|
||||||
fun getBiome(position: Vec3i): Biome?
|
fun getBiome(position: Vec3i): Biome? {
|
||||||
|
return getBiome(position.x, position.y, position.z)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getBiome(x: Int, y: Int, z: Int): Biome?
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,10 @@ import glm_.vec3.Vec3i
|
|||||||
|
|
||||||
class DummyBiomeSource(private val biome: Biome) : BiomeSource {
|
class DummyBiomeSource(private val biome: Biome) : BiomeSource {
|
||||||
|
|
||||||
|
override fun getBiome(x: Int, y: Int, z: Int): Biome? {
|
||||||
|
return biome
|
||||||
|
}
|
||||||
|
|
||||||
override fun getBiome(position: Vec3i): Biome {
|
override fun getBiome(position: Vec3i): Biome {
|
||||||
return biome
|
return biome
|
||||||
}
|
}
|
||||||
|
@ -15,14 +15,13 @@ package de.bixilon.minosoft.data.world.biome.source
|
|||||||
|
|
||||||
import de.bixilon.minosoft.data.registries.biomes.Biome
|
import de.bixilon.minosoft.data.registries.biomes.Biome
|
||||||
import de.bixilon.minosoft.util.MMath
|
import de.bixilon.minosoft.util.MMath
|
||||||
import glm_.vec3.Vec3i
|
|
||||||
|
|
||||||
class SpatialBiomeArray(val data: Array<Biome>) : BiomeSource {
|
class SpatialBiomeArray(val data: Array<Biome>) : BiomeSource {
|
||||||
|
|
||||||
override fun getBiome(position: Vec3i): Biome {
|
override fun getBiome(x: Int, y: Int, z: Int): Biome? {
|
||||||
val index = (MMath.clamp(position.y, 0, Y_BIT_MASK)) shl X_SECTION_COUNT + X_SECTION_COUNT or
|
val index = (MMath.clamp(y, 0, Y_BIT_MASK)) shl X_SECTION_COUNT + X_SECTION_COUNT or
|
||||||
((position.z and X_BIT_MASK) shl X_SECTION_COUNT) or
|
((z and X_BIT_MASK) shl X_SECTION_COUNT) or
|
||||||
(position.x and X_BIT_MASK)
|
(x and X_BIT_MASK)
|
||||||
|
|
||||||
return this.data[index]
|
return this.data[index]
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,6 @@ package de.bixilon.minosoft.data.world.biome.source
|
|||||||
|
|
||||||
import de.bixilon.minosoft.data.registries.biomes.Biome
|
import de.bixilon.minosoft.data.registries.biomes.Biome
|
||||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||||
import glm_.vec3.Vec3i
|
|
||||||
|
|
||||||
class XZBiomeArray(private val biomes: Array<Biome>) : BiomeSource {
|
class XZBiomeArray(private val biomes: Array<Biome>) : BiomeSource {
|
||||||
|
|
||||||
@ -23,7 +22,7 @@ class XZBiomeArray(private val biomes: Array<Biome>) : BiomeSource {
|
|||||||
check(biomes.size == ProtocolDefinition.SECTION_WIDTH_X * ProtocolDefinition.SECTION_WIDTH_Z) { "Biome array size does not match the xz block count!" }
|
check(biomes.size == ProtocolDefinition.SECTION_WIDTH_X * ProtocolDefinition.SECTION_WIDTH_Z) { "Biome array size does not match the xz block count!" }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getBiome(position: Vec3i): Biome {
|
override fun getBiome(x: Int, y: Int, z: Int): Biome {
|
||||||
return biomes[(position.x and 0x0F) or ((position.z and 0x0F) shl 4)]
|
return biomes[(x and 0x0F) or ((z and 0x0F) shl 4)]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,8 @@ open class SectionDataProvider<T>(
|
|||||||
protected val lock = SemaphoreLock() // lock while reading (blocks writing)
|
protected val lock = SemaphoreLock() // lock while reading (blocks writing)
|
||||||
var count: Int = 0
|
var count: Int = 0
|
||||||
private set
|
private set
|
||||||
|
val isEmpty: Boolean
|
||||||
|
get() = count == 0
|
||||||
|
|
||||||
init {
|
init {
|
||||||
recalculateCount()
|
recalculateCount()
|
||||||
|
@ -258,6 +258,14 @@ object VecUtil {
|
|||||||
val Vec3i.center: Vec3d
|
val Vec3i.center: Vec3d
|
||||||
get() = Vec3d(x + 0.5, y + 0.5, z + 0.5)
|
get() = Vec3d(x + 0.5, y + 0.5, z + 0.5)
|
||||||
|
|
||||||
|
fun Vec3i.Companion.of(chunkPosition: Vec2i, sectionHeight: Int): Vec3i {
|
||||||
|
return Vec3i(
|
||||||
|
chunkPosition.x * ProtocolDefinition.SECTION_WIDTH_X,
|
||||||
|
sectionHeight * ProtocolDefinition.SECTION_HEIGHT_Y,
|
||||||
|
chunkPosition.y * ProtocolDefinition.SECTION_WIDTH_Z
|
||||||
|
) // ToDo: Confirm
|
||||||
|
}
|
||||||
|
|
||||||
fun Vec3i.Companion.of(chunkPosition: Vec2i, sectionHeight: Int, inChunkSectionPosition: Vec3i): Vec3i {
|
fun Vec3i.Companion.of(chunkPosition: Vec2i, sectionHeight: Int, inChunkSectionPosition: Vec3i): Vec3i {
|
||||||
return Vec3i(
|
return Vec3i(
|
||||||
chunkPosition.x * ProtocolDefinition.SECTION_WIDTH_X + inChunkSectionPosition.x,
|
chunkPosition.x * ProtocolDefinition.SECTION_WIDTH_X + inChunkSectionPosition.x,
|
||||||
|
@ -25,6 +25,7 @@ import de.bixilon.minosoft.data.text.TextComponent
|
|||||||
import de.bixilon.minosoft.data.text.TextFormattable
|
import de.bixilon.minosoft.data.text.TextFormattable
|
||||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||||
|
import de.bixilon.minosoft.util.collections.SemaphoreMap
|
||||||
import de.bixilon.minosoft.util.collections.SynchronizedMap
|
import de.bixilon.minosoft.util.collections.SynchronizedMap
|
||||||
import de.bixilon.minosoft.util.enum.AliasableEnum
|
import de.bixilon.minosoft.util.enum.AliasableEnum
|
||||||
import de.bixilon.minosoft.util.json.JSONSerializer
|
import de.bixilon.minosoft.util.json.JSONSerializer
|
||||||
@ -104,11 +105,17 @@ object KUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun <K, V> Map<K, V>.toSynchronizedMap(): SynchronizedMap<K, V> {
|
fun <K, V> Map<K, V>.toSynchronizedMap(): SynchronizedMap<K, V> {
|
||||||
return if (this is SynchronizedMap<*, *>) {
|
return if (this is SemaphoreMap<*, *>) {
|
||||||
lock.acquire()
|
lock.acquire()
|
||||||
val map: SynchronizedMap<K, V> = SynchronizedMap(this.toMutableMap()).unsafeCast()
|
val map: SynchronizedMap<K, V> = SynchronizedMap(this.toMutableMap()).unsafeCast()
|
||||||
lock.release()
|
lock.release()
|
||||||
map
|
map
|
||||||
|
} else if (this is SynchronizedMap<*, *>) {
|
||||||
|
val map: SynchronizedMap<K, V>
|
||||||
|
synchronized(this.lock) {
|
||||||
|
map = SynchronizedMap(this.toMutableMap()).unsafeCast()
|
||||||
|
}
|
||||||
|
map
|
||||||
} else {
|
} else {
|
||||||
synchronizedCopy { SynchronizedMap(this.toMutableMap()) }
|
synchronizedCopy { SynchronizedMap(this.toMutableMap()) }
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,223 @@
|
|||||||
|
/*
|
||||||
|
* Minosoft
|
||||||
|
* Copyright (C) 2021 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.bixilon.minosoft.util.collections
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.util.KUtil.toSynchronizedList
|
||||||
|
import de.bixilon.minosoft.util.KUtil.toSynchronizedSet
|
||||||
|
import de.bixilon.minosoft.util.SemaphoreLock
|
||||||
|
import java.util.function.BiConsumer
|
||||||
|
import java.util.function.BiFunction
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SemaphoreMap<K, V>(
|
||||||
|
private val original: MutableMap<K, V>,
|
||||||
|
) : MutableMap<K, V> {
|
||||||
|
val lock = SemaphoreLock()
|
||||||
|
override val size: Int
|
||||||
|
get() {
|
||||||
|
lock.acquire()
|
||||||
|
val returnValue = original.size
|
||||||
|
lock.release()
|
||||||
|
return returnValue
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun containsKey(key: K): Boolean {
|
||||||
|
lock.acquire()
|
||||||
|
val returnValue = original.containsKey(key)
|
||||||
|
lock.release()
|
||||||
|
return returnValue
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun containsValue(value: V): Boolean {
|
||||||
|
lock.acquire()
|
||||||
|
val returnValue = original.containsValue(value)
|
||||||
|
lock.release()
|
||||||
|
return returnValue
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun get(key: K): V? {
|
||||||
|
lock.acquire()
|
||||||
|
val returnValue = original[key]
|
||||||
|
lock.release()
|
||||||
|
return returnValue
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isEmpty(): Boolean {
|
||||||
|
lock.acquire()
|
||||||
|
val returnValue = original.isEmpty()
|
||||||
|
lock.release()
|
||||||
|
return returnValue
|
||||||
|
}
|
||||||
|
|
||||||
|
override val entries: MutableSet<MutableMap.MutableEntry<K, V>>
|
||||||
|
get() {
|
||||||
|
lock.acquire()
|
||||||
|
val returnValue = original.entries.toSynchronizedSet()
|
||||||
|
lock.release()
|
||||||
|
return returnValue
|
||||||
|
}
|
||||||
|
override val keys: MutableSet<K>
|
||||||
|
get() {
|
||||||
|
lock.acquire()
|
||||||
|
val returnValue = original.keys.toSynchronizedSet()
|
||||||
|
lock.release()
|
||||||
|
return returnValue
|
||||||
|
}
|
||||||
|
override val values: MutableCollection<V>
|
||||||
|
get() {
|
||||||
|
lock.acquire()
|
||||||
|
val returnValue = original.values.toSynchronizedList()
|
||||||
|
lock.release()
|
||||||
|
return returnValue
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun clear() {
|
||||||
|
lock.lock()
|
||||||
|
original.clear()
|
||||||
|
lock.unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun put(key: K, value: V): V? {
|
||||||
|
lock.lock()
|
||||||
|
val returnValue = original.put(key, value)
|
||||||
|
lock.unlock()
|
||||||
|
return returnValue
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun putAll(from: Map<out K, V>) {
|
||||||
|
lock.lock()
|
||||||
|
val returnValue = original.putAll(from)
|
||||||
|
lock.unlock()
|
||||||
|
return returnValue
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun remove(key: K): V? {
|
||||||
|
lock.lock()
|
||||||
|
val returnValue = original.remove(key)
|
||||||
|
lock.unlock()
|
||||||
|
return returnValue
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
lock.acquire()
|
||||||
|
val returnValue = original.hashCode()
|
||||||
|
lock.release()
|
||||||
|
return returnValue
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
lock.acquire()
|
||||||
|
val returnValue = original.toString()
|
||||||
|
lock.release()
|
||||||
|
return returnValue
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun putIfAbsent(key: K, value: V): V? {
|
||||||
|
lock.lock()
|
||||||
|
val returnValue = original.putIfAbsent(key, value)
|
||||||
|
lock.unlock()
|
||||||
|
return returnValue
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun forEach(action: BiConsumer<in K, in V>) {
|
||||||
|
lock.acquire()
|
||||||
|
val returnValue = original.forEach(action)
|
||||||
|
lock.release()
|
||||||
|
return returnValue
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getOrDefault(key: K, defaultValue: V): V {
|
||||||
|
lock.acquire()
|
||||||
|
val returnValue = original.getOrDefault(key, defaultValue)
|
||||||
|
lock.release()
|
||||||
|
return returnValue
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getOrPut(key: K, defaultValue: () -> V): V {
|
||||||
|
lock.lock()
|
||||||
|
var value = original[key]
|
||||||
|
val returnValue = if (value == null) {
|
||||||
|
value = defaultValue()
|
||||||
|
original[key] = value
|
||||||
|
value
|
||||||
|
} else {
|
||||||
|
value
|
||||||
|
}
|
||||||
|
lock.unlock()
|
||||||
|
return returnValue
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun remove(key: K, value: V): Boolean {
|
||||||
|
lock.lock()
|
||||||
|
val returnValue = original.remove(key, value)
|
||||||
|
lock.unlock()
|
||||||
|
return returnValue
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
lock.acquire()
|
||||||
|
val returnValue = original == other
|
||||||
|
lock.release()
|
||||||
|
return returnValue
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun replaceAll(function: BiFunction<in K, in V, out V>) {
|
||||||
|
lock.lock()
|
||||||
|
val returnValue = original.replaceAll(function)
|
||||||
|
lock.unlock()
|
||||||
|
return returnValue
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun compute(key: K, remappingFunction: BiFunction<in K, in V?, out V?>): V? {
|
||||||
|
lock.acquire()
|
||||||
|
val returnValue = original.compute(key, remappingFunction)
|
||||||
|
lock.release()
|
||||||
|
return returnValue
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun computeIfAbsent(key: K, mappingFunction: Function<in K, out V>): V {
|
||||||
|
lock.acquire()
|
||||||
|
val returnValue = original.computeIfAbsent(key, mappingFunction)
|
||||||
|
lock.release()
|
||||||
|
return returnValue
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun computeIfPresent(key: K, remappingFunction: BiFunction<in K, in V, out V?>): V? {
|
||||||
|
lock.acquire()
|
||||||
|
val returnValue = original.computeIfPresent(key, remappingFunction)
|
||||||
|
lock.release()
|
||||||
|
return returnValue
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun replace(key: K, value: V): V? {
|
||||||
|
lock.lock()
|
||||||
|
val returnValue = original.replace(key, value)
|
||||||
|
lock.unlock()
|
||||||
|
return returnValue
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun merge(key: K, value: V, remappingFunction: BiFunction<in V, in V, out V?>): V? {
|
||||||
|
lock.lock()
|
||||||
|
val returnValue = original.merge(key, value, remappingFunction)
|
||||||
|
lock.unlock()
|
||||||
|
return returnValue
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun replace(key: K, oldValue: V, newValue: V): Boolean {
|
||||||
|
lock.lock()
|
||||||
|
val returnValue = original.replace(key, oldValue, newValue)
|
||||||
|
lock.unlock()
|
||||||
|
return returnValue
|
||||||
|
}
|
||||||
|
}
|
@ -15,7 +15,6 @@ package de.bixilon.minosoft.util.collections
|
|||||||
|
|
||||||
import de.bixilon.minosoft.util.KUtil.toSynchronizedList
|
import de.bixilon.minosoft.util.KUtil.toSynchronizedList
|
||||||
import de.bixilon.minosoft.util.KUtil.toSynchronizedSet
|
import de.bixilon.minosoft.util.KUtil.toSynchronizedSet
|
||||||
import de.bixilon.minosoft.util.SemaphoreLock
|
|
||||||
import java.util.function.BiConsumer
|
import java.util.function.BiConsumer
|
||||||
import java.util.function.BiFunction
|
import java.util.function.BiFunction
|
||||||
import java.util.function.Function
|
import java.util.function.Function
|
||||||
@ -23,201 +22,171 @@ import java.util.function.Function
|
|||||||
class SynchronizedMap<K, V>(
|
class SynchronizedMap<K, V>(
|
||||||
private val original: MutableMap<K, V>,
|
private val original: MutableMap<K, V>,
|
||||||
) : MutableMap<K, V> {
|
) : MutableMap<K, V> {
|
||||||
internal val lock = SemaphoreLock()
|
internal val lock = Object()
|
||||||
override val size: Int
|
override val size: Int
|
||||||
get() {
|
get() = synchronized(lock) { original.size }
|
||||||
lock.acquire()
|
|
||||||
val returnValue = original.size
|
|
||||||
lock.release()
|
|
||||||
return returnValue
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun containsKey(key: K): Boolean {
|
override fun containsKey(key: K): Boolean {
|
||||||
lock.acquire()
|
synchronized(lock) {
|
||||||
val returnValue = original.containsKey(key)
|
return original.containsKey(key)
|
||||||
lock.release()
|
}
|
||||||
return returnValue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun containsValue(value: V): Boolean {
|
override fun containsValue(value: V): Boolean {
|
||||||
lock.acquire()
|
synchronized(lock) {
|
||||||
val returnValue = original.containsValue(value)
|
return original.containsValue(value)
|
||||||
lock.release()
|
}
|
||||||
return returnValue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun get(key: K): V? {
|
override fun get(key: K): V? {
|
||||||
lock.acquire()
|
synchronized(lock) {
|
||||||
val returnValue = original[key]
|
return original[key]
|
||||||
lock.release()
|
}
|
||||||
return returnValue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isEmpty(): Boolean {
|
override fun isEmpty(): Boolean {
|
||||||
lock.acquire()
|
synchronized(lock) {
|
||||||
val returnValue = original.isEmpty()
|
return original.isEmpty()
|
||||||
lock.release()
|
}
|
||||||
return returnValue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override val entries: MutableSet<MutableMap.MutableEntry<K, V>>
|
override val entries: MutableSet<MutableMap.MutableEntry<K, V>>
|
||||||
get() {
|
get() {
|
||||||
lock.acquire()
|
synchronized(lock) {
|
||||||
val returnValue = original.entries.toSynchronizedSet()
|
return original.entries.toSynchronizedSet()
|
||||||
lock.release()
|
}
|
||||||
return returnValue
|
|
||||||
}
|
}
|
||||||
override val keys: MutableSet<K>
|
override val keys: MutableSet<K>
|
||||||
get() {
|
get() {
|
||||||
lock.acquire()
|
synchronized(lock) {
|
||||||
val returnValue = original.keys.toSynchronizedSet()
|
return original.keys.toSynchronizedSet()
|
||||||
lock.release()
|
}
|
||||||
return returnValue
|
|
||||||
}
|
}
|
||||||
override val values: MutableCollection<V>
|
override val values: MutableCollection<V>
|
||||||
get() {
|
get() {
|
||||||
lock.acquire()
|
synchronized(lock) {
|
||||||
val returnValue = original.values.toSynchronizedList()
|
return original.values.toSynchronizedList()
|
||||||
lock.release()
|
}
|
||||||
return returnValue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun clear() {
|
override fun clear() {
|
||||||
lock.lock()
|
synchronized(lock) {
|
||||||
original.clear()
|
original.clear()
|
||||||
lock.unlock()
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun put(key: K, value: V): V? {
|
override fun put(key: K, value: V): V? {
|
||||||
lock.lock()
|
synchronized(lock) {
|
||||||
val returnValue = original.put(key, value)
|
return original.put(key, value)
|
||||||
lock.unlock()
|
}
|
||||||
return returnValue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun putAll(from: Map<out K, V>) {
|
override fun putAll(from: Map<out K, V>) {
|
||||||
lock.lock()
|
synchronized(lock) {
|
||||||
val returnValue = original.putAll(from)
|
return original.putAll(from)
|
||||||
lock.unlock()
|
}
|
||||||
return returnValue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun remove(key: K): V? {
|
override fun remove(key: K): V? {
|
||||||
lock.lock()
|
synchronized(lock) {
|
||||||
val returnValue = original.remove(key)
|
return original.remove(key)
|
||||||
lock.unlock()
|
}
|
||||||
return returnValue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
override fun hashCode(): Int {
|
||||||
lock.acquire()
|
synchronized(lock) {
|
||||||
val returnValue = original.hashCode()
|
return original.hashCode()
|
||||||
lock.release()
|
}
|
||||||
return returnValue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
lock.acquire()
|
synchronized(lock) {
|
||||||
val returnValue = original.toString()
|
return original.toString()
|
||||||
lock.release()
|
}
|
||||||
return returnValue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun putIfAbsent(key: K, value: V): V? {
|
override fun putIfAbsent(key: K, value: V): V? {
|
||||||
lock.lock()
|
synchronized(lock) {
|
||||||
val returnValue = original.putIfAbsent(key, value)
|
return original.putIfAbsent(key, value)
|
||||||
lock.unlock()
|
}
|
||||||
return returnValue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun forEach(action: BiConsumer<in K, in V>) {
|
override fun forEach(action: BiConsumer<in K, in V>) {
|
||||||
lock.acquire()
|
synchronized(lock) {
|
||||||
val returnValue = original.forEach(action)
|
return original.forEach(action)
|
||||||
lock.release()
|
}
|
||||||
return returnValue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getOrDefault(key: K, defaultValue: V): V {
|
override fun getOrDefault(key: K, defaultValue: V): V {
|
||||||
lock.acquire()
|
synchronized(lock) {
|
||||||
val returnValue = original.getOrDefault(key, defaultValue)
|
return original.getOrDefault(key, defaultValue)
|
||||||
lock.release()
|
}
|
||||||
return returnValue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getOrPut(key: K, defaultValue: () -> V): V {
|
fun getOrPut(key: K, defaultValue: () -> V): V {
|
||||||
lock.lock()
|
synchronized(lock) {
|
||||||
var value = original[key]
|
var value = get(key)
|
||||||
val returnValue = if (value == null) {
|
return if (value == null) {
|
||||||
value = defaultValue()
|
value = defaultValue()
|
||||||
original[key] = value
|
put(key, value)
|
||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
value
|
value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
lock.unlock()
|
|
||||||
return returnValue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun remove(key: K, value: V): Boolean {
|
override fun remove(key: K, value: V): Boolean {
|
||||||
lock.lock()
|
synchronized(lock) {
|
||||||
val returnValue = original.remove(key, value)
|
return original.remove(key, value)
|
||||||
lock.unlock()
|
}
|
||||||
return returnValue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
lock.acquire()
|
synchronized(lock) {
|
||||||
val returnValue = original == other
|
return original == other
|
||||||
lock.release()
|
}
|
||||||
return returnValue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun replaceAll(function: BiFunction<in K, in V, out V>) {
|
override fun replaceAll(function: BiFunction<in K, in V, out V>) {
|
||||||
lock.lock()
|
synchronized(lock) {
|
||||||
val returnValue = original.replaceAll(function)
|
return original.replaceAll(function)
|
||||||
lock.unlock()
|
}
|
||||||
return returnValue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun compute(key: K, remappingFunction: BiFunction<in K, in V?, out V?>): V? {
|
override fun compute(key: K, remappingFunction: BiFunction<in K, in V?, out V?>): V? {
|
||||||
lock.acquire()
|
synchronized(lock) {
|
||||||
val returnValue = original.compute(key, remappingFunction)
|
return original.compute(key, remappingFunction)
|
||||||
lock.release()
|
}
|
||||||
return returnValue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun computeIfAbsent(key: K, mappingFunction: Function<in K, out V>): V {
|
override fun computeIfAbsent(key: K, mappingFunction: Function<in K, out V>): V {
|
||||||
lock.acquire()
|
synchronized(lock) {
|
||||||
val returnValue = original.computeIfAbsent(key, mappingFunction)
|
return original.computeIfAbsent(key, mappingFunction)
|
||||||
lock.release()
|
}
|
||||||
return returnValue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun computeIfPresent(key: K, remappingFunction: BiFunction<in K, in V, out V?>): V? {
|
override fun computeIfPresent(key: K, remappingFunction: BiFunction<in K, in V, out V?>): V? {
|
||||||
lock.acquire()
|
synchronized(lock) {
|
||||||
val returnValue = original.computeIfPresent(key, remappingFunction)
|
return original.computeIfPresent(key, remappingFunction)
|
||||||
lock.release()
|
}
|
||||||
return returnValue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun replace(key: K, value: V): V? {
|
override fun replace(key: K, value: V): V? {
|
||||||
lock.lock()
|
synchronized(lock) {
|
||||||
val returnValue = original.replace(key, value)
|
return original.replace(key, value)
|
||||||
lock.unlock()
|
}
|
||||||
return returnValue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun merge(key: K, value: V, remappingFunction: BiFunction<in V, in V, out V?>): V? {
|
override fun merge(key: K, value: V, remappingFunction: BiFunction<in V, in V, out V?>): V? {
|
||||||
lock.lock()
|
synchronized(lock) {
|
||||||
val returnValue = original.merge(key, value, remappingFunction)
|
return original.merge(key, value, remappingFunction)
|
||||||
lock.unlock()
|
}
|
||||||
return returnValue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun replace(key: K, oldValue: V, newValue: V): Boolean {
|
override fun replace(key: K, oldValue: V, newValue: V): Boolean {
|
||||||
lock.lock()
|
synchronized(lock) {
|
||||||
val returnValue = original.replace(key, oldValue, newValue)
|
return original.replace(key, oldValue, newValue)
|
||||||
lock.unlock()
|
}
|
||||||
return returnValue
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user