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 d805e41db..bf60c242f 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/WorldGen.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/WorldGen.kt @@ -34,22 +34,20 @@ import ru.dbotthepony.mc.otm.registry.game.MBlocks import ru.dbotthepony.mc.otm.registry.data.MWorldGenFeatures import ru.dbotthepony.mc.otm.worldgen.EnhancedPlacedFeature import ru.dbotthepony.mc.otm.worldgen.feature.BlackHolePlacerFeature -import ru.dbotthepony.mc.otm.worldgen.feature.DebugPlacerFeature import ru.dbotthepony.mc.otm.worldgen.feature.EnhancedFeature -import ru.dbotthepony.mc.otm.worldgen.placement.ChainPlacement +import ru.dbotthepony.mc.otm.worldgen.placement import ru.dbotthepony.mc.otm.worldgen.placement.EllipsoidPlacement import ru.dbotthepony.mc.otm.worldgen.placement.EnhancedChainPlacement import ru.dbotthepony.mc.otm.worldgen.placement.EnhancedCountPlacement -import ru.dbotthepony.mc.otm.worldgen.placement.EnhancedPlacementModifier +import ru.dbotthepony.mc.otm.worldgen.placement.EnhancedPlacement import ru.dbotthepony.mc.otm.worldgen.placement.EnhancedSplitPlacement -import ru.dbotthepony.mc.otm.worldgen.placement.SplitPlacement import ru.dbotthepony.mc.otm.worldgen.placement.WormPlacement import ru.dbotthepony.mc.otm.worldgen.wrap private object ConfiguredFeatures { val TRITANIUM_ORE = key("tritanium_ore") val TRITANIUM_ORE_SMALL = key("tritanium_ore_small") - val DILITHIUM = ekey("dilithium") + val DILITHIUM = key("dilithium") val BLACK_HOLE = key("black_hole") private fun key(name: String): ResourceKey> { @@ -62,17 +60,6 @@ private object ConfiguredFeatures { } fun registerEnhancedConfiguredFeatures(context: BootstrapContext>) { - val stone = TagMatchTest(BlockTags.STONE_ORE_REPLACEABLES) - val deepslate = TagMatchTest(BlockTags.DEEPSLATE_ORE_REPLACEABLES) - - run { - val target = listOf( - OreConfiguration.target(stone, MBlocks.DILITHIUM_ORE.defaultBlockState()), - OreConfiguration.target(deepslate, MBlocks.DEEPSLATE_DILITHIUM_ORE.defaultBlockState()), - ) - - context.register(ConfiguredFeatures.DILITHIUM, EnhancedFeature.Wrapper.configure(ConfiguredFeature(Feature.REPLACE_SINGLE_BLOCK, ReplaceBlockConfiguration(target)))) - } } fun registerConfiguredFeatures(context: BootstrapContext>) { @@ -90,6 +77,15 @@ fun registerConfiguredFeatures(context: BootstrapContext //context.register(ConfiguredFeatures.TRITANIUM_ORE_SMALL, ConfiguredFeature(MWorldGenFeatures.DEBUG_PLACEMENT, DebugPlacerFeature.Config(MBlocks.TRITANIUM_ORE.defaultBlockState()))) } + run { + val target = listOf( + OreConfiguration.target(stone, MBlocks.DILITHIUM_ORE.defaultBlockState()), + OreConfiguration.target(deepslate, MBlocks.DEEPSLATE_DILITHIUM_ORE.defaultBlockState()), + ) + + context.register(ConfiguredFeatures.DILITHIUM, ConfiguredFeature(Feature.REPLACE_SINGLE_BLOCK, ReplaceBlockConfiguration(target))) + } + context.register(ConfiguredFeatures.BLACK_HOLE, ConfiguredFeature( MWorldGenFeatures.BLACK_HOLE_PLACER, BlackHolePlacerFeature.Config(Decimal("0.25"), Decimal(1)))) @@ -134,11 +130,16 @@ fun registerPlacedFeatures(context: BootstrapContext) { context.register( PlacedFeatures.WORM_TRITANIUM, - EnhancedPlacedFeature.Builder(RarityFilter.onAverageOnceEvery(140)) - .then(InSquarePlacement.spread()) - .then(HeightRangePlacement.of(StandardDeviationHeightProvider(VerticalAnchor.absolute(-40), 15.0))) - .then( + EnhancedPlacedFeature.configure( + chunkScanRange = 24, + seedMix = 9284343575495L, + root = EnhancedChainPlacement( + RarityFilter.onAverageOnceEvery(140).wrap(), + InSquarePlacement.spread().wrap(), + HeightRangePlacement.of(StandardDeviationHeightProvider(VerticalAnchor.absolute(-40), 15.0)).wrap(), + EnhancedSplitPlacement( + EnhancedSplitPlacement.Mode.COMBINE, // "heart" EllipsoidPlacement( count = UniformInt.of(600, 900), @@ -174,18 +175,16 @@ fun registerPlacedFeatures(context: BootstrapContext) { z = ClampedNormalFloat.of(0f, 0.2f, -1f, 1f), ) ) - ) - ) - .then(configured.getOrThrow(ConfiguredFeatures.TRITANIUM_ORE_SMALL)) - .build( - chunkScanRange = 24, - seedMix = 9284343575495L, + ), + + configured.getOrThrow(ConfiguredFeatures.TRITANIUM_ORE_SMALL).placement() ) + ) ) } run { - val ore = econfigured.getOrThrow(ConfiguredFeatures.DILITHIUM) + val ore = configured.getOrThrow(ConfiguredFeatures.DILITHIUM) val ringularity = OneOfFloatProvider.of( ClampedNormalFloat.of(0.4f, 0.2f, -2f, 2f), @@ -194,10 +193,13 @@ fun registerPlacedFeatures(context: BootstrapContext) { context.register( PlacedFeatures.DILITHIUM, - EnhancedPlacedFeature.Builder(RarityFilter.onAverageOnceEvery(120)) - .then(InSquarePlacement.spread()) - .then(HeightRangePlacement.of(StandardDeviationHeightProvider(VerticalAnchor.absolute(0), 15.0))) - .then( + EnhancedPlacedFeature.configure( + chunkScanRange = 6, + seedMix = 237483209523709234L, + root = EnhancedChainPlacement( + RarityFilter.onAverageOnceEvery(120).wrap(), + InSquarePlacement.spread().wrap(), + HeightRangePlacement.of(StandardDeviationHeightProvider(VerticalAnchor.absolute(0), 15.0)).wrap(), EllipsoidPlacement( x = ringularity, y = ringularity, @@ -206,13 +208,10 @@ fun registerPlacedFeatures(context: BootstrapContext) { xLength = UniformFloat.of(30f, 70f), yLength = UniformFloat.of(40f, 90f), zLength = UniformFloat.of(30f, 70f), - ) as EnhancedPlacementModifier - ) - .then(ore) - .build( - chunkScanRange = 6, - seedMix = 237483209523709234L, + ), + ore.placement() ) + ) ) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/OverdriveThatMatters.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/OverdriveThatMatters.kt index f7914ecaa..61dbff0cf 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/OverdriveThatMatters.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/OverdriveThatMatters.kt @@ -6,10 +6,8 @@ import net.neoforged.bus.api.EventPriority import net.neoforged.fml.common.Mod import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent -import ru.dbotthepony.mc.otm.player.android.AndroidResearchDescription import ru.dbotthepony.mc.otm.player.android.AndroidResearchDescriptions import ru.dbotthepony.mc.otm.player.android.AndroidResearchManager -import ru.dbotthepony.mc.otm.player.android.AndroidResearchResult import ru.dbotthepony.mc.otm.player.android.AndroidResearchResults import ru.dbotthepony.mc.otm.player.android.feature.EnderTeleporterFeature import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity @@ -93,7 +91,7 @@ import ru.dbotthepony.mc.otm.server.MCommands import ru.dbotthepony.mc.otm.storage.StorageStack import ru.dbotthepony.mc.otm.triggers.KillAsAndroidTrigger import ru.dbotthepony.mc.otm.worldgen.feature.EnhancedFeature -import ru.dbotthepony.mc.otm.worldgen.placement.EnhancedPlacementModifier +import ru.dbotthepony.mc.otm.worldgen.placement.EnhancedPlacement import thedarkcolour.kotlinforforge.neoforge.forge.DIST import thedarkcolour.kotlinforforge.neoforge.forge.FORGE_BUS import thedarkcolour.kotlinforforge.neoforge.forge.LOADING_CONTEXT @@ -142,7 +140,7 @@ object OverdriveThatMatters { DecimalProvider.register(MOD_BUS) BooleanProvider.register(MOD_BUS) EnhancedFeature.register(MOD_BUS) - EnhancedPlacementModifier.register(MOD_BUS) + EnhancedPlacement.register(MOD_BUS) AndroidResearchDescriptions.register(MOD_BUS) AndroidResearchResults.register(MOD_BUS) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MRegistries.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MRegistries.kt index 204facf30..16cc5ace4 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MRegistries.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MRegistries.kt @@ -13,9 +13,8 @@ import ru.dbotthepony.mc.otm.player.android.AndroidFeatureType import ru.dbotthepony.mc.otm.player.android.AndroidResearchDescription import ru.dbotthepony.mc.otm.player.android.AndroidResearchResult import ru.dbotthepony.mc.otm.storage.StorageStack -import ru.dbotthepony.mc.otm.worldgen.EnhancedPlacedFeature import ru.dbotthepony.mc.otm.worldgen.feature.EnhancedFeature -import ru.dbotthepony.mc.otm.worldgen.placement.EnhancedPlacementModifier +import ru.dbotthepony.mc.otm.worldgen.placement.EnhancedPlacement object MRegistries { private fun k(name: String): ResourceKey> { @@ -33,5 +32,5 @@ object MRegistries { val BOOLEAN_PROVIDER = k>("boolean_provider") val FEATURE = k>("feature") val CONFIGURED_FEATURE = k>("configured_feature") - val PLACEMENT_MODIFIER = k>("placement_modifier") + val PLACEMENT_MODIFIER = k>("placement_modifier") } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/data/MPlacementModifiers.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/data/MPlacementModifiers.kt index 499c7f7a7..2ca50b940 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/data/MPlacementModifiers.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/data/MPlacementModifiers.kt @@ -5,6 +5,7 @@ import net.minecraft.world.level.levelgen.placement.PlacementModifierType import net.neoforged.bus.api.IEventBus import ru.dbotthepony.mc.otm.registry.MDeferredRegister import ru.dbotthepony.mc.otm.registry.MRegistries +import ru.dbotthepony.mc.otm.worldgen.feature.EnhancedFeature import ru.dbotthepony.mc.otm.worldgen.placement.ChainPlacement import ru.dbotthepony.mc.otm.worldgen.placement.EllipsoidPlacement import ru.dbotthepony.mc.otm.worldgen.placement.EnhancedChainPlacement @@ -28,6 +29,7 @@ object MPlacementModifiers { val CHAIN by registry.register("chain") { PlacementModifierType { ChainPlacement.CODEC } } init { + enhancedRegistry.register("feature") { EnhancedFeature.ConfiguredWrapper.Companion } enhancedRegistry.register("ellipsoid") { EllipsoidPlacement.Companion } enhancedRegistry.register("worm") { WormPlacement.Companion } enhancedRegistry.register("split") { EnhancedSplitPlacement.Companion } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/EnhancedPlacedFeature.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/EnhancedPlacedFeature.kt index 754268a2e..dc9c245a4 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/EnhancedPlacedFeature.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/EnhancedPlacedFeature.kt @@ -10,7 +10,6 @@ import com.mojang.serialization.DataResult import com.mojang.serialization.DynamicOps import com.mojang.serialization.codecs.RecordCodecBuilder import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream -import it.unimi.dsi.fastutil.objects.ObjectArraySet import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet import net.minecraft.Util import net.minecraft.core.BlockPos @@ -26,122 +25,38 @@ import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfigur import net.minecraft.world.level.levelgen.placement.PlacedFeature import net.minecraft.world.level.levelgen.placement.PlacementModifier import ru.dbotthepony.kommons.util.XXHash64 -import ru.dbotthepony.mc.otm.core.collect.BlockPosSet -import ru.dbotthepony.mc.otm.core.collect.Vec3iHashStrategy import ru.dbotthepony.mc.otm.core.util.GJRAND64RandomSource import ru.dbotthepony.mc.otm.data.codec.minRange import ru.dbotthepony.mc.otm.worldgen.feature.EnhancedFeature -import ru.dbotthepony.mc.otm.worldgen.placement.EnhancedPlacementModifier +import ru.dbotthepony.mc.otm.worldgen.placement.EnhancedPlacement import java.io.DataOutputStream import java.time.Duration import java.util.LinkedList import kotlin.math.sqrt -private object NodeCodec : Codec { - private val list = Codec.list(this) - - override fun encode(input: EnhancedPlacedFeature.Node, ops: DynamicOps, prefix: T): DataResult { - val result = HashMap() - - if (input.children.isNotEmpty()) { - val re = list.encodeStart(ops, input.children) - - if (re.isError) - return re - - result[ops.createString("children")] = re.resultOrPartial().get() - } - - if (input.contents.left().isPresent) { - val re = EnhancedPlacementModifier.CODEC.encodeStart(ops, input.contents.left().get()) - - if (re.isError) - return DataResult.error { "Failed to serialize placement modifier: ${re.error().get().message()}" } - - result[ops.createString("modifier")] = re.resultOrPartial().get() - } else { - val re = EnhancedFeature.CODEC.encodeStart(ops, input.contents.right().get()) - - if (re.isError) - return DataResult.error { "Failed to serialize feature: ${re.error().get().message()}" } - - result[ops.createString("feature")] = re.resultOrPartial().get() - } - - return ops.mergeToMap(prefix, result) - } - - override fun decode(ops: DynamicOps, input: T): DataResult> { - return ops.getMap(input).flatMap { - val children = it.get("children") - val modifier = it.get("modifier") - val feature = it.get("feature") - - if (modifier != null && feature != null) { - return@flatMap DataResult.error { "Enhanced feature placement node should have either modifier or feature, but both are present" } - } else if (modifier == null && feature == null) { - return@flatMap DataResult.error { "Enhanced feature placement node contains no modifier and no feature" } - } - - val deserializeChildren: List - - if (children != null) { - val result = list.decode(ops, children) - - if (result.isError) - return@flatMap DataResult.error { result.error().get().message() } - - deserializeChildren = result.map { it.first }.getOrThrow() - } else { - deserializeChildren = emptyList() - } - - if (modifier != null) { - return@flatMap EnhancedPlacementModifier.CODEC.decode(ops, modifier).map { Pair(EnhancedPlacedFeature.Node(deserializeChildren, Either.left(it.first)), ops.empty()) } - } else { - return@flatMap EnhancedFeature.CODEC.decode(ops, feature).map { Pair(EnhancedPlacedFeature.Node(deserializeChildren, Either.right(it.first)), ops.empty()) } - } - } - } -} - object EnhancedPlacedFeature : Feature( RecordCodecBuilder.create { it.group( Codec.INT.minRange(0).fieldOf("chunk_scan_range").forGetter(Config::chunkScanRange), Codec.LONG.fieldOf("seed_mix").forGetter(Config::seedMix), - NodeCodec.fieldOf("root").forGetter(Config::root), + EnhancedPlacement.CODEC.fieldOf("root").forGetter(Config::root), ).apply(it, ::Config) } ) { - class Node(val children: List, val contents: Either>>){ - fun evaluate(context: EnhancedPlacementContext) { - evaluate(context, listOf(PlacementPos(BlockPos(context.origin.minBlockX, 0, context.origin.minBlockZ), PlacementVariableMap()))) - } - - private fun evaluate(context: EnhancedPlacementContext, positions: List) { - val actualPositions = if (contents.left().isPresent) { - contents.left().get().evaluate(context, positions) - } else { - positions - } - - if (contents.right().isPresent) { - context.place(actualPositions, contents.right().get().value()) - } - - children.forEach { - it.evaluate(context.push(), actualPositions) - } - } - } - private val emptyVariableMap = PlacementVariableMap() + fun configure( + chunkScanRange: Int, + seedMix: Long, + root: EnhancedPlacement + ): PlacedFeature { + return PlacedFeature(Holder.direct(ConfiguredFeature(EnhancedPlacedFeature, Config(chunkScanRange, seedMix, root))), listOf()) + } + class Config( val chunkScanRange: Int, val seedMix: Long, - val root: Node, + val root: EnhancedPlacement, ) : FeatureConfiguration { private class GeneratedChunk : EnhancedPlacementContext.Placer { private data class Placement(val context: EnhancedPlacementContext, val positions: ObjectRBTreeSet, val feature: EnhancedFeature.Configured<*, *>) @@ -215,7 +130,7 @@ object EnhancedPlacedFeature : Feature( val chunk = GeneratedChunk() val enhancedContext = EnhancedPlacementContext(context.level(), context.chunkGenerator(), random, chunkPos, chunk) - root.evaluate(enhancedContext) + root.evaluate(enhancedContext, listOf(PlacementPos(BlockPos(chunkPos.minBlockX, 0, chunkPos.minBlockZ), PlacementVariableMap()))) return chunk } @@ -245,91 +160,4 @@ object EnhancedPlacedFeature : Feature( override fun place(context: FeaturePlaceContext): Boolean { return context.config().place(context) } - - class Builder { - private val root: Builder? - private val children = ArrayList() - private val contents: Either>> - - constructor() : this(EnhancedPlacementModifier.Passthrough) - - constructor(root: EnhancedPlacementModifier) { - this.root = null - this.contents = Either.left(root) - } - - constructor(root: PlacementModifier) : this(EnhancedPlacementModifier.Wrapper(root)) - - constructor(root: Holder>) { - this.root = null - this.contents = Either.right(root) - } - - constructor(root: EnhancedFeature.Configured<*, *>) { - this.root = null - this.contents = Either.right(Holder.direct(root)) - } - - private constructor(parent: Builder, root: PlacementModifier) : this(parent, EnhancedPlacementModifier.Wrapper(root)) - - private constructor(parent: Builder, root: EnhancedPlacementModifier) { - this.root = parent - this.contents = Either.left(root) - } - - private constructor(parent: Builder, root: Holder>) { - this.root = parent - this.contents = Either.right(root) - } - - private constructor(parent: Builder, root: EnhancedFeature.Configured<*, *>) { - this.root = parent - this.contents = Either.right(Holder.direct(root)) - } - - fun then(action: PlacementModifier): Builder { - return Builder(root ?: this, action).also(children::add) - } - - fun then(action: EnhancedPlacementModifier): Builder { - return Builder(root ?: this, action).also(children::add) - } - - fun then(action: EnhancedFeature.Configured<*, *>): Builder { - return Builder(root ?: this, action).also(children::add) - } - - fun then(action: Holder>): Builder { - return Builder(root ?: this, action).also(children::add) - } - - @JvmName("thenVanilla") - fun then(action: ConfiguredFeature<*, *>): Builder { - return then(EnhancedFeature.Wrapper.configure(action)) - } - - @JvmName("thenVanilla") - fun then(action: Holder>): Builder { - return then(EnhancedFeature.Wrapper.configure(action)) - } - - inline fun fork(configurator: Builder.() -> Unit): Builder { - configurator(this) - return this - } - - private fun buildNode(): Node { - return Node(children.map { it.buildNode() }, contents) - } - - fun build( - chunkScanRange: Int, - seedMix: Long, - ): PlacedFeature { - if (root != null) - return root.build(chunkScanRange, seedMix) - - return PlacedFeature(Holder.direct(ConfiguredFeature(EnhancedPlacedFeature, Config(chunkScanRange, seedMix, buildNode()))), listOf()) - } - } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/EnhancedPlacementContext.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/EnhancedPlacementContext.kt index 68beaeff6..bd3013789 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/EnhancedPlacementContext.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/EnhancedPlacementContext.kt @@ -1,6 +1,5 @@ package ru.dbotthepony.mc.otm.worldgen -import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap import net.minecraft.core.BlockPos import net.minecraft.util.RandomSource import net.minecraft.world.level.ChunkPos @@ -9,10 +8,8 @@ import net.minecraft.world.level.chunk.ChunkGenerator import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration import net.minecraft.world.level.levelgen.placement.PlacementContext -import ru.dbotthepony.kommons.util.KOptional import ru.dbotthepony.mc.otm.worldgen.feature.EnhancedFeature import java.util.* -import kotlin.collections.HashMap class EnhancedPlacementContext { fun interface Placer { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/Ext.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/Ext.kt index f44556fef..0da07df44 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/Ext.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/Ext.kt @@ -1,12 +1,15 @@ package ru.dbotthepony.mc.otm.worldgen import net.minecraft.core.BlockPos +import net.minecraft.core.Holder +import net.minecraft.world.level.levelgen.feature.ConfiguredFeature import net.minecraft.world.level.levelgen.placement.PlacementModifier import ru.dbotthepony.mc.otm.core.collect.Vec3iHashStrategy -import ru.dbotthepony.mc.otm.worldgen.placement.EnhancedPlacementModifier +import ru.dbotthepony.mc.otm.worldgen.feature.EnhancedFeature +import ru.dbotthepony.mc.otm.worldgen.placement.EnhancedPlacement -fun PlacementModifier.wrap(): EnhancedPlacementModifier { - return EnhancedPlacementModifier.Wrapper(this) +fun PlacementModifier.wrap(): EnhancedPlacement { + return EnhancedPlacement.Wrapper(this) } data class PlacementPos(val pos: BlockPos, val variables: PlacementVariableMap) : Comparable { @@ -14,3 +17,9 @@ data class PlacementPos(val pos: BlockPos, val variables: PlacementVariableMap) return Vec3iHashStrategy.compare(pos, other.pos) } } + +@JvmName("placement") +fun Holder>.placement() = EnhancedFeature.ConfiguredWrapper(this) +@JvmName("vanillaPlacement") +fun Holder>.placement() = EnhancedFeature.Wrapper.configure(this) +fun ConfiguredFeature<*, *>.placement() = EnhancedFeature.Wrapper.configure(this) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/feature/EnhancedFeature.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/feature/EnhancedFeature.kt index b731a29ae..49403adfd 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/feature/EnhancedFeature.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/feature/EnhancedFeature.kt @@ -13,6 +13,7 @@ import ru.dbotthepony.mc.otm.registry.MDeferredRegister import ru.dbotthepony.mc.otm.registry.MRegistries import ru.dbotthepony.mc.otm.worldgen.EnhancedPlacementContext import ru.dbotthepony.mc.otm.worldgen.PlacementPos +import ru.dbotthepony.mc.otm.worldgen.placement.EnhancedPlacement abstract class EnhancedFeature(codec: Codec) { abstract fun place(context: EnhancedPlacementContext, config: FC, positions: Set, allPositions: Set): Boolean @@ -21,10 +22,30 @@ abstract class EnhancedFeature(codec: Codec) { fun place(context: EnhancedPlacementContext, positions: Set, allPositions: Set): Boolean { return feature.place(context, config, positions, allPositions) } + + fun placement(): ConfiguredWrapper { + return ConfiguredWrapper(Holder.direct(this)) + } + } + + data class ConfiguredWrapper(val configured: Holder>) : EnhancedPlacement { + override fun evaluate(context: EnhancedPlacementContext, positions: List): List { + context.place(positions, configured.value()) + return positions + } + + override val type: EnhancedPlacement.Type<*> + get() = Companion + + companion object : EnhancedPlacement.Type { + override val codec: MapCodec by lazy { + CODEC.xmap(::ConfiguredWrapper, ConfiguredWrapper::configured).fieldOf("feature") + } + } } val codec: MapCodec> = codec.fieldOf("config").xmap({ Configured(this, it) }, { it.config }) - fun configure(config: FC) = Configured(this, config) + fun configure(config: FC) = Configured(this, config).placement() object Wrapper : EnhancedFeature>>(ConfiguredFeature.CODEC) { override fun place( diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/EllipsoidPlacement.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/EllipsoidPlacement.kt index 686193663..069423002 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/EllipsoidPlacement.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/EllipsoidPlacement.kt @@ -14,7 +14,6 @@ import ru.dbotthepony.mc.otm.core.collect.Vec3iHashStrategy import ru.dbotthepony.mc.otm.registry.data.MPlacementModifiers import ru.dbotthepony.mc.otm.worldgen.EnhancedPlacementContext import ru.dbotthepony.mc.otm.worldgen.PlacementPos -import ru.dbotthepony.mc.otm.worldgen.PlacementVariableMap import java.util.stream.Stream /** @@ -55,7 +54,7 @@ data class EllipsoidPlacement( * Ellipsoid size sampler on Y axis */ val yLength: FloatProvider, -) : PlacementModifier(), EnhancedPlacementModifier { +) : PlacementModifier(), EnhancedPlacement { init { require(xLength.minValue >= 1f) { "Bad ellipsoid x minimal size: $xLength" } require(zLength.minValue >= 1f) { "Bad ellipsoid z minimal size: $zLength" } @@ -113,14 +112,14 @@ data class EllipsoidPlacement( return result } - override val type: EnhancedPlacementModifier.Type<*> + override val type: EnhancedPlacement.Type<*> get() = Companion override fun type(): PlacementModifierType<*> { return MPlacementModifiers.ELLIPSOID_PLACEMENT } - companion object : EnhancedPlacementModifier.Type { + companion object : EnhancedPlacement.Type { val CODEC: MapCodec by lazy { RecordCodecBuilder.mapCodec { it.group( diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/EnhancedChainPlacement.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/EnhancedChainPlacement.kt index 0c79d21c8..51ccf1fa6 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/EnhancedChainPlacement.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/EnhancedChainPlacement.kt @@ -3,31 +3,37 @@ package ru.dbotthepony.mc.otm.worldgen.placement import com.google.common.collect.ImmutableList import com.mojang.serialization.Codec import com.mojang.serialization.MapCodec -import net.minecraft.core.BlockPos -import net.minecraft.world.level.levelgen.placement.PlacementModifier import ru.dbotthepony.mc.otm.worldgen.EnhancedPlacementContext import ru.dbotthepony.mc.otm.worldgen.PlacementPos /** - * Daisy-chaining placements. Required only when using placement modifiers which operate on children list + * Chains placements, feeding results from one placement into next + * + * Each placement gets its own, new [EnhancedPlacementContext], so variables can be pushed safely into it */ class EnhancedChainPlacement( - val children: List -) : EnhancedPlacementModifier { - constructor(vararg children: EnhancedPlacementModifier) : this(ImmutableList.copyOf(children)) + val children: List +) : EnhancedPlacement { + constructor(vararg children: EnhancedPlacement) : this(ImmutableList.copyOf(children)) override fun evaluate(context: EnhancedPlacementContext, positions: List): List { + var currentContext = context var current = positions - children.forEach { current = it.evaluate(context, current) } + + children.forEach { + current = it.evaluate(context, current) + currentContext = currentContext.push() + } + return current } - override val type: EnhancedPlacementModifier.Type<*> + override val type: EnhancedPlacement.Type<*> get() = Companion - companion object : EnhancedPlacementModifier.Type { + companion object : EnhancedPlacement.Type { override val codec: MapCodec by lazy { - Codec.list(EnhancedPlacementModifier.CODEC).xmap(::EnhancedChainPlacement, EnhancedChainPlacement::children).fieldOf("children") + Codec.list(EnhancedPlacement.CODEC).xmap(::EnhancedChainPlacement, EnhancedChainPlacement::children).fieldOf("children") } } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/EnhancedCountPlacement.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/EnhancedCountPlacement.kt index 01033c1a3..c737c6aa4 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/EnhancedCountPlacement.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/EnhancedCountPlacement.kt @@ -5,7 +5,7 @@ import net.minecraft.util.valueproviders.IntProvider import ru.dbotthepony.mc.otm.worldgen.EnhancedPlacementContext import ru.dbotthepony.mc.otm.worldgen.PlacementPos -class EnhancedCountPlacement(val provider: IntProvider) : EnhancedPlacementModifier { +class EnhancedCountPlacement(val provider: IntProvider) : EnhancedPlacement { override fun evaluate(context: EnhancedPlacementContext, positions: List): List { val count = provider.sample(context.random) @@ -21,10 +21,10 @@ class EnhancedCountPlacement(val provider: IntProvider) : EnhancedPlacementModif } } - override val type: EnhancedPlacementModifier.Type<*> + override val type: EnhancedPlacement.Type<*> get() = Companion - companion object : EnhancedPlacementModifier.Type { + companion object : EnhancedPlacement.Type { override val codec: MapCodec = IntProvider.CODEC.xmap(::EnhancedCountPlacement, EnhancedCountPlacement::provider).fieldOf("count") } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/EnhancedPlacementModifier.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/EnhancedPlacement.kt similarity index 83% rename from src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/EnhancedPlacementModifier.kt rename to src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/EnhancedPlacement.kt index a71f03db2..7e270bc58 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/EnhancedPlacementModifier.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/EnhancedPlacement.kt @@ -2,8 +2,6 @@ package ru.dbotthepony.mc.otm.worldgen.placement import com.mojang.serialization.Codec import com.mojang.serialization.MapCodec -import net.minecraft.core.BlockPos -import net.minecraft.world.level.levelgen.placement.PlacementContext import net.minecraft.world.level.levelgen.placement.PlacementModifier import net.neoforged.bus.api.IEventBus import ru.dbotthepony.mc.otm.registry.MBuiltInRegistries @@ -11,18 +9,17 @@ import ru.dbotthepony.mc.otm.registry.MDeferredRegister import ru.dbotthepony.mc.otm.registry.MRegistries import ru.dbotthepony.mc.otm.worldgen.EnhancedPlacementContext import ru.dbotthepony.mc.otm.worldgen.PlacementPos -import ru.dbotthepony.mc.otm.worldgen.PlacementVariableMap import java.util.stream.Collectors -interface EnhancedPlacementModifier { - interface Type { +interface EnhancedPlacement { + interface Type { val codec: MapCodec } fun evaluate(context: EnhancedPlacementContext, positions: List): List val type: Type<*> - class Wrapper(val parent: PlacementModifier) : EnhancedPlacementModifier { + class Wrapper(val parent: PlacementModifier) : EnhancedPlacement { override fun evaluate(context: EnhancedPlacementContext, positions: List): List { return positions.stream() .flatMap { (pos, vars) -> parent.getPositions(context.vanillaContext, context.random, pos).map { PlacementPos(it, vars) } } @@ -37,7 +34,7 @@ interface EnhancedPlacementModifier { } } - object Passthrough : EnhancedPlacementModifier, Type { + object Passthrough : EnhancedPlacement, Type { override fun evaluate(context: EnhancedPlacementContext, positions: List): List { return positions } @@ -56,7 +53,7 @@ interface EnhancedPlacementModifier { registrar.register("passthrough") { Passthrough } } - val CODEC: Codec by lazy { + val CODEC: Codec by lazy { MBuiltInRegistries.PLACEMENT_MODIFIER.byNameCodec().dispatch({ it.type }, { it.codec }) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/EnhancedSplitPlacement.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/EnhancedSplitPlacement.kt index 2ead61418..2af662d8e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/EnhancedSplitPlacement.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/EnhancedSplitPlacement.kt @@ -3,16 +3,11 @@ package ru.dbotthepony.mc.otm.worldgen.placement import com.google.common.collect.ImmutableList import com.mojang.serialization.Codec import com.mojang.serialization.MapCodec -import net.minecraft.core.BlockPos -import net.minecraft.util.RandomSource -import net.minecraft.world.level.levelgen.placement.PlacementContext +import com.mojang.serialization.codecs.RecordCodecBuilder +import net.minecraft.util.StringRepresentable import net.minecraft.world.level.levelgen.placement.PlacementModifier -import net.minecraft.world.level.levelgen.placement.PlacementModifierType -import ru.dbotthepony.mc.otm.registry.data.MPlacementModifiers import ru.dbotthepony.mc.otm.worldgen.EnhancedPlacementContext import ru.dbotthepony.mc.otm.worldgen.PlacementPos -import java.util.stream.Collectors -import java.util.stream.Stream /** * Or "shard" placement, if you will. @@ -20,22 +15,48 @@ import java.util.stream.Stream * Basically, allows multiple [PlacementModifier]s to split/branch off from provided point. */ class EnhancedSplitPlacement( - val children: List -) : EnhancedPlacementModifier { - constructor(vararg children: EnhancedPlacementModifier) : this(ImmutableList.copyOf(children)) + val mode: Mode, + val children: List, +) : EnhancedPlacement { + constructor(mode: Mode, vararg children: EnhancedPlacement) : this(mode, ImmutableList.copyOf(children)) - override fun evaluate(context: EnhancedPlacementContext, positions: List): List { - val result = ArrayList() - children.forEach { result.addAll(it.evaluate(context, positions)) } - return result + enum class Mode : StringRepresentable { + COMBINE, + FORK; + + private val lname = name.lowercase() + + override fun getSerializedName(): String { + return lname + } + + companion object { + val CODEC: Codec = StringRepresentable.fromEnum(::values) + } } - override val type: EnhancedPlacementModifier.Type<*> + override fun evaluate(context: EnhancedPlacementContext, positions: List): List { + if (mode == Mode.COMBINE) { + val result = ArrayList() + children.forEach { result.addAll(it.evaluate(context.push(), positions)) } + return result + } else { + children.forEach { it.evaluate(context.push(), positions) } + return positions + } + } + + override val type: EnhancedPlacement.Type<*> get() = Companion - companion object : EnhancedPlacementModifier.Type { + companion object : EnhancedPlacement.Type { override val codec: MapCodec by lazy { - Codec.list(EnhancedPlacementModifier.CODEC).xmap(::EnhancedSplitPlacement, EnhancedSplitPlacement::children).fieldOf("children") + RecordCodecBuilder.mapCodec { + it.group( + Mode.CODEC.fieldOf("mode").forGetter(EnhancedSplitPlacement::mode), + Codec.list(EnhancedPlacement.CODEC).fieldOf("children").forGetter(EnhancedSplitPlacement::children), + ).apply(it, ::EnhancedSplitPlacement) + } } } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/WormPlacement.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/WormPlacement.kt index 64bd6291b..7886972a3 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/WormPlacement.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/WormPlacement.kt @@ -13,7 +13,6 @@ 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 ru.dbotthepony.mc.otm.core.addAll import ru.dbotthepony.mc.otm.core.math.Vector import ru.dbotthepony.mc.otm.core.math.angleDifference import ru.dbotthepony.mc.otm.core.math.normalizeAngle @@ -46,7 +45,7 @@ class WormPlacement( val initialAngleXY: FloatProvider = DEFAULT_INITIAL_ANGLE_XY, val maxTravelDown: Int = Int.MAX_VALUE, val maxTravelUp: Int = Int.MAX_VALUE, -) : PlacementModifier(), EnhancedPlacementModifier { +) : PlacementModifier(), EnhancedPlacement { private inner class Worm(private val random: RandomSource, private var position: Vector) { private var remainingDistance = length.sample(random) private var xzRotation = random.nextDouble(-PI, PI) @@ -165,7 +164,7 @@ class WormPlacement( } } - override val type: EnhancedPlacementModifier.Type<*> + override val type: EnhancedPlacement.Type<*> get() = Companion override fun getPositions(context: PlacementContext, random: RandomSource, center: BlockPos): Stream { @@ -176,7 +175,7 @@ class WormPlacement( return MPlacementModifiers.WORM_PLACEMENT } - companion object : EnhancedPlacementModifier.Type { + companion object : EnhancedPlacement.Type { private fun increment(value: Float): Float { var i = 1f