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.resources.ResourceKey
|
||||||
import net.minecraft.tags.BiomeTags
|
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.ClampedNormalInt
|
||||||
|
import net.minecraft.util.valueproviders.UniformInt
|
||||||
import net.minecraft.world.level.levelgen.GenerationStep
|
import net.minecraft.world.level.levelgen.GenerationStep
|
||||||
import net.minecraft.world.level.levelgen.VerticalAnchor
|
import net.minecraft.world.level.levelgen.VerticalAnchor
|
||||||
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature
|
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.HeightRangePlacement
|
||||||
import net.minecraft.world.level.levelgen.placement.InSquarePlacement
|
import net.minecraft.world.level.levelgen.placement.InSquarePlacement
|
||||||
import net.minecraft.world.level.levelgen.placement.PlacedFeature
|
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.minecraft.world.level.levelgen.structure.templatesystem.TagMatchTest
|
||||||
import net.neoforged.neoforge.common.world.BiomeModifier
|
import net.neoforged.neoforge.common.world.BiomeModifier
|
||||||
import net.neoforged.neoforge.registries.NeoForgeRegistries
|
import net.neoforged.neoforge.registries.NeoForgeRegistries
|
||||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
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.data.world.StandardDeviationHeightProvider
|
||||||
import ru.dbotthepony.mc.otm.registry.MBlocks
|
import ru.dbotthepony.mc.otm.registry.MBlocks
|
||||||
import ru.dbotthepony.mc.otm.registry.MWorldGenFeatures
|
import ru.dbotthepony.mc.otm.registry.MWorldGenFeatures
|
||||||
@ -51,6 +56,7 @@ fun registerConfiguredFeatures(context: BootstrapContext<ConfiguredFeature<*, *>
|
|||||||
private object PlacedFeatures {
|
private object PlacedFeatures {
|
||||||
val NORMAL_TRITANIUM = key("normal_tritanium")
|
val NORMAL_TRITANIUM = key("normal_tritanium")
|
||||||
val DEEP_TRITANIUM = key("deep_tritanium")
|
val DEEP_TRITANIUM = key("deep_tritanium")
|
||||||
|
val CLOUD_TITANIUM = key("cloud_tritanium")
|
||||||
val BLACK_HOLE = key("black_hole")
|
val BLACK_HOLE = key("black_hole")
|
||||||
|
|
||||||
private fun key(name: String): ResourceKey<PlacedFeature> {
|
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)
|
val blackHole = configured.getOrThrow(ConfiguredFeatures.BLACK_HOLE)
|
||||||
|
|
||||||
context.register(PlacedFeatures.BLACK_HOLE, PlacedFeature(
|
context.register(PlacedFeatures.BLACK_HOLE, PlacedFeature(
|
||||||
@ -110,7 +134,8 @@ fun registerBiomeModifiers(context: BootstrapContext<BiomeModifier>) {
|
|||||||
biomes.getOrThrow(BiomeTags.IS_OVERWORLD),
|
biomes.getOrThrow(BiomeTags.IS_OVERWORLD),
|
||||||
HolderSet.direct(
|
HolderSet.direct(
|
||||||
placed.getOrThrow(PlacedFeatures.NORMAL_TRITANIUM),
|
placed.getOrThrow(PlacedFeatures.NORMAL_TRITANIUM),
|
||||||
placed.getOrThrow(PlacedFeatures.DEEP_TRITANIUM)
|
placed.getOrThrow(PlacedFeatures.DEEP_TRITANIUM),
|
||||||
|
placed.getOrThrow(PlacedFeatures.CLOUD_TITANIUM),
|
||||||
),
|
),
|
||||||
GenerationStep.Decoration.UNDERGROUND_ORES
|
GenerationStep.Decoration.UNDERGROUND_ORES
|
||||||
)
|
)
|
||||||
|
@ -99,6 +99,7 @@ object OverdriveThatMatters {
|
|||||||
MWorldGenFeatures.register(MOD_BUS)
|
MWorldGenFeatures.register(MOD_BUS)
|
||||||
CommandArgumentTypes.register(MOD_BUS)
|
CommandArgumentTypes.register(MOD_BUS)
|
||||||
MHeightProviders.register(MOD_BUS)
|
MHeightProviders.register(MOD_BUS)
|
||||||
|
MPlacementModifiers.register(MOD_BUS)
|
||||||
|
|
||||||
StorageStack.Companion.register(MOD_BUS)
|
StorageStack.Companion.register(MOD_BUS)
|
||||||
MatteryChestMenu.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)
|
data class DoublePair(val first: Double, val second: Double)
|
||||||
|
|
||||||
// normal distribution via Box-Muller
|
// 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 rand1: Double
|
||||||
var rand2: Double
|
var rand2: Double
|
||||||
var distSqr: 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
|
// All Mojang's random sources use MarsagliaPolarGaussian for generating normal distributed doubles,
|
||||||
fun RandomSource.nextNormalDouble(stddev: Double, mean: Double): DoublePair {
|
// which is Box-Muller transform already, so we can use that
|
||||||
var rand1: Double
|
fun RandomSource.nextNormalDoubles(stddev: Double, mean: Double): DoublePair {
|
||||||
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)
|
|
||||||
|
|
||||||
return DoublePair(
|
return DoublePair(
|
||||||
rand1 * mapping * stddev + mean,
|
nextGaussian() * stddev + mean,
|
||||||
rand2 * mapping * 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
|
var i = 100
|
||||||
|
|
||||||
while (i-- > 0) {
|
while (i-- > 0) {
|
||||||
val (r0, r1) = random.nextNormalDouble(deviation, yd)
|
val i0 = random.nextNormalDouble(deviation, yd).toInt()
|
||||||
val i0 = r0.toInt()
|
|
||||||
val i1 = r1.toInt()
|
|
||||||
|
|
||||||
if (i0 in context.minGenY .. context.genDepth) {
|
if (i0 in context.minGenY .. context.genDepth) {
|
||||||
return i0
|
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