Tritanium cloud/ellipsoid ore distribution
This commit is contained in:
parent
35e871890c
commit
d528f8465c
@ -6,6 +6,9 @@ import net.minecraft.data.worldgen.BootstrapContext
|
||||
import net.minecraft.resources.ResourceKey
|
||||
import net.minecraft.tags.BiomeTags
|
||||
import net.minecraft.tags.BlockTags
|
||||
import net.minecraft.util.valueproviders.ClampedNormalFloat
|
||||
import net.minecraft.util.valueproviders.ClampedNormalInt
|
||||
import net.minecraft.util.valueproviders.UniformInt
|
||||
import net.minecraft.world.level.levelgen.GenerationStep
|
||||
import net.minecraft.world.level.levelgen.VerticalAnchor
|
||||
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature
|
||||
@ -16,10 +19,12 @@ import net.minecraft.world.level.levelgen.placement.CountPlacement
|
||||
import net.minecraft.world.level.levelgen.placement.HeightRangePlacement
|
||||
import net.minecraft.world.level.levelgen.placement.InSquarePlacement
|
||||
import net.minecraft.world.level.levelgen.placement.PlacedFeature
|
||||
import net.minecraft.world.level.levelgen.placement.RarityFilter
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.TagMatchTest
|
||||
import net.neoforged.neoforge.common.world.BiomeModifier
|
||||
import net.neoforged.neoforge.registries.NeoForgeRegistries
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.data.world.EllipsoidPlacement
|
||||
import ru.dbotthepony.mc.otm.data.world.StandardDeviationHeightProvider
|
||||
import ru.dbotthepony.mc.otm.registry.MBlocks
|
||||
import ru.dbotthepony.mc.otm.registry.MWorldGenFeatures
|
||||
@ -51,6 +56,7 @@ fun registerConfiguredFeatures(context: BootstrapContext<ConfiguredFeature<*, *>
|
||||
private object PlacedFeatures {
|
||||
val NORMAL_TRITANIUM = key("normal_tritanium")
|
||||
val DEEP_TRITANIUM = key("deep_tritanium")
|
||||
val CLOUD_TITANIUM = key("cloud_tritanium")
|
||||
val BLACK_HOLE = key("black_hole")
|
||||
|
||||
private fun key(name: String): ResourceKey<PlacedFeature> {
|
||||
@ -80,6 +86,24 @@ fun registerPlacedFeatures(context: BootstrapContext<PlacedFeature>) {
|
||||
)
|
||||
))
|
||||
|
||||
context.register(PlacedFeatures.CLOUD_TITANIUM, PlacedFeature(
|
||||
ore,
|
||||
listOf(
|
||||
RarityFilter.onAverageOnceEvery(6),
|
||||
InSquarePlacement.spread(),
|
||||
HeightRangePlacement.of(StandardDeviationHeightProvider(VerticalAnchor.absolute(10), 15.0)),
|
||||
EllipsoidPlacement(
|
||||
x = ClampedNormalInt.of(0f, 12f, Int.MIN_VALUE, Int.MAX_VALUE),
|
||||
y = ClampedNormalInt.of(0f, 12f, Int.MIN_VALUE, Int.MAX_VALUE),
|
||||
z = ClampedNormalInt.of(0f, 8f, Int.MIN_VALUE, Int.MAX_VALUE),
|
||||
count = ClampedNormalInt.of(100f, 100f, 80, 300),
|
||||
xLength = ClampedNormalFloat.of(11f, 4f, 4f, 16f),
|
||||
yLength = ClampedNormalFloat.of(11f, 4f, 4f, 16f),
|
||||
zLength = ClampedNormalFloat.of(11f, 4f, 4f, 16f),
|
||||
)
|
||||
)
|
||||
))
|
||||
|
||||
val blackHole = configured.getOrThrow(ConfiguredFeatures.BLACK_HOLE)
|
||||
|
||||
context.register(PlacedFeatures.BLACK_HOLE, PlacedFeature(
|
||||
@ -110,7 +134,8 @@ fun registerBiomeModifiers(context: BootstrapContext<BiomeModifier>) {
|
||||
biomes.getOrThrow(BiomeTags.IS_OVERWORLD),
|
||||
HolderSet.direct(
|
||||
placed.getOrThrow(PlacedFeatures.NORMAL_TRITANIUM),
|
||||
placed.getOrThrow(PlacedFeatures.DEEP_TRITANIUM)
|
||||
placed.getOrThrow(PlacedFeatures.DEEP_TRITANIUM),
|
||||
placed.getOrThrow(PlacedFeatures.CLOUD_TITANIUM),
|
||||
),
|
||||
GenerationStep.Decoration.UNDERGROUND_ORES
|
||||
)
|
||||
|
@ -99,6 +99,7 @@ object OverdriveThatMatters {
|
||||
MWorldGenFeatures.register(MOD_BUS)
|
||||
CommandArgumentTypes.register(MOD_BUS)
|
||||
MHeightProviders.register(MOD_BUS)
|
||||
MPlacementModifiers.register(MOD_BUS)
|
||||
|
||||
StorageStack.Companion.register(MOD_BUS)
|
||||
MatteryChestMenu.Companion.register(MOD_BUS)
|
||||
|
@ -598,7 +598,7 @@ infix fun FluidStack.isNotSameAs(other: FluidStack): Boolean {
|
||||
data class DoublePair(val first: Double, val second: Double)
|
||||
|
||||
// normal distribution via Box-Muller
|
||||
fun RandomGenerator.nextNormalDouble(stddev: Double, mean: Double): DoublePair {
|
||||
fun RandomGenerator.nextNormalDoubles(stddev: Double, mean: Double): DoublePair {
|
||||
var rand1: Double
|
||||
var rand2: Double
|
||||
var distSqr: Double
|
||||
@ -617,22 +617,15 @@ fun RandomGenerator.nextNormalDouble(stddev: Double, mean: Double): DoublePair {
|
||||
)
|
||||
}
|
||||
|
||||
// this kinda exists in form of nextGaussian, but it doesn't allow to specify deviation and mean
|
||||
fun RandomSource.nextNormalDouble(stddev: Double, mean: Double): DoublePair {
|
||||
var rand1: Double
|
||||
var rand2: Double
|
||||
var distSqr: Double
|
||||
|
||||
do {
|
||||
rand1 = 2.0 * nextDouble() - 1.0
|
||||
rand2 = 2.0 * nextDouble() - 1.0
|
||||
distSqr = rand1 * rand1 + rand2 * rand2
|
||||
} while (distSqr >= 1)
|
||||
|
||||
val mapping = sqrt(-2.0 * ln(distSqr) / distSqr)
|
||||
|
||||
// All Mojang's random sources use MarsagliaPolarGaussian for generating normal distributed doubles,
|
||||
// which is Box-Muller transform already, so we can use that
|
||||
fun RandomSource.nextNormalDoubles(stddev: Double, mean: Double): DoublePair {
|
||||
return DoublePair(
|
||||
rand1 * mapping * stddev + mean,
|
||||
rand2 * mapping * stddev + mean
|
||||
nextGaussian() * stddev + mean,
|
||||
nextGaussian() * stddev + mean
|
||||
)
|
||||
}
|
||||
|
||||
fun RandomSource.nextNormalDouble(stddev: Double, mean: Double): Double {
|
||||
return nextGaussian() * stddev + mean
|
||||
}
|
||||
|
@ -0,0 +1,93 @@
|
||||
package ru.dbotthepony.mc.otm.data.world
|
||||
|
||||
import com.mojang.serialization.Codec
|
||||
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.PlacementContext
|
||||
import net.minecraft.world.level.levelgen.placement.PlacementModifier
|
||||
import net.minecraft.world.level.levelgen.placement.PlacementModifierType
|
||||
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.minus
|
||||
import ru.dbotthepony.mc.otm.core.math.plus
|
||||
import ru.dbotthepony.mc.otm.data.codec.minRange
|
||||
import ru.dbotthepony.mc.otm.registry.MPlacementModifiers
|
||||
import java.util.stream.Stream
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
// aka "cloud placement"
|
||||
data class EllipsoidPlacement(
|
||||
val x: IntProvider,
|
||||
val z: IntProvider,
|
||||
val y: IntProvider,
|
||||
val count: IntProvider,
|
||||
val xLength: FloatProvider,
|
||||
val zLength: FloatProvider,
|
||||
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" }
|
||||
require(yLength.minValue >= 1f) { "Bad ellipsoid y minimal size: $yLength" }
|
||||
}
|
||||
|
||||
override fun getPositions(
|
||||
context: PlacementContext,
|
||||
random: RandomSource,
|
||||
position: BlockPos
|
||||
): Stream<BlockPos> {
|
||||
var 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
|
||||
|
||||
count = minOf(count, (xLength * zLength * yLength * PI * (4.0 / 3.0)).roundToInt())
|
||||
|
||||
return Stream.generate { position + BlockPos(this.x.sample(random), this.y.sample(random), this.z.sample(random)) }
|
||||
.limit(count * 10L) // failsafe
|
||||
.filter {
|
||||
val (ellipsoidX, ellipsoidY, ellipsoidZ) = it - position
|
||||
|
||||
(ellipsoidX * ellipsoidX) / xPow +
|
||||
(ellipsoidY * ellipsoidY) / yPow +
|
||||
(ellipsoidZ * ellipsoidZ) / zPow <= 1.0f
|
||||
}
|
||||
.distinct()
|
||||
.limit(count.toLong())
|
||||
}
|
||||
|
||||
override fun type(): PlacementModifierType<*> {
|
||||
return MPlacementModifiers.ELLIPSOID_PLACEMENT
|
||||
}
|
||||
|
||||
companion object {
|
||||
val CODEC: MapCodec<EllipsoidPlacement> by lazy {
|
||||
RecordCodecBuilder.mapCodec {
|
||||
it.group(
|
||||
IntProvider.CODEC.fieldOf("x").forGetter(EllipsoidPlacement::x),
|
||||
IntProvider.CODEC.fieldOf("y").forGetter(EllipsoidPlacement::y),
|
||||
IntProvider.CODEC.fieldOf("z").forGetter(EllipsoidPlacement::z),
|
||||
IntProvider.CODEC.fieldOf("count").forGetter(EllipsoidPlacement::count),
|
||||
FloatProvider.codec(1f, Float.MAX_VALUE).fieldOf("x_size").forGetter(EllipsoidPlacement::xLength),
|
||||
FloatProvider.codec(1f, Float.MAX_VALUE).fieldOf("z_size").forGetter(EllipsoidPlacement::zLength),
|
||||
FloatProvider.codec(1f, Float.MAX_VALUE).fieldOf("y_size").forGetter(EllipsoidPlacement::yLength),
|
||||
).apply(it, ::EllipsoidPlacement)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -26,14 +26,10 @@ data class StandardDeviationHeightProvider(
|
||||
var i = 100
|
||||
|
||||
while (i-- > 0) {
|
||||
val (r0, r1) = random.nextNormalDouble(deviation, yd)
|
||||
val i0 = r0.toInt()
|
||||
val i1 = r1.toInt()
|
||||
val i0 = random.nextNormalDouble(deviation, yd).toInt()
|
||||
|
||||
if (i0 in context.minGenY .. context.genDepth) {
|
||||
return i0
|
||||
} else if (i1 in context.minGenY .. context.genDepth) {
|
||||
return i1
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,16 @@
|
||||
package ru.dbotthepony.mc.otm.registry
|
||||
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.world.level.levelgen.placement.PlacementModifierType
|
||||
import net.neoforged.bus.api.IEventBus
|
||||
import ru.dbotthepony.mc.otm.data.world.EllipsoidPlacement
|
||||
|
||||
object MPlacementModifiers {
|
||||
private val registry = MDeferredRegister(BuiltInRegistries.PLACEMENT_MODIFIER_TYPE)
|
||||
|
||||
fun register(bus: IEventBus) {
|
||||
registry.register(bus)
|
||||
}
|
||||
|
||||
val ELLIPSOID_PLACEMENT by registry.register("ellipsoid") { PlacementModifierType { EllipsoidPlacement.CODEC } }
|
||||
}
|
Loading…
Reference in New Issue
Block a user