diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/OreGen.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/WorldGen.kt similarity index 77% rename from src/data/kotlin/ru/dbotthepony/mc/otm/datagen/OreGen.kt rename to src/data/kotlin/ru/dbotthepony/mc/otm/datagen/WorldGen.kt index 42c075079..4bb408e4a 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/OreGen.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/WorldGen.kt @@ -19,10 +19,14 @@ import net.minecraft.world.level.levelgen.placement.PlacedFeature 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.registry.MBlocks +import ru.dbotthepony.mc.otm.registry.MWorldGenFeatures +import ru.dbotthepony.mc.otm.worldgen.feature.BlackHolePlacerConfiguration private object ConfiguredFeatures { val TRITANIUM_ORE = key("tritanium_ore") + val BLACK_HOLE = key("black_hole") private fun key(name: String): ResourceKey<ConfiguredFeature<*, *>> { return ResourceKey.create(Registries.CONFIGURED_FEATURE, modLocation(name)) @@ -39,11 +43,14 @@ fun registerConfiguredFeatures(context: BootstrapContext<ConfiguredFeature<*, *> ) context.register(ConfiguredFeatures.TRITANIUM_ORE, ConfiguredFeature(Feature.ORE, OreConfiguration(target, 9))) + context.register(ConfiguredFeatures.BLACK_HOLE, ConfiguredFeature(MWorldGenFeatures.BLACK_HOLE_PLACER, + BlackHolePlacerConfiguration(0.001f, Decimal(125_000), Decimal(500_000)))) } private object PlacedFeatures { val NORMAL_TRITANIUM = key("normal_tritanium") val DEEP_TRITANIUM = key("deep_tritanium") + val BLACK_HOLE = key("black_hole") private fun key(name: String): ResourceKey<PlacedFeature> { return ResourceKey.create(Registries.PLACED_FEATURE, modLocation(name)) @@ -71,10 +78,21 @@ fun registerPlacedFeatures(context: BootstrapContext<PlacedFeature>) { HeightRangePlacement.uniform(VerticalAnchor.aboveBottom(8), VerticalAnchor.absolute(0)) ) )) + + val blackHole = configured.getOrThrow(ConfiguredFeatures.BLACK_HOLE) + + context.register(PlacedFeatures.BLACK_HOLE, PlacedFeature( + blackHole, + listOf( + CountPlacement.of(1), + HeightRangePlacement.uniform(VerticalAnchor.absolute(64), VerticalAnchor.absolute(128)) + ) + )) } private object BiomeModifiers { val TRITANIUM_ORE = key("tritanium_ore") + val BLACK_HOLE = key("black_hole") private fun key(name: String): ResourceKey<BiomeModifier> { return ResourceKey.create(NeoForgeRegistries.Keys.BIOME_MODIFIERS, modLocation(name)) @@ -96,4 +114,15 @@ fun registerBiomeModifiers(context: BootstrapContext<BiomeModifier>) { GenerationStep.Decoration.UNDERGROUND_ORES ) ) + + context.register( + BiomeModifiers.BLACK_HOLE, + net.neoforged.neoforge.common.world.BiomeModifiers.AddFeaturesBiomeModifier( + biomes.getOrThrow(BiomeTags.IS_OVERWORLD), + HolderSet.direct( + placed.getOrThrow(PlacedFeatures.BLACK_HOLE) + ), + GenerationStep.Decoration.SURFACE_STRUCTURES + ) + ) } diff --git a/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java b/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java index 87ac9a543..c4707e8c6 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java +++ b/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java @@ -127,6 +127,7 @@ public final class OverdriveThatMatters { MArmorMaterials.INSTANCE.register(bus); MCriteriaTriggers.INSTANCE.register(bus); MStats.INSTANCE.register(bus); + MWorldGenFeatures.INSTANCE.register(bus); CommandArgumentTypes.INSTANCE.register(bus); StorageStack.Companion.register(bus); diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MWorldGenFeatures.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MWorldGenFeatures.kt new file mode 100644 index 000000000..e6d47f33d --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MWorldGenFeatures.kt @@ -0,0 +1,19 @@ +package ru.dbotthepony.mc.otm.registry + +import net.minecraft.core.registries.BuiltInRegistries +import net.minecraft.world.level.levelgen.feature.Feature +import net.neoforged.bus.api.IEventBus +import ru.dbotthepony.mc.otm.worldgen.feature.BlackHolePlacerConfiguration +import ru.dbotthepony.mc.otm.worldgen.feature.BlackHolePlacerFeature + +object MWorldGenFeatures { + private val registry = MDeferredRegister(BuiltInRegistries.FEATURE) + + fun register(bus: IEventBus) { + registry.register(bus) + } + + val BLACK_HOLE_PLACER: Feature<BlackHolePlacerConfiguration> by registry.register("black_hole_placer") { + BlackHolePlacerFeature(BlackHolePlacerConfiguration.CODEC) + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/feature/BlackHolePlacer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/feature/BlackHolePlacer.kt new file mode 100644 index 000000000..099ecf94a --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/feature/BlackHolePlacer.kt @@ -0,0 +1,49 @@ +package ru.dbotthepony.mc.otm.worldgen.feature + +import com.mojang.serialization.Codec +import com.mojang.serialization.codecs.RecordCodecBuilder +import net.minecraft.world.level.levelgen.feature.Feature +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext +import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration +import ru.dbotthepony.mc.otm.block.entity.blackhole.BlackHoleBlockEntity +import ru.dbotthepony.mc.otm.core.math.Decimal +import ru.dbotthepony.mc.otm.core.math.nextDecimal +import ru.dbotthepony.mc.otm.data.DecimalCodec +import ru.dbotthepony.mc.otm.registry.MBlocks + +class BlackHolePlacerConfiguration(val chance: Float, val minMatter: Decimal, val maxMatter: Decimal) : FeatureConfiguration { + companion object { + val CODEC: Codec<BlackHolePlacerConfiguration> = RecordCodecBuilder.create { + t -> t.group( + Codec.floatRange(0.0F, 1.0F).fieldOf("chance").forGetter(BlackHolePlacerConfiguration::chance), + DecimalCodec.fieldOf("matter_min").forGetter(BlackHolePlacerConfiguration::minMatter), + DecimalCodec.fieldOf("matter_max").forGetter(BlackHolePlacerConfiguration::maxMatter) + ).apply(t, ::BlackHolePlacerConfiguration) + } + } +} + +class BlackHolePlacerFeature(val codec: Codec<BlackHolePlacerConfiguration>) : Feature<BlackHolePlacerConfiguration>(codec) { + override fun place(context: FeaturePlaceContext<BlackHolePlacerConfiguration?>): Boolean { + val random = context.random() + val level = context.level() + val pos = context.origin() + + val config = context.config() + if (config == null) return false + + if (level.getBlockState(pos).isAir && random.nextDouble() < config.chance.toDouble()) { + if (level.setBlock(pos, MBlocks.BLACK_HOLE.defaultBlockState(), 2)) { + val entity = level.getBlockEntity(pos) + + if (entity is BlackHoleBlockEntity) { + entity.mass = random.nextDecimal(config.minMatter, config.maxMatter) + } + + return true + } + } + + return false + } +}