Make enormous placement a wrapper around regular placement modifiers, simplifying code
This commit is contained in:
parent
7736762c86
commit
674c875249
@ -8,7 +8,6 @@ import net.minecraft.tags.BiomeTags
|
||||
import net.minecraft.tags.BlockTags
|
||||
import net.minecraft.util.valueproviders.ClampedNormalFloat
|
||||
import net.minecraft.util.valueproviders.ConstantFloat
|
||||
import net.minecraft.util.valueproviders.ConstantInt
|
||||
import net.minecraft.util.valueproviders.UniformFloat
|
||||
import net.minecraft.util.valueproviders.UniformInt
|
||||
import net.minecraft.world.level.levelgen.GenerationStep
|
||||
@ -33,10 +32,8 @@ import ru.dbotthepony.mc.otm.worldgen.placement.StandardDeviationHeightProvider
|
||||
import ru.dbotthepony.mc.otm.registry.game.MBlocks
|
||||
import ru.dbotthepony.mc.otm.registry.data.MWorldGenFeatures
|
||||
import ru.dbotthepony.mc.otm.worldgen.feature.BlackHolePlacerFeature
|
||||
import ru.dbotthepony.mc.otm.worldgen.feature.DebugPlacerFeature
|
||||
import ru.dbotthepony.mc.otm.worldgen.placement.AbstractEnormousPlacement
|
||||
import ru.dbotthepony.mc.otm.worldgen.placement.EnormousPlacement
|
||||
import ru.dbotthepony.mc.otm.worldgen.placement.EllipsoidPlacement
|
||||
import ru.dbotthepony.mc.otm.worldgen.placement.EnormousEllipsoidPlacement
|
||||
import ru.dbotthepony.mc.otm.worldgen.placement.WormPlacement
|
||||
|
||||
private object ConfiguredFeatures {
|
||||
@ -118,36 +115,34 @@ fun registerPlacedFeatures(context: BootstrapContext<PlacedFeature>) {
|
||||
context.register(PlacedFeatures.WORM_TRITANIUM, PlacedFeature(
|
||||
configured.getOrThrow(ConfiguredFeatures.TRITANIUM_ORE_SMALL),
|
||||
listOf(
|
||||
WormPlacement(
|
||||
parameters = AbstractEnormousPlacement.Parameters(
|
||||
chunkScanRange = 24,
|
||||
seedMix = 9284343575495L,
|
||||
prePlacementModifiers = listOf(
|
||||
RarityFilter.onAverageOnceEvery(300),
|
||||
InSquarePlacement.spread(),
|
||||
HeightRangePlacement.of(StandardDeviationHeightProvider(VerticalAnchor.absolute(-40), 15.0)),
|
||||
EnormousPlacement(
|
||||
chunkScanRange = 24,
|
||||
seedMix = 9284343575495L,
|
||||
children = listOf(
|
||||
RarityFilter.onAverageOnceEvery(300),
|
||||
InSquarePlacement.spread(),
|
||||
HeightRangePlacement.of(StandardDeviationHeightProvider(VerticalAnchor.absolute(-40), 15.0)),
|
||||
WormPlacement(
|
||||
length = UniformInt.of(120, 400),
|
||||
turnRateXY = WormPlacement.normalDistributedTurnRate(10f),
|
||||
turnRateXZ = WormPlacement.normalDistributedTurnRate(60f),
|
||||
turnSpeedXZ = WormPlacement.constantTurnRate(10f),
|
||||
turnSpeedXY = WormPlacement.constantTurnRate(4f),
|
||||
turnChanceXY = BooleanProvider.Unbiased(6),
|
||||
turnChanceXZ = BooleanProvider.BiasedLinear(0.6f, 5),
|
||||
maxTravelUp = 16,
|
||||
maxTravelDown = 16,
|
||||
),
|
||||
postPlacementModifiers = listOf(
|
||||
EllipsoidPlacement(
|
||||
count = UniformInt.of(15, 30),
|
||||
xLength = ConstantFloat.of(14f),
|
||||
yLength = ConstantFloat.of(14f),
|
||||
zLength = ConstantFloat.of(14f),
|
||||
x = ClampedNormalFloat.of(0f, 0.4f, -1f, 1f),
|
||||
y = ClampedNormalFloat.of(0f, 0.4f, -1f, 1f),
|
||||
z = ClampedNormalFloat.of(0f, 0.4f, -1f, 1f),
|
||||
)
|
||||
EllipsoidPlacement(
|
||||
count = UniformInt.of(15, 30),
|
||||
xLength = ConstantFloat.of(14f),
|
||||
yLength = ConstantFloat.of(14f),
|
||||
zLength = ConstantFloat.of(14f),
|
||||
x = ClampedNormalFloat.of(0f, 0.4f, -1f, 1f),
|
||||
y = ClampedNormalFloat.of(0f, 0.4f, -1f, 1f),
|
||||
z = ClampedNormalFloat.of(0f, 0.4f, -1f, 1f),
|
||||
)
|
||||
),
|
||||
length = UniformInt.of(120, 400),
|
||||
turnRateXY = WormPlacement.normalDistributedTurnRate(10f),
|
||||
turnRateXZ = WormPlacement.normalDistributedTurnRate(60f),
|
||||
turnSpeedXZ = WormPlacement.constantTurnRate(10f),
|
||||
turnSpeedXY = WormPlacement.constantTurnRate(4f),
|
||||
turnChanceXY = BooleanProvider.Unbiased(6),
|
||||
turnChanceXZ = BooleanProvider.BiasedLinear(0.6f, 5),
|
||||
maxTravelUp = 16,
|
||||
maxTravelDown = 16,
|
||||
)
|
||||
)
|
||||
)
|
||||
))
|
||||
@ -164,23 +159,23 @@ fun registerPlacedFeatures(context: BootstrapContext<PlacedFeature>) {
|
||||
context.register(PlacedFeatures.DILITHIUM, PlacedFeature(
|
||||
ore,
|
||||
listOf(
|
||||
EnormousEllipsoidPlacement(
|
||||
parameters = AbstractEnormousPlacement.Parameters(
|
||||
chunkScanRange = 5,
|
||||
seedMix = 237483209523709234L,
|
||||
prePlacementModifiers = listOf(
|
||||
RarityFilter.onAverageOnceEvery(120),
|
||||
InSquarePlacement.spread(),
|
||||
HeightRangePlacement.of(StandardDeviationHeightProvider(VerticalAnchor.absolute(0), 15.0)),
|
||||
),
|
||||
EnormousPlacement(
|
||||
chunkScanRange = 6,
|
||||
seedMix = 237483209523709234L,
|
||||
children = listOf(
|
||||
RarityFilter.onAverageOnceEvery(120),
|
||||
InSquarePlacement.spread(),
|
||||
HeightRangePlacement.of(StandardDeviationHeightProvider(VerticalAnchor.absolute(0), 15.0)),
|
||||
EllipsoidPlacement(
|
||||
x = ringularity,
|
||||
y = ringularity,
|
||||
z = ringularity,
|
||||
count = UniformInt.of(8000, 16000),
|
||||
xLength = UniformFloat.of(30f, 70f),
|
||||
yLength = UniformFloat.of(40f, 90f),
|
||||
zLength = UniformFloat.of(30f, 70f),
|
||||
)
|
||||
),
|
||||
x = ringularity,
|
||||
y = ringularity,
|
||||
z = ringularity,
|
||||
count = UniformInt.of(8000, 16000),
|
||||
xLength = UniformFloat.of(30f, 70f),
|
||||
yLength = UniformFloat.of(40f, 90f),
|
||||
zLength = UniformFloat.of(30f, 70f),
|
||||
)
|
||||
)
|
||||
))
|
||||
|
@ -5,7 +5,7 @@ import net.minecraft.world.level.levelgen.placement.PlacementModifierType
|
||||
import net.neoforged.bus.api.IEventBus
|
||||
import ru.dbotthepony.mc.otm.registry.MDeferredRegister
|
||||
import ru.dbotthepony.mc.otm.worldgen.placement.EllipsoidPlacement
|
||||
import ru.dbotthepony.mc.otm.worldgen.placement.EnormousEllipsoidPlacement
|
||||
import ru.dbotthepony.mc.otm.worldgen.placement.EnormousPlacement
|
||||
import ru.dbotthepony.mc.otm.worldgen.placement.WormPlacement
|
||||
|
||||
object MPlacementModifiers {
|
||||
@ -15,7 +15,7 @@ object MPlacementModifiers {
|
||||
registry.register(bus)
|
||||
}
|
||||
|
||||
val ENORMOUS by registry.register("enormous") { PlacementModifierType { EnormousPlacement.CODEC } }
|
||||
val ELLIPSOID_PLACEMENT by registry.register("ellipsoid") { PlacementModifierType { EllipsoidPlacement.CODEC } }
|
||||
val ENORMOUS_ELLIPSOID_PLACEMENT by registry.register("enormous_ellipsoid") { PlacementModifierType { EnormousEllipsoidPlacement.CODEC } }
|
||||
val WORM_PLACEMENT by registry.register("worm") { PlacementModifierType { WormPlacement.CODEC } }
|
||||
}
|
||||
|
@ -25,14 +25,41 @@ import kotlin.math.roundToInt
|
||||
* This placement modifier is designed to be terminal; other placement modifiers after this MUST NOT be placed
|
||||
*/
|
||||
data class EllipsoidPlacement(
|
||||
override val x: FloatProvider,
|
||||
override val z: FloatProvider,
|
||||
override val y: FloatProvider,
|
||||
override val count: IntProvider,
|
||||
override val xLength: FloatProvider,
|
||||
override val zLength: FloatProvider,
|
||||
override val yLength: FloatProvider,
|
||||
) : PlacementModifier(), IEllipsoidPlacement {
|
||||
/**
|
||||
* X position within ellipsoid sampler, expected to be in range -1 .. 1
|
||||
*/
|
||||
val x: FloatProvider,
|
||||
|
||||
/**
|
||||
* Z position within ellipsoid sampler, expected to be in range -1 .. 1
|
||||
*/
|
||||
val z: FloatProvider,
|
||||
|
||||
/**
|
||||
* Y position within ellipsoid sampler, expected to be in range -1 .. 1
|
||||
*/
|
||||
val y: FloatProvider,
|
||||
|
||||
/**
|
||||
* Total amount of block positions to generate
|
||||
*/
|
||||
val count: IntProvider,
|
||||
|
||||
/**
|
||||
* Ellipsoid size sampler on X axis
|
||||
*/
|
||||
val xLength: FloatProvider,
|
||||
|
||||
/**
|
||||
* Ellipsoid size sampler on Z axis
|
||||
*/
|
||||
val zLength: FloatProvider,
|
||||
|
||||
/**
|
||||
* Ellipsoid size sampler on Y axis
|
||||
*/
|
||||
val yLength: FloatProvider,
|
||||
) : PlacementModifier() {
|
||||
init {
|
||||
require(xLength.minValue >= 1f) { "Bad ellipsoid x minimal size: $xLength" }
|
||||
require(zLength.minValue >= 1f) { "Bad ellipsoid z minimal size: $zLength" }
|
||||
@ -44,7 +71,36 @@ data class EllipsoidPlacement(
|
||||
random: RandomSource,
|
||||
position: BlockPos
|
||||
): Stream<BlockPos> {
|
||||
return getEllipsoidPositions(random, position)
|
||||
val count = count.sample(random)
|
||||
|
||||
if (count <= 0)
|
||||
return Stream.empty()
|
||||
|
||||
val xLength = xLength.sample(random)
|
||||
val zLength = zLength.sample(random)
|
||||
val yLength = yLength.sample(random)
|
||||
|
||||
val xPow = xLength * xLength
|
||||
val zPow = zLength * zLength
|
||||
val yPow = yLength * yLength
|
||||
|
||||
return Stream.generate {
|
||||
val x = this.x.sample(random) * xLength
|
||||
val y = this.y.sample(random) * yLength
|
||||
val z = this.z.sample(random) * zLength
|
||||
BlockPos(x.toInt(), y.toInt(), z.toInt())
|
||||
}
|
||||
.limit(count.toLong() * 10)
|
||||
.filter {
|
||||
val (ellipsoidX, ellipsoidY, ellipsoidZ) = it
|
||||
|
||||
(ellipsoidX * ellipsoidX) / xPow +
|
||||
(ellipsoidY * ellipsoidY) / yPow +
|
||||
(ellipsoidZ * ellipsoidZ) / zPow <= 1.0f
|
||||
}
|
||||
.distinct()
|
||||
.limit(count.toLong())
|
||||
.map { it + position }
|
||||
}
|
||||
|
||||
override fun type(): PlacementModifierType<*> {
|
||||
|
@ -1,60 +0,0 @@
|
||||
package ru.dbotthepony.mc.otm.worldgen.placement
|
||||
|
||||
import com.mojang.serialization.MapCodec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.util.RandomSource
|
||||
import net.minecraft.util.valueproviders.FloatProvider
|
||||
import net.minecraft.util.valueproviders.IntProvider
|
||||
import net.minecraft.world.level.levelgen.placement.PlacementModifierType
|
||||
import ru.dbotthepony.mc.otm.registry.data.MPlacementModifiers
|
||||
import java.util.stream.Stream
|
||||
|
||||
/**
|
||||
* Enormous ellipsoid ("cloud") placement, suitable to be used as ONLY primary placement modifier
|
||||
*
|
||||
* This placement modifier is designed to be terminal; other placement modifiers after this MUST NOT be placed
|
||||
*
|
||||
* @see AbstractEnormousPlacement
|
||||
*/
|
||||
class EnormousEllipsoidPlacement(
|
||||
parameters: Parameters,
|
||||
override val x: FloatProvider,
|
||||
override val z: FloatProvider,
|
||||
override val y: FloatProvider,
|
||||
override val count: IntProvider,
|
||||
override val xLength: FloatProvider,
|
||||
override val zLength: FloatProvider,
|
||||
override val yLength: FloatProvider,
|
||||
) : AbstractEnormousPlacement(parameters), IEllipsoidPlacement {
|
||||
init {
|
||||
require(xLength.minValue >= 1f) { "Bad ellipsoid x minimal size: $xLength" }
|
||||
require(zLength.minValue >= 1f) { "Bad ellipsoid z minimal size: $zLength" }
|
||||
require(yLength.minValue >= 1f) { "Bad ellipsoid y minimal size: $yLength" }
|
||||
}
|
||||
|
||||
override fun type(): PlacementModifierType<*> {
|
||||
return MPlacementModifiers.ENORMOUS_ELLIPSOID_PLACEMENT
|
||||
}
|
||||
|
||||
override fun getPositions(center: BlockPos, random: RandomSource): Stream<BlockPos> {
|
||||
return getEllipsoidPositions(random, center)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val CODEC: MapCodec<EnormousEllipsoidPlacement> by lazy {
|
||||
RecordCodecBuilder.mapCodec {
|
||||
it.group(
|
||||
PARAMETERS_CODEC.forGetter(EnormousEllipsoidPlacement::parameters),
|
||||
FloatProvider.CODEC.fieldOf("x").forGetter(EnormousEllipsoidPlacement::x),
|
||||
FloatProvider.CODEC.fieldOf("y").forGetter(EnormousEllipsoidPlacement::y),
|
||||
FloatProvider.CODEC.fieldOf("z").forGetter(EnormousEllipsoidPlacement::z),
|
||||
IntProvider.CODEC.fieldOf("count").forGetter(EnormousEllipsoidPlacement::count),
|
||||
FloatProvider.codec(1f, Float.MAX_VALUE).fieldOf("x_size").forGetter(EnormousEllipsoidPlacement::xLength),
|
||||
FloatProvider.codec(1f, Float.MAX_VALUE).fieldOf("z_size").forGetter(EnormousEllipsoidPlacement::zLength),
|
||||
FloatProvider.codec(1f, Float.MAX_VALUE).fieldOf("y_size").forGetter(EnormousEllipsoidPlacement::yLength),
|
||||
).apply(it, ::EnormousEllipsoidPlacement)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -12,17 +12,16 @@ 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 net.minecraft.world.level.levelgen.placement.PlacementModifierType
|
||||
import ru.dbotthepony.kommons.util.XXHash64
|
||||
import ru.dbotthepony.mc.otm.core.util.PCG32RandomSource
|
||||
import ru.dbotthepony.mc.otm.data.codec.minRange
|
||||
import ru.dbotthepony.mc.otm.worldgen.placement.AbstractEnormousPlacement.Parameters
|
||||
import ru.dbotthepony.mc.otm.registry.data.MPlacementModifiers
|
||||
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
|
||||
@ -32,35 +31,23 @@ import kotlin.math.sqrt
|
||||
/**
|
||||
* Enormous placement base, which allows it to span over several chunks without issues.
|
||||
*
|
||||
* MUST come as first placement modifier, other placement modifiers (such as rarity and
|
||||
* shuffle of center point within chunks) must be provided inside [Parameters.prePlacementModifiers] list, in same order as if they were
|
||||
* *before* this placement
|
||||
*
|
||||
* If "post-processing" placements are required, better provide them as [Parameters.postPlacementModifiers].
|
||||
* This modifier is designed to be the only "top-level" placement modifier,
|
||||
* and all logic regarding actual placements embedded in [children]
|
||||
*/
|
||||
abstract class AbstractEnormousPlacement(val parameters: Parameters) : PlacementModifier() {
|
||||
data class Parameters(
|
||||
/**
|
||||
* 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 prePlacementModifiers: List<PlacementModifier> = listOf(),
|
||||
|
||||
/**
|
||||
* Post placement modifiers, operating on positions returned by this placement
|
||||
*
|
||||
* Generally, using this will yield better results
|
||||
*/
|
||||
val postPlacementModifiers: List<PlacementModifier> = listOf(),
|
||||
)
|
||||
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 = ArrayList<BlockPos>()
|
||||
@ -78,8 +65,6 @@ abstract class AbstractEnormousPlacement(val parameters: Parameters) : Placement
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun getPositions(center: BlockPos, random: RandomSource): Stream<BlockPos>
|
||||
|
||||
private val level2cache = WeakHashMap<WorldGenLevel, Cache<ChunkPos, GeneratedChunk>>()
|
||||
private val lock = ReentrantLock()
|
||||
|
||||
@ -102,7 +87,7 @@ abstract class AbstractEnormousPlacement(val parameters: Parameters) : Placement
|
||||
val dataStream = DataOutputStream(bytes)
|
||||
|
||||
dataStream.writeLong(context.level.seed)
|
||||
dataStream.writeLong(parameters.seedMix)
|
||||
dataStream.writeLong(seedMix)
|
||||
dataStream.writeInt(pos.x)
|
||||
dataStream.writeInt(pos.z)
|
||||
|
||||
@ -111,25 +96,24 @@ abstract class AbstractEnormousPlacement(val parameters: Parameters) : Placement
|
||||
|
||||
val random = PCG32RandomSource(hash.digestAsLong())
|
||||
var stream = Stream.of(BlockPos(pos.minBlockX, 0, pos.minBlockZ))
|
||||
parameters.prePlacementModifiers.forEach { modifier -> stream = stream.flatMap { modifier.getPositions(context, random, it).sequential() } }
|
||||
stream = stream.flatMap { getPositions(it, random) }
|
||||
parameters.postPlacementModifiers.forEach { modifier -> stream = stream.flatMap { modifier.getPositions(context, random, it).sequential() } }
|
||||
children.forEach { modifier -> stream = stream.flatMap { modifier.getPositions(context, random, it).sequential() } }
|
||||
return GeneratedChunk(stream)
|
||||
}
|
||||
|
||||
final override fun getPositions(context: PlacementContext, random: RandomSource, pos: BlockPos): Stream<BlockPos> {
|
||||
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 -parameters.chunkScanRange .. parameters.chunkScanRange) {
|
||||
for (z in -parameters.chunkScanRange .. parameters.chunkScanRange) {
|
||||
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 <= parameters.chunkScanRange) {
|
||||
if (radius <= chunkScanRange) {
|
||||
val thisPos = ChunkPos(cPos.x + x, cPos.z + z)
|
||||
|
||||
instances.add(getCache(context.level).get(thisPos) { computeChunk(context, thisPos) })
|
||||
instances.add(cache.get(thisPos) { computeChunk(context, thisPos) })
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -137,14 +121,17 @@ abstract class AbstractEnormousPlacement(val parameters: Parameters) : Placement
|
||||
return instances.stream().flatMap { it.getPositions(cPos) }
|
||||
}
|
||||
|
||||
override fun type(): PlacementModifierType<*> {
|
||||
return MPlacementModifiers.ENORMOUS
|
||||
}
|
||||
|
||||
companion object {
|
||||
val PARAMETERS_CODEC: MapCodec<Parameters> = RecordCodecBuilder.mapCodec {
|
||||
val CODEC: MapCodec<EnormousPlacement> = RecordCodecBuilder.mapCodec {
|
||||
it.group(
|
||||
Codec.INT.minRange(0).fieldOf("chunk_scan_range").forGetter(Parameters::chunkScanRange),
|
||||
Codec.LONG.fieldOf("seed_mix").forGetter(Parameters::seedMix),
|
||||
CODEC.listOf().optionalFieldOf("placement", listOf()).forGetter(Parameters::prePlacementModifiers),
|
||||
CODEC.listOf().optionalFieldOf("post_placement", listOf()).forGetter(Parameters::postPlacementModifiers),
|
||||
).apply(it, ::Parameters)
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
package ru.dbotthepony.mc.otm.worldgen.placement
|
||||
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.util.RandomSource
|
||||
import net.minecraft.util.valueproviders.FloatProvider
|
||||
import net.minecraft.util.valueproviders.IntProvider
|
||||
import ru.dbotthepony.mc.otm.core.math.component1
|
||||
import ru.dbotthepony.mc.otm.core.math.component2
|
||||
import ru.dbotthepony.mc.otm.core.math.component3
|
||||
import ru.dbotthepony.mc.otm.core.math.plus
|
||||
import java.util.stream.Stream
|
||||
|
||||
interface IEllipsoidPlacement {
|
||||
/**
|
||||
* X position within ellipsoid sampler, expected to be in range -1 .. 1
|
||||
*/
|
||||
val x: FloatProvider
|
||||
|
||||
/**
|
||||
* Z position within ellipsoid sampler, expected to be in range -1 .. 1
|
||||
*/
|
||||
val z: FloatProvider
|
||||
|
||||
/**
|
||||
* Y position within ellipsoid sampler, expected to be in range -1 .. 1
|
||||
*/
|
||||
val y: FloatProvider
|
||||
|
||||
/**
|
||||
* Total amount of block positions to generate
|
||||
*/
|
||||
val count: IntProvider
|
||||
|
||||
/**
|
||||
* Ellipsoid size sampler on X axis
|
||||
*/
|
||||
val xLength: FloatProvider
|
||||
|
||||
/**
|
||||
* Ellipsoid size sampler on Z axis
|
||||
*/
|
||||
val zLength: FloatProvider
|
||||
|
||||
/**
|
||||
* Ellipsoid size sampler on Y axis
|
||||
*/
|
||||
val yLength: FloatProvider
|
||||
|
||||
fun getEllipsoidPositions(random: RandomSource, position: BlockPos): Stream<BlockPos> {
|
||||
val count = count.sample(random)
|
||||
|
||||
if (count <= 0)
|
||||
return Stream.empty()
|
||||
|
||||
val xLength = xLength.sample(random)
|
||||
val zLength = zLength.sample(random)
|
||||
val yLength = yLength.sample(random)
|
||||
|
||||
val xPow = xLength * xLength
|
||||
val zPow = zLength * zLength
|
||||
val yPow = yLength * yLength
|
||||
|
||||
return Stream.generate {
|
||||
val x = this.x.sample(random) * xLength
|
||||
val y = this.y.sample(random) * yLength
|
||||
val z = this.z.sample(random) * zLength
|
||||
BlockPos(x.toInt(), y.toInt(), z.toInt())
|
||||
}
|
||||
.limit(count.toLong() * 10)
|
||||
.filter {
|
||||
val (ellipsoidX, ellipsoidY, ellipsoidZ) = it
|
||||
|
||||
(ellipsoidX * ellipsoidX) / xPow +
|
||||
(ellipsoidY * ellipsoidY) / yPow +
|
||||
(ellipsoidZ * ellipsoidZ) / zPow <= 1.0f
|
||||
}
|
||||
.distinct()
|
||||
.limit(count.toLong())
|
||||
.map { it + position }
|
||||
}
|
||||
}
|
@ -10,6 +10,8 @@ import net.minecraft.util.valueproviders.ConstantFloat
|
||||
import net.minecraft.util.valueproviders.FloatProvider
|
||||
import net.minecraft.util.valueproviders.IntProvider
|
||||
import net.minecraft.util.valueproviders.UniformFloat
|
||||
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.mc.otm.core.math.Vector
|
||||
import ru.dbotthepony.mc.otm.core.math.angleDifference
|
||||
@ -28,7 +30,6 @@ import kotlin.math.sign
|
||||
import kotlin.math.sin
|
||||
|
||||
class WormPlacement(
|
||||
parameters: Parameters,
|
||||
val length: IntProvider,
|
||||
val turnChanceXZ: BooleanProvider,
|
||||
val turnChanceXY: BooleanProvider,
|
||||
@ -39,7 +40,7 @@ class WormPlacement(
|
||||
val initialAngleXY: FloatProvider = DEFAULT_INITIAL_ANGLE_XY,
|
||||
val maxTravelDown: Int = Int.MAX_VALUE,
|
||||
val maxTravelUp: Int = Int.MAX_VALUE,
|
||||
) : AbstractEnormousPlacement(parameters) {
|
||||
) : PlacementModifier() {
|
||||
private inner class Worm(private val random: RandomSource, private var position: Vector) {
|
||||
private var remainingDistance = length.sample(random)
|
||||
private var xzRotation = random.nextDouble(-PI / 2.0, PI / 2.0)
|
||||
@ -129,7 +130,7 @@ class WormPlacement(
|
||||
}
|
||||
}
|
||||
|
||||
override fun getPositions(center: BlockPos, random: RandomSource): Stream<BlockPos> {
|
||||
override fun getPositions(context: PlacementContext, random: RandomSource, center: BlockPos): Stream<BlockPos> {
|
||||
val worms = ArrayList<Worm>()
|
||||
worms.add(Worm(random, Vector.ZERO))
|
||||
val positions = ArrayList<BlockPos>()
|
||||
@ -200,7 +201,6 @@ class WormPlacement(
|
||||
|
||||
val CODEC: MapCodec<WormPlacement> = RecordCodecBuilder.mapCodec {
|
||||
it.group(
|
||||
PARAMETERS_CODEC.forGetter(WormPlacement::parameters),
|
||||
IntProvider.CODEC.fieldOf("length").forGetter(WormPlacement::length),
|
||||
BooleanProvider.CODEC.fieldOf("turn_chance_xz").forGetter(WormPlacement::turnChanceXZ),
|
||||
BooleanProvider.CODEC.fieldOf("turn_chance_xy").forGetter(WormPlacement::turnChanceXY),
|
||||
|
Loading…
Reference in New Issue
Block a user