diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/AbstractEnormousPlacement.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/AbstractEnormousPlacement.kt index 56852daf5..85e69d149 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/AbstractEnormousPlacement.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/AbstractEnormousPlacement.kt @@ -1,5 +1,6 @@ package ru.dbotthepony.mc.otm.worldgen.placement +import com.github.benmanes.caffeine.cache.Cache import com.github.benmanes.caffeine.cache.Caffeine import com.github.benmanes.caffeine.cache.Scheduler import com.mojang.serialization.Codec @@ -11,6 +12,8 @@ import net.minecraft.core.BlockPos import net.minecraft.core.SectionPos import net.minecraft.util.RandomSource import net.minecraft.world.level.ChunkPos +import net.minecraft.world.level.Level +import net.minecraft.world.level.WorldGenLevel import net.minecraft.world.level.levelgen.placement.PlacementContext import net.minecraft.world.level.levelgen.placement.PlacementModifier import ru.dbotthepony.kommons.util.XXHash64 @@ -19,7 +22,11 @@ import ru.dbotthepony.mc.otm.data.codec.minRange import ru.dbotthepony.mc.otm.worldgen.placement.AbstractEnormousPlacement.Parameters import java.io.DataOutputStream import java.time.Duration +import java.util.Collections +import java.util.WeakHashMap +import java.util.concurrent.locks.ReentrantLock import java.util.stream.Stream +import kotlin.concurrent.withLock import kotlin.math.sqrt /** @@ -73,13 +80,22 @@ abstract class AbstractEnormousPlacement(val parameters: Parameters) : Placement protected abstract fun getPositions(center: BlockPos, random: RandomSource): Stream - private val chunkCache = Caffeine.newBuilder() - .scheduler(Scheduler.systemScheduler()) - .executor(Util.backgroundExecutor()) - .maximumSize(16384L) - .expireAfterWrite(Duration.ofMinutes(5)) - .softValues() - .build() + private val level2cache = WeakHashMap>() + private val lock = ReentrantLock() + + private fun getCache(level: WorldGenLevel): Cache { + return lock.withLock { + level2cache.computeIfAbsent(level) { + Caffeine.newBuilder() + .scheduler(Scheduler.systemScheduler()) + .executor(Util.backgroundExecutor()) + .maximumSize(16384L) + .expireAfterWrite(Duration.ofMinutes(5)) + .softValues() + .build() + } + } + } private fun computeChunk(context: PlacementContext, pos: ChunkPos): GeneratedChunk { val bytes = FastByteArrayOutputStream() @@ -113,7 +129,7 @@ abstract class AbstractEnormousPlacement(val parameters: Parameters) : Placement if (radius <= parameters.chunkScanRange) { val thisPos = ChunkPos(cPos.x + x, cPos.z + z) - instances.add(chunkCache.get(thisPos) { computeChunk(context, thisPos) }) + instances.add(getCache(context.level).get(thisPos) { computeChunk(context, thisPos) }) } } }