diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/WorldGen.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/WorldGen.kt index 944cd851e..a2e805f68 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/WorldGen.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/WorldGen.kt @@ -26,6 +26,7 @@ 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.OneOfFloatProvider import ru.dbotthepony.mc.otm.worldgen.placement.StandardDeviationHeightProvider import ru.dbotthepony.mc.otm.registry.game.MBlocks import ru.dbotthepony.mc.otm.registry.data.MWorldGenFeatures @@ -109,6 +110,11 @@ fun registerPlacedFeatures(context: BootstrapContext) { run { val ore = configured.getOrThrow(ConfiguredFeatures.DILITHIUM) + val ringularity = OneOfFloatProvider.of( + ClampedNormalFloat.of(0.4f, 0.2f, -2f, 2f), + ClampedNormalFloat.of(-0.4f, 0.2f, -2f, 2f), + ) + context.register(PlacedFeatures.DILITHIUM, PlacedFeature( ore, listOf( @@ -116,18 +122,18 @@ fun registerPlacedFeatures(context: BootstrapContext) { parameters = AbstractEnormousPlacement.Parameters( chunkScanRange = 5, placementModifiers = listOf( - RarityFilter.onAverageOnceEvery(60), + RarityFilter.onAverageOnceEvery(120), InSquarePlacement.spread(), HeightRangePlacement.of(StandardDeviationHeightProvider(VerticalAnchor.absolute(0), 15.0)), ) ), - x = ClampedNormalFloat.of(0f, 0.3f, -2f, 2f), - y = ClampedNormalFloat.of(0f, 0.3f, -2f, 2f), - z = ClampedNormalFloat.of(0f, 0.3f, -2f, 2f), - count = UniformInt.of(8000, 24000), - xLength = UniformFloat.of(30f, 60f), + x = ringularity, + y = ringularity, + z = ringularity, + count = UniformInt.of(8000, 28000), + xLength = UniformFloat.of(30f, 70f), yLength = UniformFloat.of(40f, 90f), - zLength = UniformFloat.of(30f, 60f), + zLength = UniformFloat.of(30f, 70f), ) ) )) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/OverdriveThatMatters.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/OverdriveThatMatters.kt index c9d4377f1..3f8d77806 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/OverdriveThatMatters.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/OverdriveThatMatters.kt @@ -86,6 +86,7 @@ import ru.dbotthepony.mc.otm.registry.data.MHeightProviders import ru.dbotthepony.mc.otm.registry.data.MItemFunctionTypes import ru.dbotthepony.mc.otm.registry.data.MLootItemConditions import ru.dbotthepony.mc.otm.registry.data.MLootNumberProviders +import ru.dbotthepony.mc.otm.registry.data.MNumberProviders import ru.dbotthepony.mc.otm.registry.data.MPlacementModifiers import ru.dbotthepony.mc.otm.registry.data.MWorldGenFeatures import ru.dbotthepony.mc.otm.server.MCommands @@ -124,6 +125,7 @@ object OverdriveThatMatters { CommandArgumentTypes.register(MOD_BUS) MHeightProviders.register(MOD_BUS) MPlacementModifiers.register(MOD_BUS) + MNumberProviders.register(MOD_BUS) MLootNumberProviders.register(MOD_BUS) StorageStack.register(MOD_BUS) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/data/world/OneOfFloatProvider.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/data/world/OneOfFloatProvider.kt new file mode 100644 index 000000000..92d486a81 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/data/world/OneOfFloatProvider.kt @@ -0,0 +1,38 @@ +package ru.dbotthepony.mc.otm.data.world + +import net.minecraft.util.RandomSource +import net.minecraft.util.valueproviders.FloatProvider +import net.minecraft.util.valueproviders.FloatProviderType +import ru.dbotthepony.mc.otm.registry.data.MNumberProviders + +class OneOfFloatProvider(private val provider: OneOfProvider) : FloatProvider() { + override fun sample(random: RandomSource): Float { + return provider.select(random).sample(random) + } + + override fun getMinValue(): Float { + return provider.children.minOf { it.minValue } + } + + override fun getMaxValue(): Float { + return provider.children.minOf { it.maxValue } + } + + override fun getType(): FloatProviderType<*> { + return MNumberProviders.ONE_OF_FLOAT + } + + companion object { + @JvmStatic + fun of(vararg providers: FloatProvider): OneOfFloatProvider { + return OneOfFloatProvider(OneOfProvider.of(*providers)) + } + + @JvmStatic + fun of(providers: Collection): OneOfFloatProvider { + return OneOfFloatProvider(OneOfProvider.of(providers)) + } + + val CODEC = OneOfProvider.createCodec(FloatProvider.CODEC, ::OneOfFloatProvider, OneOfFloatProvider::provider) + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/data/world/OneOfIntProvider.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/data/world/OneOfIntProvider.kt new file mode 100644 index 000000000..92b85e50a --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/data/world/OneOfIntProvider.kt @@ -0,0 +1,38 @@ +package ru.dbotthepony.mc.otm.data.world + +import net.minecraft.util.RandomSource +import net.minecraft.util.valueproviders.IntProvider +import net.minecraft.util.valueproviders.IntProviderType +import ru.dbotthepony.mc.otm.registry.data.MNumberProviders + +class OneOfIntProvider(private val provider: OneOfProvider) : IntProvider() { + override fun sample(random: RandomSource): Int { + return provider.select(random).sample(random) + } + + override fun getMinValue(): Int { + return provider.children.minOf { it.minValue } + } + + override fun getMaxValue(): Int { + return provider.children.minOf { it.maxValue } + } + + override fun getType(): IntProviderType<*> { + return MNumberProviders.ONE_OF_INT + } + + companion object { + @JvmStatic + fun of(vararg providers: IntProvider): OneOfIntProvider { + return OneOfIntProvider(OneOfProvider.of(*providers)) + } + + @JvmStatic + fun of(providers: Collection): OneOfIntProvider { + return OneOfIntProvider(OneOfProvider.of(providers)) + } + + val CODEC = OneOfProvider.createCodec(IntProvider.CODEC, ::OneOfIntProvider, OneOfIntProvider::provider) + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/data/world/OneOfProvider.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/data/world/OneOfProvider.kt new file mode 100644 index 000000000..ddcfab249 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/data/world/OneOfProvider.kt @@ -0,0 +1,85 @@ +package ru.dbotthepony.mc.otm.data.world + +import com.google.common.collect.ImmutableList +import com.mojang.serialization.Codec +import com.mojang.serialization.DataResult +import com.mojang.serialization.MapCodec +import com.mojang.serialization.codecs.RecordCodecBuilder +import net.minecraft.util.RandomSource +import net.minecraft.util.valueproviders.IntProvider +import ru.dbotthepony.mc.otm.core.random +import java.util.Optional + +class OneOfProvider private constructor(val children: List, val selector: Optional = Optional.empty()) { + fun select(random: RandomSource): T { + if (selector.isEmpty) { + return children.random(random) + } + + val index = selector.get().sample(random) + + if (index !in children.indices) { + throw RuntimeException("Provided selector ($selector) provided index out of bounds: $index (bounds: ${children.indices})") + } + + return children[index] + } + + class Builder { + private var selector: IntProvider? = null + private val inputs = ArrayList() + + fun indexSelector(selector: IntProvider): Builder { + this.selector = selector + return this + } + + fun add(vararg provider: T): Builder { + inputs.addAll(provider) + return this + } + + fun copy(): Builder { + val new = Builder() + new.selector = selector + new.inputs.addAll(inputs) + return new + } + + fun build(): OneOfProvider { + return OneOfProvider(ImmutableList.copyOf(inputs), Optional.ofNullable(selector)) + } + } + + companion object { + @JvmStatic + fun of(vararg providers: T): OneOfProvider { + return OneOfProvider(ImmutableList.copyOf(providers)) + } + + @JvmStatic + fun of(providers: Collection): OneOfProvider { + return OneOfProvider(ImmutableList.copyOf(providers)) + } + + @JvmStatic + fun createCodec(childrenCodec: Codec): MapCodec> { + return RecordCodecBuilder.mapCodec { + it.group( + Codec.list(childrenCodec, 1, Int.MAX_VALUE).fieldOf("children").forGetter> { it.children }, + IntProvider.POSITIVE_CODEC.optionalFieldOf("selector").forGetter> { it.selector }, + ).apply(it, ::OneOfProvider) + }.validate { + if (it.selector.isEmpty || it.selector.get().minValue in it.children.indices && it.selector.get().maxValue in it.children.indices) { + return@validate DataResult.success(it) + } else { + return@validate DataResult.error { "Provided number sampler ${it.selector.get()} can produce values outside of children list index range (list size: ${it.children.size})" } + } + } + } + + fun createCodec(childrenCodec: Codec, to: (OneOfProvider) -> S, from: (S) -> OneOfProvider): MapCodec { + return createCodec(childrenCodec).xmap(to, from) + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/data/MNumberProviders.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/data/MNumberProviders.kt new file mode 100644 index 000000000..bfa161372 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/data/MNumberProviders.kt @@ -0,0 +1,22 @@ +package ru.dbotthepony.mc.otm.registry.data + +import net.minecraft.core.registries.BuiltInRegistries +import net.minecraft.util.valueproviders.FloatProviderType +import net.minecraft.util.valueproviders.IntProviderType +import net.neoforged.bus.api.IEventBus +import ru.dbotthepony.mc.otm.data.world.OneOfFloatProvider +import ru.dbotthepony.mc.otm.data.world.OneOfIntProvider +import ru.dbotthepony.mc.otm.registry.MDeferredRegister + +object MNumberProviders { + private val floats = MDeferredRegister(BuiltInRegistries.FLOAT_PROVIDER_TYPE) + private val ints = MDeferredRegister(BuiltInRegistries.INT_PROVIDER_TYPE) + + fun register(bus: IEventBus) { + floats.register(bus) + ints.register(bus) + } + + val ONE_OF_FLOAT by floats.register("one_of_float") { FloatProviderType { OneOfFloatProvider.CODEC } } + val ONE_OF_INT by ints.register("one_of_int") { IntProviderType { OneOfIntProvider.CODEC } } +}