Use sets for block positions instead of lists

it makes no sense to give same position twice
This commit is contained in:
DBotThePony 2025-03-24 19:07:25 +07:00
parent 18f9bc2654
commit bc81103e38
Signed by: DBot
GPG Key ID: DCC23B5715498507
5 changed files with 52 additions and 15 deletions

View File

@ -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<BlockPos>, Comparator<BlockPos> {
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
}
}

View File

@ -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<EnhancedPlacedFeature.Config>(
) {
class Node(val children: List<Node>, val contents: Either<EnhancedPlacementModifier, Holder<EnhancedFeature.Configured<*, *>>>){
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<BlockPos>) {
private fun evaluate(context: EnhancedPlacementContext, positions: Set<BlockPos>) {
val actualPositions = if (contents.left().isPresent) {
contents.left().get().evaluate(context, positions)
} else {
@ -137,12 +138,12 @@ object EnhancedPlacedFeature : Feature<EnhancedPlacedFeature.Config>(
val root: Node,
) : FeatureConfiguration {
private class GeneratedChunk : EnhancedPlacementContext.Placer {
private data class Placement(val context: EnhancedPlacementContext, val positions: List<BlockPos>, val feature: EnhancedFeature.Configured<*, *>)
private data class Placement(val context: EnhancedPlacementContext, val positions: Set<BlockPos>, val feature: EnhancedFeature.Configured<*, *>)
// TODO: extremely inefficient
private val placed = ArrayList<Placement>()
override fun place(context: EnhancedPlacementContext, positions: List<BlockPos>, feature: EnhancedFeature.Configured<*, *>) {
override fun place(context: EnhancedPlacementContext, positions: Set<BlockPos>, feature: EnhancedFeature.Configured<*, *>) {
placed.add(Placement(context, positions, feature))
}
@ -151,10 +152,10 @@ object EnhancedPlacedFeature : Feature<EnhancedPlacedFeature.Config>(
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
}
}

View File

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

View File

@ -14,10 +14,10 @@ import ru.dbotthepony.mc.otm.registry.MRegistries
import ru.dbotthepony.mc.otm.worldgen.EnhancedPlacementContext
abstract class EnhancedFeature<FC>(codec: Codec<FC>) {
abstract fun place(context: EnhancedPlacementContext, config: FC, positions: List<BlockPos>, allPositions: List<BlockPos>): Boolean
abstract fun place(context: EnhancedPlacementContext, config: FC, positions: Set<BlockPos>, allPositions: Set<BlockPos>): Boolean
data class Configured<F : EnhancedFeature<FC>, FC>(val feature: F, val config: FC) {
fun place(context: EnhancedPlacementContext, positions: List<BlockPos>, allPositions: List<BlockPos>): Boolean {
fun place(context: EnhancedPlacementContext, positions: Set<BlockPos>, allPositions: Set<BlockPos>): Boolean {
return feature.place(context, config, positions, allPositions)
}
}
@ -29,8 +29,8 @@ abstract class EnhancedFeature<FC>(codec: Codec<FC>) {
override fun place(
context: EnhancedPlacementContext,
config: Holder<ConfiguredFeature<*, *>>,
positions: List<BlockPos>,
allPositions: List<BlockPos>
positions: Set<BlockPos>,
allPositions: Set<BlockPos>
): Boolean {
var any = false
positions.forEach { any = config.value().place(context.level, context.generator, context.random, it) || any }

View File

@ -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<T : EnhancedPlacementModifier> {
val codec: MapCodec<T>
}
fun evaluate(context: EnhancedPlacementContext, positions: List<BlockPos>): List<BlockPos>
fun evaluate(context: EnhancedPlacementContext, positions: Set<BlockPos>): Set<BlockPos>
val type: Type<*>
class Wrapper(val parent: PlacementModifier) : EnhancedPlacementModifier {
override fun evaluate(context: EnhancedPlacementContext, positions: List<BlockPos>): List<BlockPos> {
return positions.stream().flatMap { parent.getPositions(context.vanillaContext, context.random, it) }.toList()
override fun evaluate(context: EnhancedPlacementContext, positions: Set<BlockPos>): Set<BlockPos> {
return positions.stream()
.flatMap { parent.getPositions(context.vanillaContext, context.random, it) }
.collect(Collectors.toCollection { ObjectLinkedOpenCustomHashSet(BlockPosHashStrategy) })
}
override val type: Type<*>