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.tags.BlockTags
|
||||||
import net.minecraft.util.valueproviders.ClampedNormalFloat
|
import net.minecraft.util.valueproviders.ClampedNormalFloat
|
||||||
import net.minecraft.util.valueproviders.ConstantFloat
|
import net.minecraft.util.valueproviders.ConstantFloat
|
||||||
import net.minecraft.util.valueproviders.ConstantInt
|
|
||||||
import net.minecraft.util.valueproviders.UniformFloat
|
import net.minecraft.util.valueproviders.UniformFloat
|
||||||
import net.minecraft.util.valueproviders.UniformInt
|
import net.minecraft.util.valueproviders.UniformInt
|
||||||
import net.minecraft.world.level.levelgen.GenerationStep
|
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.game.MBlocks
|
||||||
import ru.dbotthepony.mc.otm.registry.data.MWorldGenFeatures
|
import ru.dbotthepony.mc.otm.registry.data.MWorldGenFeatures
|
||||||
import ru.dbotthepony.mc.otm.worldgen.feature.BlackHolePlacerFeature
|
import ru.dbotthepony.mc.otm.worldgen.feature.BlackHolePlacerFeature
|
||||||
import ru.dbotthepony.mc.otm.worldgen.feature.DebugPlacerFeature
|
import ru.dbotthepony.mc.otm.worldgen.placement.EnormousPlacement
|
||||||
import ru.dbotthepony.mc.otm.worldgen.placement.AbstractEnormousPlacement
|
|
||||||
import ru.dbotthepony.mc.otm.worldgen.placement.EllipsoidPlacement
|
import ru.dbotthepony.mc.otm.worldgen.placement.EllipsoidPlacement
|
||||||
import ru.dbotthepony.mc.otm.worldgen.placement.EnormousEllipsoidPlacement
|
|
||||||
import ru.dbotthepony.mc.otm.worldgen.placement.WormPlacement
|
import ru.dbotthepony.mc.otm.worldgen.placement.WormPlacement
|
||||||
|
|
||||||
private object ConfiguredFeatures {
|
private object ConfiguredFeatures {
|
||||||
@ -118,16 +115,24 @@ fun registerPlacedFeatures(context: BootstrapContext<PlacedFeature>) {
|
|||||||
context.register(PlacedFeatures.WORM_TRITANIUM, PlacedFeature(
|
context.register(PlacedFeatures.WORM_TRITANIUM, PlacedFeature(
|
||||||
configured.getOrThrow(ConfiguredFeatures.TRITANIUM_ORE_SMALL),
|
configured.getOrThrow(ConfiguredFeatures.TRITANIUM_ORE_SMALL),
|
||||||
listOf(
|
listOf(
|
||||||
WormPlacement(
|
EnormousPlacement(
|
||||||
parameters = AbstractEnormousPlacement.Parameters(
|
|
||||||
chunkScanRange = 24,
|
chunkScanRange = 24,
|
||||||
seedMix = 9284343575495L,
|
seedMix = 9284343575495L,
|
||||||
prePlacementModifiers = listOf(
|
children = listOf(
|
||||||
RarityFilter.onAverageOnceEvery(300),
|
RarityFilter.onAverageOnceEvery(300),
|
||||||
InSquarePlacement.spread(),
|
InSquarePlacement.spread(),
|
||||||
HeightRangePlacement.of(StandardDeviationHeightProvider(VerticalAnchor.absolute(-40), 15.0)),
|
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(
|
EllipsoidPlacement(
|
||||||
count = UniformInt.of(15, 30),
|
count = UniformInt.of(15, 30),
|
||||||
xLength = ConstantFloat.of(14f),
|
xLength = ConstantFloat.of(14f),
|
||||||
@ -138,16 +143,6 @@ fun registerPlacedFeatures(context: BootstrapContext<PlacedFeature>) {
|
|||||||
z = 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,16 +159,14 @@ fun registerPlacedFeatures(context: BootstrapContext<PlacedFeature>) {
|
|||||||
context.register(PlacedFeatures.DILITHIUM, PlacedFeature(
|
context.register(PlacedFeatures.DILITHIUM, PlacedFeature(
|
||||||
ore,
|
ore,
|
||||||
listOf(
|
listOf(
|
||||||
EnormousEllipsoidPlacement(
|
EnormousPlacement(
|
||||||
parameters = AbstractEnormousPlacement.Parameters(
|
chunkScanRange = 6,
|
||||||
chunkScanRange = 5,
|
|
||||||
seedMix = 237483209523709234L,
|
seedMix = 237483209523709234L,
|
||||||
prePlacementModifiers = listOf(
|
children = listOf(
|
||||||
RarityFilter.onAverageOnceEvery(120),
|
RarityFilter.onAverageOnceEvery(120),
|
||||||
InSquarePlacement.spread(),
|
InSquarePlacement.spread(),
|
||||||
HeightRangePlacement.of(StandardDeviationHeightProvider(VerticalAnchor.absolute(0), 15.0)),
|
HeightRangePlacement.of(StandardDeviationHeightProvider(VerticalAnchor.absolute(0), 15.0)),
|
||||||
),
|
EllipsoidPlacement(
|
||||||
),
|
|
||||||
x = ringularity,
|
x = ringularity,
|
||||||
y = ringularity,
|
y = ringularity,
|
||||||
z = ringularity,
|
z = ringularity,
|
||||||
@ -182,6 +175,8 @@ fun registerPlacedFeatures(context: BootstrapContext<PlacedFeature>) {
|
|||||||
yLength = UniformFloat.of(40f, 90f),
|
yLength = UniformFloat.of(40f, 90f),
|
||||||
zLength = UniformFloat.of(30f, 70f),
|
zLength = UniformFloat.of(30f, 70f),
|
||||||
)
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
)
|
)
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import net.minecraft.world.level.levelgen.placement.PlacementModifierType
|
|||||||
import net.neoforged.bus.api.IEventBus
|
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.EllipsoidPlacement
|
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
|
import ru.dbotthepony.mc.otm.worldgen.placement.WormPlacement
|
||||||
|
|
||||||
object MPlacementModifiers {
|
object MPlacementModifiers {
|
||||||
@ -15,7 +15,7 @@ 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 ENORMOUS_ELLIPSOID_PLACEMENT by registry.register("enormous_ellipsoid") { PlacementModifierType { EnormousEllipsoidPlacement.CODEC } }
|
|
||||||
val WORM_PLACEMENT by registry.register("worm") { PlacementModifierType { WormPlacement.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
|
* This placement modifier is designed to be terminal; other placement modifiers after this MUST NOT be placed
|
||||||
*/
|
*/
|
||||||
data class EllipsoidPlacement(
|
data class EllipsoidPlacement(
|
||||||
override val x: FloatProvider,
|
/**
|
||||||
override val z: FloatProvider,
|
* X position within ellipsoid sampler, expected to be in range -1 .. 1
|
||||||
override val y: FloatProvider,
|
*/
|
||||||
override val count: IntProvider,
|
val x: FloatProvider,
|
||||||
override val xLength: FloatProvider,
|
|
||||||
override val zLength: FloatProvider,
|
/**
|
||||||
override val yLength: FloatProvider,
|
* Z position within ellipsoid sampler, expected to be in range -1 .. 1
|
||||||
) : PlacementModifier(), IEllipsoidPlacement {
|
*/
|
||||||
|
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 {
|
init {
|
||||||
require(xLength.minValue >= 1f) { "Bad ellipsoid x minimal size: $xLength" }
|
require(xLength.minValue >= 1f) { "Bad ellipsoid x minimal size: $xLength" }
|
||||||
require(zLength.minValue >= 1f) { "Bad ellipsoid z minimal size: $zLength" }
|
require(zLength.minValue >= 1f) { "Bad ellipsoid z minimal size: $zLength" }
|
||||||
@ -44,7 +71,36 @@ data class EllipsoidPlacement(
|
|||||||
random: RandomSource,
|
random: RandomSource,
|
||||||
position: BlockPos
|
position: BlockPos
|
||||||
): Stream<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<*> {
|
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.core.SectionPos
|
||||||
import net.minecraft.util.RandomSource
|
import net.minecraft.util.RandomSource
|
||||||
import net.minecraft.world.level.ChunkPos
|
import net.minecraft.world.level.ChunkPos
|
||||||
import net.minecraft.world.level.Level
|
|
||||||
import net.minecraft.world.level.WorldGenLevel
|
import net.minecraft.world.level.WorldGenLevel
|
||||||
import net.minecraft.world.level.levelgen.placement.PlacementContext
|
import net.minecraft.world.level.levelgen.placement.PlacementContext
|
||||||
import net.minecraft.world.level.levelgen.placement.PlacementModifier
|
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.kommons.util.XXHash64
|
||||||
import ru.dbotthepony.mc.otm.core.util.PCG32RandomSource
|
import ru.dbotthepony.mc.otm.core.util.PCG32RandomSource
|
||||||
import ru.dbotthepony.mc.otm.data.codec.minRange
|
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.io.DataOutputStream
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
import java.util.Collections
|
|
||||||
import java.util.WeakHashMap
|
import java.util.WeakHashMap
|
||||||
import java.util.concurrent.locks.ReentrantLock
|
import java.util.concurrent.locks.ReentrantLock
|
||||||
import java.util.stream.Stream
|
import java.util.stream.Stream
|
||||||
@ -32,14 +31,10 @@ import kotlin.math.sqrt
|
|||||||
/**
|
/**
|
||||||
* Enormous placement base, which allows it to span over several chunks without issues.
|
* 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
|
* This modifier is designed to be the only "top-level" placement modifier,
|
||||||
* shuffle of center point within chunks) must be provided inside [Parameters.prePlacementModifiers] list, in same order as if they were
|
* and all logic regarding actual placements embedded in [children]
|
||||||
* *before* this placement
|
|
||||||
*
|
|
||||||
* If "post-processing" placements are required, better provide them as [Parameters.postPlacementModifiers].
|
|
||||||
*/
|
*/
|
||||||
abstract class AbstractEnormousPlacement(val parameters: Parameters) : PlacementModifier() {
|
class EnormousPlacement(
|
||||||
data class Parameters(
|
|
||||||
/**
|
/**
|
||||||
* How many chunks away to look for actual placements
|
* How many chunks away to look for actual placements
|
||||||
*
|
*
|
||||||
@ -51,16 +46,8 @@ abstract class AbstractEnormousPlacement(val parameters: Parameters) : Placement
|
|||||||
/**
|
/**
|
||||||
* Baseline placement modifiers, dictating how to appear in chunk
|
* Baseline placement modifiers, dictating how to appear in chunk
|
||||||
*/
|
*/
|
||||||
val prePlacementModifiers: List<PlacementModifier> = listOf(),
|
val children: List<PlacementModifier>,
|
||||||
|
) : PlacementModifier() {
|
||||||
/**
|
|
||||||
* Post placement modifiers, operating on positions returned by this placement
|
|
||||||
*
|
|
||||||
* Generally, using this will yield better results
|
|
||||||
*/
|
|
||||||
val postPlacementModifiers: List<PlacementModifier> = listOf(),
|
|
||||||
)
|
|
||||||
|
|
||||||
private class GeneratedChunk(positions: Stream<BlockPos>) {
|
private class GeneratedChunk(positions: Stream<BlockPos>) {
|
||||||
// TODO: memory inefficient
|
// TODO: memory inefficient
|
||||||
private val positions = ArrayList<BlockPos>()
|
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 level2cache = WeakHashMap<WorldGenLevel, Cache<ChunkPos, GeneratedChunk>>()
|
||||||
private val lock = ReentrantLock()
|
private val lock = ReentrantLock()
|
||||||
|
|
||||||
@ -102,7 +87,7 @@ abstract class AbstractEnormousPlacement(val parameters: Parameters) : Placement
|
|||||||
val dataStream = DataOutputStream(bytes)
|
val dataStream = DataOutputStream(bytes)
|
||||||
|
|
||||||
dataStream.writeLong(context.level.seed)
|
dataStream.writeLong(context.level.seed)
|
||||||
dataStream.writeLong(parameters.seedMix)
|
dataStream.writeLong(seedMix)
|
||||||
dataStream.writeInt(pos.x)
|
dataStream.writeInt(pos.x)
|
||||||
dataStream.writeInt(pos.z)
|
dataStream.writeInt(pos.z)
|
||||||
|
|
||||||
@ -111,25 +96,24 @@ abstract class AbstractEnormousPlacement(val parameters: Parameters) : Placement
|
|||||||
|
|
||||||
val random = PCG32RandomSource(hash.digestAsLong())
|
val random = PCG32RandomSource(hash.digestAsLong())
|
||||||
var stream = Stream.of(BlockPos(pos.minBlockX, 0, pos.minBlockZ))
|
var stream = Stream.of(BlockPos(pos.minBlockX, 0, pos.minBlockZ))
|
||||||
parameters.prePlacementModifiers.forEach { modifier -> stream = stream.flatMap { modifier.getPositions(context, random, it).sequential() } }
|
children.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() } }
|
|
||||||
return GeneratedChunk(stream)
|
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 cPos = ChunkPos(pos)
|
||||||
val instances = ArrayList<GeneratedChunk>()
|
val instances = ArrayList<GeneratedChunk>()
|
||||||
|
|
||||||
for (x in -parameters.chunkScanRange .. parameters.chunkScanRange) {
|
for (x in -chunkScanRange .. chunkScanRange) {
|
||||||
for (z in -parameters.chunkScanRange .. parameters.chunkScanRange) {
|
for (z in -chunkScanRange .. chunkScanRange) {
|
||||||
// floor, so chunk scan range of 1 will give square instead of diamond
|
// floor, so chunk scan range of 1 will give square instead of diamond
|
||||||
val radius = sqrt(x.toDouble() * x + z.toDouble() * z).toInt()
|
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)
|
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) }
|
return instances.stream().flatMap { it.getPositions(cPos) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun type(): PlacementModifierType<*> {
|
||||||
|
return MPlacementModifiers.ENORMOUS
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val PARAMETERS_CODEC: MapCodec<Parameters> = RecordCodecBuilder.mapCodec {
|
val CODEC: MapCodec<EnormousPlacement> = RecordCodecBuilder.mapCodec {
|
||||||
it.group(
|
it.group(
|
||||||
Codec.INT.minRange(0).fieldOf("chunk_scan_range").forGetter(Parameters::chunkScanRange),
|
Codec.INT.minRange(0).fieldOf("chunk_scan_range").forGetter(EnormousPlacement::chunkScanRange),
|
||||||
Codec.LONG.fieldOf("seed_mix").forGetter(Parameters::seedMix),
|
Codec.LONG.fieldOf("seed_mix").forGetter(EnormousPlacement::seedMix),
|
||||||
CODEC.listOf().optionalFieldOf("placement", listOf()).forGetter(Parameters::prePlacementModifiers),
|
PlacementModifier.CODEC.listOf().optionalFieldOf("children", listOf()).forGetter(EnormousPlacement::children),
|
||||||
CODEC.listOf().optionalFieldOf("post_placement", listOf()).forGetter(Parameters::postPlacementModifiers),
|
).apply(it, ::EnormousPlacement)
|
||||||
).apply(it, ::Parameters)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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.FloatProvider
|
||||||
import net.minecraft.util.valueproviders.IntProvider
|
import net.minecraft.util.valueproviders.IntProvider
|
||||||
import net.minecraft.util.valueproviders.UniformFloat
|
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 net.minecraft.world.level.levelgen.placement.PlacementModifierType
|
||||||
import ru.dbotthepony.mc.otm.core.math.Vector
|
import ru.dbotthepony.mc.otm.core.math.Vector
|
||||||
import ru.dbotthepony.mc.otm.core.math.angleDifference
|
import ru.dbotthepony.mc.otm.core.math.angleDifference
|
||||||
@ -28,7 +30,6 @@ import kotlin.math.sign
|
|||||||
import kotlin.math.sin
|
import kotlin.math.sin
|
||||||
|
|
||||||
class WormPlacement(
|
class WormPlacement(
|
||||||
parameters: Parameters,
|
|
||||||
val length: IntProvider,
|
val length: IntProvider,
|
||||||
val turnChanceXZ: BooleanProvider,
|
val turnChanceXZ: BooleanProvider,
|
||||||
val turnChanceXY: BooleanProvider,
|
val turnChanceXY: BooleanProvider,
|
||||||
@ -39,7 +40,7 @@ class WormPlacement(
|
|||||||
val initialAngleXY: FloatProvider = DEFAULT_INITIAL_ANGLE_XY,
|
val initialAngleXY: FloatProvider = DEFAULT_INITIAL_ANGLE_XY,
|
||||||
val maxTravelDown: Int = Int.MAX_VALUE,
|
val maxTravelDown: Int = Int.MAX_VALUE,
|
||||||
val maxTravelUp: 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 inner class Worm(private val random: RandomSource, private var position: Vector) {
|
||||||
private var remainingDistance = length.sample(random)
|
private var remainingDistance = length.sample(random)
|
||||||
private var xzRotation = random.nextDouble(-PI / 2.0, PI / 2.0)
|
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>()
|
val worms = ArrayList<Worm>()
|
||||||
worms.add(Worm(random, Vector.ZERO))
|
worms.add(Worm(random, Vector.ZERO))
|
||||||
val positions = ArrayList<BlockPos>()
|
val positions = ArrayList<BlockPos>()
|
||||||
@ -200,7 +201,6 @@ class WormPlacement(
|
|||||||
|
|
||||||
val CODEC: MapCodec<WormPlacement> = RecordCodecBuilder.mapCodec {
|
val CODEC: MapCodec<WormPlacement> = RecordCodecBuilder.mapCodec {
|
||||||
it.group(
|
it.group(
|
||||||
PARAMETERS_CODEC.forGetter(WormPlacement::parameters),
|
|
||||||
IntProvider.CODEC.fieldOf("length").forGetter(WormPlacement::length),
|
IntProvider.CODEC.fieldOf("length").forGetter(WormPlacement::length),
|
||||||
BooleanProvider.CODEC.fieldOf("turn_chance_xz").forGetter(WormPlacement::turnChanceXZ),
|
BooleanProvider.CODEC.fieldOf("turn_chance_xz").forGetter(WormPlacement::turnChanceXZ),
|
||||||
BooleanProvider.CODEC.fieldOf("turn_chance_xy").forGetter(WormPlacement::turnChanceXY),
|
BooleanProvider.CODEC.fieldOf("turn_chance_xy").forGetter(WormPlacement::turnChanceXY),
|
||||||
|
Loading…
Reference in New Issue
Block a user