Use sets only for final placements, use lists for intermediate

This commit is contained in:
DBotThePony 2025-03-24 20:16:57 +07:00
parent 78c0a5d717
commit ab6e3ad87f
Signed by: DBot
GPG Key ID: DCC23B5715498507
3 changed files with 12 additions and 10 deletions

View File

@ -11,6 +11,7 @@ import com.mojang.serialization.DynamicOps
import com.mojang.serialization.codecs.RecordCodecBuilder import com.mojang.serialization.codecs.RecordCodecBuilder
import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream
import it.unimi.dsi.fastutil.objects.ObjectArraySet import it.unimi.dsi.fastutil.objects.ObjectArraySet
import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet
import net.minecraft.Util import net.minecraft.Util
import net.minecraft.core.BlockPos import net.minecraft.core.BlockPos
import net.minecraft.core.Holder import net.minecraft.core.Holder
@ -24,6 +25,7 @@ import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfigur
import net.minecraft.world.level.levelgen.placement.PlacedFeature import net.minecraft.world.level.levelgen.placement.PlacedFeature
import net.minecraft.world.level.levelgen.placement.PlacementModifier import net.minecraft.world.level.levelgen.placement.PlacementModifier
import ru.dbotthepony.kommons.util.XXHash64 import ru.dbotthepony.kommons.util.XXHash64
import ru.dbotthepony.mc.otm.core.collect.BlockPosHashStrategy
import ru.dbotthepony.mc.otm.core.util.GJRAND64RandomSource import ru.dbotthepony.mc.otm.core.util.GJRAND64RandomSource
import ru.dbotthepony.mc.otm.data.codec.minRange import ru.dbotthepony.mc.otm.data.codec.minRange
import ru.dbotthepony.mc.otm.worldgen.feature.EnhancedFeature import ru.dbotthepony.mc.otm.worldgen.feature.EnhancedFeature
@ -112,10 +114,10 @@ object EnhancedPlacedFeature : Feature<EnhancedPlacedFeature.Config>(
) { ) {
class Node(val children: List<Node>, val contents: Either<EnhancedPlacementModifier, Holder<EnhancedFeature.Configured<*, *>>>){ class Node(val children: List<Node>, val contents: Either<EnhancedPlacementModifier, Holder<EnhancedFeature.Configured<*, *>>>){
fun evaluate(context: EnhancedPlacementContext) { fun evaluate(context: EnhancedPlacementContext) {
evaluate(context, setOf(BlockPos(context.origin.minBlockX, 0, context.origin.minBlockZ))) evaluate(context, listOf(BlockPos(context.origin.minBlockX, 0, context.origin.minBlockZ)))
} }
private fun evaluate(context: EnhancedPlacementContext, positions: Set<BlockPos>) { private fun evaluate(context: EnhancedPlacementContext, positions: List<BlockPos>) {
val actualPositions = if (contents.left().isPresent) { val actualPositions = if (contents.left().isPresent) {
contents.left().get().evaluate(context, positions) contents.left().get().evaluate(context, positions)
} else { } else {
@ -143,8 +145,8 @@ object EnhancedPlacedFeature : Feature<EnhancedPlacedFeature.Config>(
// TODO: extremely inefficient // TODO: extremely inefficient
private val placed = ArrayList<Placement>() private val placed = ArrayList<Placement>()
override fun place(context: EnhancedPlacementContext, positions: Set<BlockPos>, feature: EnhancedFeature.Configured<*, *>) { override fun place(context: EnhancedPlacementContext, positions: List<BlockPos>, feature: EnhancedFeature.Configured<*, *>) {
placed.add(Placement(context, positions, feature)) placed.add(Placement(context, ObjectRBTreeSet(BlockPosHashStrategy).also { it.addAll(positions) }, feature))
} }
fun place(context: FeaturePlaceContext<*>): Boolean { fun place(context: FeaturePlaceContext<*>): Boolean {

View File

@ -15,7 +15,7 @@ import kotlin.collections.HashMap
class EnhancedPlacementContext { class EnhancedPlacementContext {
fun interface Placer { fun interface Placer {
fun place(context: EnhancedPlacementContext, positions: Set<BlockPos>, feature: EnhancedFeature.Configured<*, *>) fun place(context: EnhancedPlacementContext, positions: List<BlockPos>, feature: EnhancedFeature.Configured<*, *>)
} }
val level: WorldGenLevel val level: WorldGenLevel
@ -79,7 +79,7 @@ class EnhancedPlacementContext {
return EnhancedPlacementContext(this) return EnhancedPlacementContext(this)
} }
fun place(positions: Set<BlockPos>, feature: EnhancedFeature.Configured<*, *>) { fun place(positions: List<BlockPos>, feature: EnhancedFeature.Configured<*, *>) {
placer.place(this, positions, feature) placer.place(this, positions, feature)
} }

View File

@ -20,15 +20,15 @@ interface EnhancedPlacementModifier {
val codec: MapCodec<T> val codec: MapCodec<T>
} }
fun evaluate(context: EnhancedPlacementContext, positions: Set<BlockPos>): Set<BlockPos> fun evaluate(context: EnhancedPlacementContext, positions: List<BlockPos>): List<BlockPos>
val type: Type<*> val type: Type<*>
class Wrapper(val parent: PlacementModifier) : EnhancedPlacementModifier { class Wrapper(val parent: PlacementModifier) : EnhancedPlacementModifier {
override fun evaluate(context: EnhancedPlacementContext, positions: Set<BlockPos>): Set<BlockPos> { override fun evaluate(context: EnhancedPlacementContext, positions: List<BlockPos>): List<BlockPos> {
return positions.stream() return positions.stream()
.flatMap { parent.getPositions(context.vanillaContext, context.random, it) } .flatMap { parent.getPositions(context.vanillaContext, context.random, it) }
// use Red-Black tree set instead of AVL tree set because we are write-intense // use Red-Black tree set instead of AVL tree set because we are write-intense
.collect(Collectors.toCollection { ObjectRBTreeSet(BlockPosHashStrategy) }) .collect(Collectors.toCollection(::ArrayList))
} }
override val type: Type<*> override val type: Type<*>
@ -40,7 +40,7 @@ interface EnhancedPlacementModifier {
} }
object Passthrough : EnhancedPlacementModifier, Type<Passthrough> { object Passthrough : EnhancedPlacementModifier, Type<Passthrough> {
override fun evaluate(context: EnhancedPlacementContext, positions: Set<BlockPos>): Set<BlockPos> { override fun evaluate(context: EnhancedPlacementContext, positions: List<BlockPos>): List<BlockPos> {
return positions return positions
} }