diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/collect/BlockPosHashStrategy.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/collect/BlockPosHashStrategy.kt new file mode 100644 index 000000000..ba32c3ad8 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/collect/BlockPosHashStrategy.kt @@ -0,0 +1,30 @@ +package ru.dbotthepony.mc.otm.core.collect + +import it.unimi.dsi.fastutil.Hash +import it.unimi.dsi.fastutil.HashCommon +import net.minecraft.core.BlockPos + +object BlockPosHashStrategy : Hash.Strategy, Comparator { + override fun equals(a: BlockPos?, b: BlockPos?): Boolean { + return a == b + } + + override fun hashCode(o: BlockPos?): Int { + o ?: return 0 + return HashCommon.murmurHash3(o.x.toLong().and(1 shl 26 - 1) or o.z.toLong().and(1 shl 26 - 1).shl(26) or o.y.toLong().and(1 shl 12 - 1).shl(52)).toInt() + } + + override fun compare(o1: BlockPos?, o2: BlockPos?): Int { + if (o1 == null && o2 == null) + return 0 + else if (o1 == null) + return -1 // nulls come first + else if (o2 == null) + return 1 + + var cmp = o1.x.compareTo(o2.x) + if (cmp == 0) cmp = o1.z.compareTo(o2.z) + if (cmp == 0) cmp = o1.y.compareTo(o2.y) + return cmp + } +} 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 5cac733d5..5b8b88015 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/EnhancedPlacedFeature.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/EnhancedPlacedFeature.kt @@ -10,6 +10,7 @@ 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 net.minecraft.Util import net.minecraft.core.BlockPos import net.minecraft.core.Holder @@ -111,10 +112,10 @@ object EnhancedPlacedFeature : Feature( ) { class Node(val children: List, val contents: Either>>){ fun evaluate(context: EnhancedPlacementContext) { - evaluate(context, listOf(BlockPos(context.origin.minBlockX, 0, context.origin.minBlockZ))) + evaluate(context, setOf(BlockPos(context.origin.minBlockX, 0, context.origin.minBlockZ))) } - private fun evaluate(context: EnhancedPlacementContext, positions: List) { + private fun evaluate(context: EnhancedPlacementContext, positions: Set) { val actualPositions = if (contents.left().isPresent) { contents.left().get().evaluate(context, positions) } else { @@ -137,12 +138,12 @@ object EnhancedPlacedFeature : Feature( val root: Node, ) : FeatureConfiguration { private class GeneratedChunk : EnhancedPlacementContext.Placer { - private data class Placement(val context: EnhancedPlacementContext, val positions: List, val feature: EnhancedFeature.Configured<*, *>) + private data class Placement(val context: EnhancedPlacementContext, val positions: Set, val feature: EnhancedFeature.Configured<*, *>) // TODO: extremely inefficient private val placed = ArrayList() - override fun place(context: EnhancedPlacementContext, positions: List, feature: EnhancedFeature.Configured<*, *>) { + override fun place(context: EnhancedPlacementContext, positions: Set, feature: EnhancedFeature.Configured<*, *>) { placed.add(Placement(context, positions, feature)) } @@ -151,10 +152,10 @@ object EnhancedPlacedFeature : Feature( val pos = ChunkPos(context.origin()) for ((eContext, positions, feature) in placed) { - val filtered = positions.filter { SectionPos.blockToSectionCoord(it.x) == pos.x && SectionPos.blockToSectionCoord(it.z) == pos.z } + val filtered = positions.filter { SectionPos.blockToSectionCoord(it.x) == pos.x && SectionPos.blockToSectionCoord(it.z) == pos.z }.toTypedArray() if (filtered.isNotEmpty()) { - any = feature.place(eContext, filtered, positions) || any + any = feature.place(eContext, ObjectArraySet.ofUnchecked(*filtered), positions) || any } } 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 3cdd33f4d..1d77163ab 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/EnhancedPlacementContext.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/EnhancedPlacementContext.kt @@ -15,7 +15,7 @@ import kotlin.collections.HashMap class EnhancedPlacementContext { fun interface Placer { - fun place(context: EnhancedPlacementContext, positions: List, feature: EnhancedFeature.Configured<*, *>) + fun place(context: EnhancedPlacementContext, positions: Set, feature: EnhancedFeature.Configured<*, *>) } val level: WorldGenLevel @@ -79,7 +79,7 @@ class EnhancedPlacementContext { return EnhancedPlacementContext(this) } - fun place(positions: List, feature: EnhancedFeature.Configured<*, *>) { + fun place(positions: Set, feature: EnhancedFeature.Configured<*, *>) { placer.place(this, positions, feature) } 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 606eb5ce4..89b4fd343 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 @@ -14,10 +14,10 @@ import ru.dbotthepony.mc.otm.registry.MRegistries import ru.dbotthepony.mc.otm.worldgen.EnhancedPlacementContext abstract class EnhancedFeature(codec: Codec) { - abstract fun place(context: EnhancedPlacementContext, config: FC, positions: List, allPositions: List): Boolean + abstract fun place(context: EnhancedPlacementContext, config: FC, positions: Set, allPositions: Set): Boolean data class Configured, FC>(val feature: F, val config: FC) { - fun place(context: EnhancedPlacementContext, positions: List, allPositions: List): Boolean { + fun place(context: EnhancedPlacementContext, positions: Set, allPositions: Set): Boolean { return feature.place(context, config, positions, allPositions) } } @@ -29,8 +29,8 @@ abstract class EnhancedFeature(codec: Codec) { override fun place( context: EnhancedPlacementContext, config: Holder>, - positions: List, - allPositions: List + positions: Set, + allPositions: Set ): Boolean { var any = false positions.forEach { any = config.value().place(context.level, context.generator, context.random, it) || any } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/EnhancedPlacementModifier.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/EnhancedPlacementModifier.kt index e2f1b81d0..6f7ac934a 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/EnhancedPlacementModifier.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/placement/EnhancedPlacementModifier.kt @@ -2,25 +2,31 @@ package ru.dbotthepony.mc.otm.worldgen.placement import com.mojang.serialization.Codec import com.mojang.serialization.MapCodec +import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenCustomHashSet +import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet import net.minecraft.core.BlockPos import net.minecraft.world.level.levelgen.placement.PlacementModifier import net.neoforged.bus.api.IEventBus +import ru.dbotthepony.mc.otm.core.collect.BlockPosHashStrategy import ru.dbotthepony.mc.otm.registry.MBuiltInRegistries import ru.dbotthepony.mc.otm.registry.MDeferredRegister import ru.dbotthepony.mc.otm.registry.MRegistries import ru.dbotthepony.mc.otm.worldgen.EnhancedPlacementContext +import java.util.stream.Collectors interface EnhancedPlacementModifier { interface Type { val codec: MapCodec } - fun evaluate(context: EnhancedPlacementContext, positions: List): List + fun evaluate(context: EnhancedPlacementContext, positions: Set): Set val type: Type<*> class Wrapper(val parent: PlacementModifier) : EnhancedPlacementModifier { - override fun evaluate(context: EnhancedPlacementContext, positions: List): List { - return positions.stream().flatMap { parent.getPositions(context.vanillaContext, context.random, it) }.toList() + override fun evaluate(context: EnhancedPlacementContext, positions: Set): Set { + return positions.stream() + .flatMap { parent.getPositions(context.vanillaContext, context.random, it) } + .collect(Collectors.toCollection { ObjectLinkedOpenCustomHashSet(BlockPosHashStrategy) }) } override val type: Type<*>