Remove enormous placement
This commit is contained in:
parent
1acd105925
commit
1e6e38ea7d
@ -37,7 +37,6 @@ import ru.dbotthepony.mc.otm.worldgen.feature.BlackHolePlacerFeature
|
|||||||
import ru.dbotthepony.mc.otm.worldgen.feature.DebugPlacerFeature
|
import ru.dbotthepony.mc.otm.worldgen.feature.DebugPlacerFeature
|
||||||
import ru.dbotthepony.mc.otm.worldgen.feature.EnhancedFeature
|
import ru.dbotthepony.mc.otm.worldgen.feature.EnhancedFeature
|
||||||
import ru.dbotthepony.mc.otm.worldgen.placement.ChainPlacement
|
import ru.dbotthepony.mc.otm.worldgen.placement.ChainPlacement
|
||||||
import ru.dbotthepony.mc.otm.worldgen.placement.EnormousPlacement
|
|
||||||
import ru.dbotthepony.mc.otm.worldgen.placement.EllipsoidPlacement
|
import ru.dbotthepony.mc.otm.worldgen.placement.EllipsoidPlacement
|
||||||
import ru.dbotthepony.mc.otm.worldgen.placement.SplitPlacement
|
import ru.dbotthepony.mc.otm.worldgen.placement.SplitPlacement
|
||||||
import ru.dbotthepony.mc.otm.worldgen.placement.WormPlacement
|
import ru.dbotthepony.mc.otm.worldgen.placement.WormPlacement
|
||||||
|
@ -6,7 +6,6 @@ import net.neoforged.bus.api.IEventBus
|
|||||||
import ru.dbotthepony.mc.otm.registry.MDeferredRegister
|
import ru.dbotthepony.mc.otm.registry.MDeferredRegister
|
||||||
import ru.dbotthepony.mc.otm.worldgen.placement.ChainPlacement
|
import ru.dbotthepony.mc.otm.worldgen.placement.ChainPlacement
|
||||||
import ru.dbotthepony.mc.otm.worldgen.placement.EllipsoidPlacement
|
import ru.dbotthepony.mc.otm.worldgen.placement.EllipsoidPlacement
|
||||||
import ru.dbotthepony.mc.otm.worldgen.placement.EnormousPlacement
|
|
||||||
import ru.dbotthepony.mc.otm.worldgen.placement.SplitPlacement
|
import ru.dbotthepony.mc.otm.worldgen.placement.SplitPlacement
|
||||||
import ru.dbotthepony.mc.otm.worldgen.placement.WormPlacement
|
import ru.dbotthepony.mc.otm.worldgen.placement.WormPlacement
|
||||||
|
|
||||||
@ -17,7 +16,6 @@ object MPlacementModifiers {
|
|||||||
registry.register(bus)
|
registry.register(bus)
|
||||||
}
|
}
|
||||||
|
|
||||||
val ENORMOUS by registry.register("enormous") { PlacementModifierType { EnormousPlacement.CODEC } }
|
|
||||||
val ELLIPSOID_PLACEMENT by registry.register("ellipsoid") { PlacementModifierType { EllipsoidPlacement.CODEC } }
|
val ELLIPSOID_PLACEMENT by registry.register("ellipsoid") { PlacementModifierType { EllipsoidPlacement.CODEC } }
|
||||||
val WORM_PLACEMENT by registry.register("worm") { PlacementModifierType { WormPlacement.CODEC } }
|
val WORM_PLACEMENT by registry.register("worm") { PlacementModifierType { WormPlacement.CODEC } }
|
||||||
val SPLIT by registry.register("split") { PlacementModifierType { SplitPlacement.CODEC} }
|
val SPLIT by registry.register("split") { PlacementModifierType { SplitPlacement.CODEC} }
|
||||||
|
@ -1,136 +0,0 @@
|
|||||||
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
|
|
||||||
import com.mojang.serialization.MapCodec
|
|
||||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
|
||||||
import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream
|
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet
|
|
||||||
import net.minecraft.Util
|
|
||||||
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.WorldGenLevel
|
|
||||||
import net.minecraft.world.level.levelgen.placement.PlacementContext
|
|
||||||
import net.minecraft.world.level.levelgen.placement.PlacementModifier
|
|
||||||
import net.minecraft.world.level.levelgen.placement.PlacementModifierType
|
|
||||||
import ru.dbotthepony.kommons.util.XXHash64
|
|
||||||
import ru.dbotthepony.mc.otm.core.util.GJRAND64RandomSource
|
|
||||||
import ru.dbotthepony.mc.otm.data.codec.minRange
|
|
||||||
import ru.dbotthepony.mc.otm.registry.data.MPlacementModifiers
|
|
||||||
import java.io.DataOutputStream
|
|
||||||
import java.time.Duration
|
|
||||||
import java.util.stream.Stream
|
|
||||||
import kotlin.math.sqrt
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enormous placement base, which allows it to span over several chunks without issues.
|
|
||||||
*
|
|
||||||
* This modifier is designed to be the only "top-level" placement modifier,
|
|
||||||
* and all logic regarding actual placements embedded in [children]
|
|
||||||
*/
|
|
||||||
class EnormousPlacement(
|
|
||||||
/**
|
|
||||||
* How many chunks away to look for actual placements
|
|
||||||
*
|
|
||||||
* Too small value will cause placement cutoffs
|
|
||||||
*/
|
|
||||||
val chunkScanRange: Int,
|
|
||||||
val seedMix: Long,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Baseline placement modifiers, dictating how to appear in chunk
|
|
||||||
*/
|
|
||||||
val children: List<PlacementModifier>,
|
|
||||||
) : PlacementModifier() {
|
|
||||||
private class GeneratedChunk(positions: Stream<BlockPos>) {
|
|
||||||
// TODO: memory inefficient
|
|
||||||
private val positions = ObjectOpenHashSet<BlockPos>()
|
|
||||||
|
|
||||||
init {
|
|
||||||
positions.forEach { this.positions.add(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: this is primitive implementation, need to implement better one
|
|
||||||
fun getPositions(pos: ChunkPos): Stream<BlockPos> {
|
|
||||||
return positions.stream().filter {
|
|
||||||
SectionPos.blockToSectionCoord(it.x) == pos.x &&
|
|
||||||
SectionPos.blockToSectionCoord(it.z) == pos.z
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val level2cache = Caffeine.newBuilder()
|
|
||||||
.scheduler(Scheduler.systemScheduler())
|
|
||||||
.executor(Util.backgroundExecutor())
|
|
||||||
.expireAfterAccess(Duration.ofMinutes(10))
|
|
||||||
.weakKeys()
|
|
||||||
.build<WorldGenLevel, Cache<ChunkPos, GeneratedChunk>>()
|
|
||||||
|
|
||||||
private fun getCache(level: WorldGenLevel): Cache<ChunkPos, GeneratedChunk> {
|
|
||||||
return level2cache.get(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()
|
|
||||||
val dataStream = DataOutputStream(bytes)
|
|
||||||
|
|
||||||
dataStream.writeLong(seedMix)
|
|
||||||
dataStream.writeInt(pos.x)
|
|
||||||
dataStream.writeInt(pos.z)
|
|
||||||
|
|
||||||
val hash = XXHash64()
|
|
||||||
hash.update(bytes.array, 0, bytes.length)
|
|
||||||
|
|
||||||
val random = GJRAND64RandomSource(context.level.seed, hash.digestAsLong())
|
|
||||||
var stream = Stream.of(BlockPos(pos.minBlockX, 0, pos.minBlockZ))
|
|
||||||
children.forEach { modifier -> stream = stream.flatMap { modifier.getPositions(context, random, it).sequential() } }
|
|
||||||
return GeneratedChunk(stream)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getPositions(context: PlacementContext, random: RandomSource, pos: BlockPos): Stream<BlockPos> {
|
|
||||||
val cache = getCache(context.level)
|
|
||||||
val cPos = ChunkPos(pos)
|
|
||||||
val instances = ArrayList<GeneratedChunk>()
|
|
||||||
|
|
||||||
for (x in -chunkScanRange .. chunkScanRange) {
|
|
||||||
for (z in -chunkScanRange .. chunkScanRange) {
|
|
||||||
// floor, so chunk scan range of 1 will give square instead of diamond
|
|
||||||
val radius = sqrt(x.toDouble() * x + z.toDouble() * z).toInt()
|
|
||||||
|
|
||||||
if (radius <= chunkScanRange) {
|
|
||||||
val thisPos = ChunkPos(cPos.x + x, cPos.z + z)
|
|
||||||
|
|
||||||
instances.add(cache.get(thisPos) { computeChunk(context, thisPos) })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return instances.stream().flatMap { it.getPositions(cPos) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun type(): PlacementModifierType<*> {
|
|
||||||
return MPlacementModifiers.ENORMOUS
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
val CODEC: MapCodec<EnormousPlacement> = RecordCodecBuilder.mapCodec {
|
|
||||||
it.group(
|
|
||||||
Codec.INT.minRange(0).fieldOf("chunk_scan_range").forGetter(EnormousPlacement::chunkScanRange),
|
|
||||||
Codec.LONG.fieldOf("seed_mix").forGetter(EnormousPlacement::seedMix),
|
|
||||||
PlacementModifier.CODEC.listOf().optionalFieldOf("children", listOf()).forGetter(EnormousPlacement::children),
|
|
||||||
).apply(it, ::EnormousPlacement)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user