Add BooleanProvider.BiasedLinear

This commit is contained in:
DBotThePony 2025-03-08 11:06:35 +07:00
parent a89371007f
commit 01054a05d2
Signed by: DBot
GPG Key ID: DCC23B5715498507
2 changed files with 59 additions and 13 deletions

View File

@ -7,9 +7,6 @@ import net.minecraft.resources.ResourceKey
import net.minecraft.tags.BiomeTags import net.minecraft.tags.BiomeTags
import net.minecraft.tags.BlockTags import net.minecraft.tags.BlockTags
import net.minecraft.util.valueproviders.ClampedNormalFloat import net.minecraft.util.valueproviders.ClampedNormalFloat
import net.minecraft.util.valueproviders.ClampedNormalInt
import net.minecraft.util.valueproviders.ConstantFloat
import net.minecraft.util.valueproviders.IntProvider
import net.minecraft.util.valueproviders.UniformFloat import net.minecraft.util.valueproviders.UniformFloat
import net.minecraft.util.valueproviders.UniformInt import net.minecraft.util.valueproviders.UniformInt
import net.minecraft.world.level.levelgen.GenerationStep import net.minecraft.world.level.levelgen.GenerationStep
@ -23,8 +20,6 @@ import net.minecraft.world.level.levelgen.placement.HeightRangePlacement
import net.minecraft.world.level.levelgen.placement.InSquarePlacement import net.minecraft.world.level.levelgen.placement.InSquarePlacement
import net.minecraft.world.level.levelgen.placement.PlacedFeature import net.minecraft.world.level.levelgen.placement.PlacedFeature
import net.minecraft.world.level.levelgen.placement.RarityFilter import net.minecraft.world.level.levelgen.placement.RarityFilter
import net.minecraft.world.level.levelgen.structure.templatesystem.AlwaysTrueTest
import net.minecraft.world.level.levelgen.structure.templatesystem.BlockStateMatchTest
import net.minecraft.world.level.levelgen.structure.templatesystem.TagMatchTest import net.minecraft.world.level.levelgen.structure.templatesystem.TagMatchTest
import net.neoforged.neoforge.common.world.BiomeModifier import net.neoforged.neoforge.common.world.BiomeModifier
import net.neoforged.neoforge.registries.NeoForgeRegistries import net.neoforged.neoforge.registries.NeoForgeRegistries
@ -130,7 +125,7 @@ fun registerPlacedFeatures(context: BootstrapContext<PlacedFeature>) {
) )
), ),
wormLength = UniformInt.of(40, 200), wormLength = UniformInt.of(40, 200),
wormTurnChance = BooleanProvider.Uniform(4), wormTurnChance = BooleanProvider.BiasedLinear(0.6f, 4),
wormTurnXY = WormPlacement.normalDistributedTurnRate(60f), wormTurnXY = WormPlacement.normalDistributedTurnRate(60f),
wormTurnXZ = WormPlacement.normalDistributedTurnRate(60f), wormTurnXZ = WormPlacement.normalDistributedTurnRate(60f),
) )

View File

@ -7,7 +7,7 @@ import net.minecraft.util.RandomSource
import net.neoforged.bus.api.IEventBus import net.neoforged.bus.api.IEventBus
import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.core.ResourceLocation import ru.dbotthepony.mc.otm.core.ResourceLocation
import ru.dbotthepony.mc.otm.data.codec.minRange import ru.dbotthepony.mc.otm.data.codec.inRange
import ru.dbotthepony.mc.otm.registry.MDeferredRegister import ru.dbotthepony.mc.otm.registry.MDeferredRegister
import ru.dbotthepony.mc.otm.registry.RegistryDelegate import ru.dbotthepony.mc.otm.registry.RegistryDelegate
@ -23,7 +23,12 @@ interface BooleanProvider {
fun sample(random: RandomSource): Boolean fun sample(random: RandomSource): Boolean
} }
class Uniform(val chance: Int) : BooleanProvider, Instance { /**
* Each time boolean is sampled, there is a fixed chance for it to test true
*/
class Unbiased(val chance: Float) : BooleanProvider, Instance {
constructor(chance: Int) : this(1f / chance)
override fun instance(): Instance { override fun instance(): Instance {
return this return this
} }
@ -32,12 +37,57 @@ interface BooleanProvider {
get() = Companion get() = Companion
override fun sample(random: RandomSource): Boolean { override fun sample(random: RandomSource): Boolean {
return random.nextInt(chance) == 0 return random.nextFloat() <= chance
} }
companion object : Type<Uniform> { companion object : Type<Unbiased> {
override val codec: MapCodec<Uniform> = RecordCodecBuilder.mapCodec { override val codec: MapCodec<Unbiased> = RecordCodecBuilder.mapCodec {
it.group(Codec.INT.minRange(1).fieldOf("once_every").forGetter(Uniform::chance)).apply(it, ::Uniform) it.group(Codec.FLOAT.inRange(0f, 1f).fieldOf("chance").forGetter(Unbiased::chance)).apply(it, ::Unbiased)
}
}
}
/**
* Successful roll chance is specified as follows:
* ```
* base_chance * failures
* ```
*
* `failures` starts at 1, and increases each time roll failed, eventually reaching 100%
* if no successful rolls have been made.
*
* Once roll is successful, `failures` is reset back to 1.
*/
class BiasedLinear(val baseChance: Float) : BooleanProvider {
constructor(middle: Float, at: Int) : this(middle / at)
private class I(private val baseChance: Float) : Instance {
var lastSuccess = 1f
override fun sample(random: RandomSource): Boolean {
val success = random.nextFloat() <= lastSuccess * baseChance
if (success)
lastSuccess = 1f
else
lastSuccess += 1f
return success
}
}
override fun instance(): Instance {
return I(baseChance)
}
override val type: Type<*>
get() = Companion
companion object : Type<BiasedLinear> {
override val codec: MapCodec<BiasedLinear> = RecordCodecBuilder.mapCodec {
it.group(
Codec.FLOAT.inRange(0f, 1f).fieldOf("base_chance").forGetter(BiasedLinear::baseChance),
).apply(it, ::BiasedLinear)
} }
} }
} }
@ -53,7 +103,8 @@ interface BooleanProvider {
private val registrar = MDeferredRegister(registryKey) private val registrar = MDeferredRegister(registryKey)
init { init {
registrar.register("uniform") { Uniform.Companion } registrar.register("unbiased") { Unbiased.Companion }
registrar.register("linear_bias") { BiasedLinear.Companion }
} }
val CODEC: Codec<BooleanProvider> by lazy { val CODEC: Codec<BooleanProvider> by lazy {