Revert "Remove otmRandom"
This reverts commit 5a016bef
The way OTM uses random generator in its code will quickly cause LCG used in Minecraft to show its bias
because LCG in minecraft samples its highest 48 bits, which gives us at best 2^16 period in the lowest bit returned by LCG.
Which it doesn't sound bad, it quickly causes RNG become biased the quicker/more it is sampled on each tick, especially considering
some may use `level.random.nextInt(chance) == 0` to determine chance of something happening,
which will get extremely biased on heavy RNG congested environment
If we avoid sampling Level's generator this much, we won't suffer from bias in our own code, as well as avoid biasing other mods this much.
The "2^16 period" problem is also might be the reason why Entities get their own instance of RandomSource, and Mob Goals use random exactly the way described above (`nextInt(chance)`), which can and will suffer from bias the moment mob exists in world for more than 2^16 ticks (but actual bias will happen sooner because RNG is not sampled only once per tick, obviously)
This commit is contained in:
parent
bc5ad7f37b
commit
b7b2b8095c
19
src/main/java/ru/dbotthepony/mc/otm/mixin/LevelMixin.java
Normal file
19
src/main/java/ru/dbotthepony/mc/otm/mixin/LevelMixin.java
Normal file
@ -0,0 +1,19 @@
|
||||
package ru.dbotthepony.mc.otm.mixin;
|
||||
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.neoforged.fml.ModList;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import ru.dbotthepony.mc.otm.core.IMatteryLevel;
|
||||
import ru.dbotthepony.mc.otm.core.util.GJRAND64RandomSource;
|
||||
|
||||
@Mixin(Level.class)
|
||||
public abstract class LevelMixin implements IMatteryLevel {
|
||||
private final RandomSource otm_random = ModList.get().isLoaded("better_random") ? null : new GJRAND64RandomSource();
|
||||
|
||||
@Override
|
||||
public @Nullable RandomSource getOtmRandom() {
|
||||
return otm_random;
|
||||
}
|
||||
}
|
@ -8,6 +8,7 @@ import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import ru.dbotthepony.mc.otm.player.IMatteryPlayer;
|
||||
import ru.dbotthepony.mc.otm.core.IMatteryLevel;
|
||||
import ru.dbotthepony.mc.otm.registry.game.MSoundEvents;
|
||||
|
||||
@Mixin(AbstractHurtingProjectile.class)
|
||||
@ -24,7 +25,7 @@ public class MixinAbstractHurtingProjectile {
|
||||
AbstractHurtingProjectile proj = (AbstractHurtingProjectile)(Object)this;
|
||||
|
||||
if (cap.isAndroid() && proj.getOwner() != entity) {
|
||||
entity.level().playSound(entity, proj.blockPosition(), MSoundEvents.INSTANCE.getANDROID_PROJ_PARRY(), SoundSource.PLAYERS, 1.0f, 0.95f + entity.level().getRandom().nextFloat() * 0.1f);
|
||||
entity.level().playSound(entity, proj.blockPosition(), MSoundEvents.INSTANCE.getANDROID_PROJ_PARRY(), SoundSource.PLAYERS, 1.0f, 0.95f + ((IMatteryLevel) entity.level()).getOtmRandom().nextFloat() * 0.1f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ import ru.dbotthepony.mc.otm.core.math.getSphericalBlockPositions
|
||||
import ru.dbotthepony.mc.otm.core.math.times
|
||||
import ru.dbotthepony.mc.otm.core.nbt.map
|
||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||
import ru.dbotthepony.mc.otm.core.random
|
||||
import ru.dbotthepony.mc.otm.core.otmRandom
|
||||
import ru.dbotthepony.mc.otm.isClient
|
||||
import ru.dbotthepony.mc.otm.matter.MatterManager
|
||||
import ru.dbotthepony.mc.otm.registry.MDamageTypes
|
||||
@ -271,7 +271,7 @@ class BlackHoleBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mattery
|
||||
}
|
||||
|
||||
// шанс 1% что черная дыра потеряет 0.1 MtU каждую секунду * силу гравитации дыры ^ -1
|
||||
if (level.random.nextDouble() < 0.01 * 0.05 * (1 / gravitationStrength)) {
|
||||
if (level.otmRandom.nextDouble() < 0.01 * 0.05 * (1 / gravitationStrength)) {
|
||||
this.mass += HAWKING_MASS_LOSE_STEP
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ import ru.dbotthepony.mc.otm.core.math.times
|
||||
import ru.dbotthepony.mc.otm.core.multiblock.BlockEntityTag
|
||||
import ru.dbotthepony.mc.otm.core.multiblock.MultiblockStatus
|
||||
import ru.dbotthepony.mc.otm.core.multiblock.shapedMultiblock
|
||||
import ru.dbotthepony.mc.otm.core.random
|
||||
import ru.dbotthepony.mc.otm.core.otmRandom
|
||||
import ru.dbotthepony.mc.otm.core.util.InvalidableLazy
|
||||
import ru.dbotthepony.mc.otm.menu.tech.BlackHoleGeneratorMenu
|
||||
import ru.dbotthepony.mc.otm.registry.game.MBlockEntities
|
||||
@ -86,8 +86,8 @@ class BlackHoleGeneratorBlockEntity(blockPos: BlockPos, blockState: BlockState)
|
||||
multiblock?.blockEntities(MatterHatchBlockEntity.INPUT_TAG)?.iterator()?.map { it.matter }?.toList() ?: listOf()
|
||||
}
|
||||
|
||||
val energy = CombinedProfiledEnergyStorage(FlowDirection.NONE, energyTarget::value, { level?.random })
|
||||
val matter = CombinedProfiledMatterStorage(FlowDirection.NONE, matterTarget::value, { level?.random })
|
||||
val energy = CombinedProfiledEnergyStorage(FlowDirection.NONE, energyTarget::value, { level?.otmRandom })
|
||||
val matter = CombinedProfiledMatterStorage(FlowDirection.NONE, matterTarget::value, { level?.otmRandom })
|
||||
|
||||
enum class Mode(val label: Component, val tooltip: Component) {
|
||||
TARGET_MASS(TranslatableComponent("otm.gui.black_hole_generator.sustain.mode"), TranslatableComponent("otm.gui.black_hole_generator.sustain.desc")),
|
||||
|
@ -14,7 +14,7 @@ import ru.dbotthepony.mc.otm.core.collect.map
|
||||
import ru.dbotthepony.mc.otm.core.collect.reduce
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.core.math.RelativeSide
|
||||
import ru.dbotthepony.mc.otm.core.random
|
||||
import ru.dbotthepony.mc.otm.core.otmRandom
|
||||
import ru.dbotthepony.mc.otm.core.shuffle
|
||||
import ru.dbotthepony.mc.otm.graph.GraphNodeList
|
||||
import ru.dbotthepony.mc.otm.onceServer
|
||||
@ -627,7 +627,7 @@ class EnergyCableGraph : GraphNodeList<EnergyCableBlockEntity.Node, EnergyCableG
|
||||
}
|
||||
|
||||
fun receiveEnergy(howMuch: Decimal, simulate: Boolean, fromNode: EnergyCableBlockEntity.Node, fromSide: RelativeSide): Decimal {
|
||||
livelyNodesList.shuffle(fromNode.blockEntity.level!!.random)
|
||||
livelyNodesList.shuffle(fromNode.blockEntity.level!!.otmRandom)
|
||||
|
||||
val itr = livelyNodesList.iterator()
|
||||
var received = Decimal.ZERO
|
||||
|
@ -32,7 +32,7 @@ import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
|
||||
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
||||
import ru.dbotthepony.mc.otm.container.HandlerFilter
|
||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||
import ru.dbotthepony.mc.otm.core.random
|
||||
import ru.dbotthepony.mc.otm.core.otmRandom
|
||||
import ru.dbotthepony.mc.otm.menu.decorative.CargoCrateMenu
|
||||
import ru.dbotthepony.mc.otm.registry.game.MBlockEntities
|
||||
import ru.dbotthepony.mc.otm.registry.game.MSoundEvents
|
||||
@ -71,7 +71,7 @@ class CargoCrateBlockEntity(
|
||||
|
||||
if (interactingPlayers++ == 0 && level != null && !isRemoved && level.getBlockState(blockPos).block is CargoCrateBlock) {
|
||||
level.setBlock(blockPos, blockState.setValue(CargoCrateBlock.IS_OPEN, true), Block.UPDATE_CLIENTS)
|
||||
level.playSound(null, blockPos, MSoundEvents.CARGO_CRATE_OPEN, SoundSource.BLOCKS, 1f, 0.8f + level.random.nextFloat() * 0.2f)
|
||||
level.playSound(null, blockPos, MSoundEvents.CARGO_CRATE_OPEN, SoundSource.BLOCKS, 1f, 0.8f + level.otmRandom.nextFloat() * 0.2f)
|
||||
level.gameEvent(GameEvent.CONTAINER_OPEN, blockPos, GameEvent.Context.of(blockState))
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ import ru.dbotthepony.mc.otm.config.MachinesConfig
|
||||
import ru.dbotthepony.mc.otm.container.HandlerFilter
|
||||
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.core.random
|
||||
import ru.dbotthepony.mc.otm.core.otmRandom
|
||||
import ru.dbotthepony.mc.otm.data.codec.DecimalCodec
|
||||
import ru.dbotthepony.mc.otm.data.codec.minRange
|
||||
import ru.dbotthepony.mc.otm.graph.matter.SimpleMatterNode
|
||||
@ -126,7 +126,7 @@ class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState)
|
||||
|
||||
return JobContainer.success(
|
||||
DecomposerJob(
|
||||
(level?.random?.nextDouble() ?: 1.0) <= 0.2 * upgrades.failureMultiplier,
|
||||
(level?.otmRandom?.nextDouble() ?: 1.0) <= 0.2 * upgrades.failureMultiplier,
|
||||
matter.matter,
|
||||
matter.complexity * MachinesConfig.MATTER_DECOMPOSER.workTimeMultiplier
|
||||
)
|
||||
|
@ -28,7 +28,7 @@ import ru.dbotthepony.mc.otm.container.HandlerFilter
|
||||
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
||||
import ru.dbotthepony.mc.otm.container.UpgradeContainer
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.core.random
|
||||
import ru.dbotthepony.mc.otm.core.otmRandom
|
||||
import ru.dbotthepony.mc.otm.core.registryName
|
||||
import ru.dbotthepony.mc.otm.graph.matter.MatterNode
|
||||
import ru.dbotthepony.mc.otm.matter.IMatterValue
|
||||
@ -264,7 +264,7 @@ class MatterReconstructorBlockEntity(blockPos: BlockPos, blockState: BlockState)
|
||||
return
|
||||
}
|
||||
|
||||
if (failureChance * upgrades.failureMultiplier <= 0.0 || level!!.random.nextDouble() >= failureChance * upgrades.failureMultiplier)
|
||||
if (failureChance * upgrades.failureMultiplier <= 0.0 || level!!.otmRandom.nextDouble() >= failureChance * upgrades.failureMultiplier)
|
||||
repairProgress += progressPerTick
|
||||
|
||||
energy.extractEnergy(energyConsumption * (progressPerTick / thisProgressPerTick), false)
|
||||
|
@ -24,7 +24,7 @@ import ru.dbotthepony.mc.otm.config.MachinesConfig
|
||||
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
||||
import ru.dbotthepony.mc.otm.container.HandlerFilter
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.core.random
|
||||
import ru.dbotthepony.mc.otm.core.otmRandom
|
||||
import ru.dbotthepony.mc.otm.graph.matter.MatterGraph
|
||||
import ru.dbotthepony.mc.otm.item.matter.MatterDustItem
|
||||
import ru.dbotthepony.mc.otm.menu.matter.MatterRecyclerMenu
|
||||
@ -117,7 +117,7 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState)
|
||||
stack.shrink(1)
|
||||
container.setChanged(0)
|
||||
|
||||
val actualMatter = dustMatter.matter * (0.4 + level!!.random.nextDouble() * 0.6)
|
||||
val actualMatter = dustMatter.matter * (0.4 + level!!.otmRandom.nextDouble() * 0.6)
|
||||
|
||||
return JobContainer.success(
|
||||
RecyclerJob(
|
||||
|
@ -28,7 +28,7 @@ import ru.dbotthepony.mc.otm.config.MachinesConfig
|
||||
import ru.dbotthepony.mc.otm.container.HandlerFilter
|
||||
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.core.random
|
||||
import ru.dbotthepony.mc.otm.core.otmRandom
|
||||
import ru.dbotthepony.mc.otm.data.codec.DecimalCodec
|
||||
import ru.dbotthepony.mc.otm.data.codec.minRange
|
||||
import ru.dbotthepony.mc.otm.graph.matter.MatterNode
|
||||
@ -184,7 +184,7 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
||||
task = allocation.task.id,
|
||||
matterValue = matter.matter,
|
||||
pattern = Optional.ofNullable(allocation.pattern),
|
||||
asDust = (level?.random?.nextDouble() ?: 1.0) * upgrades.failureMultiplier > (allocation.pattern?.researchPercent ?: 2.0),
|
||||
asDust = (level?.otmRandom?.nextDouble() ?: 1.0) * upgrades.failureMultiplier > (allocation.pattern?.researchPercent ?: 2.0),
|
||||
ticks = ticks,
|
||||
))
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ import ru.dbotthepony.mc.otm.container.balance
|
||||
import ru.dbotthepony.mc.otm.core.collect.filter
|
||||
import ru.dbotthepony.mc.otm.core.collect.maybe
|
||||
import ru.dbotthepony.mc.otm.core.immutableList
|
||||
import ru.dbotthepony.mc.otm.core.random
|
||||
import ru.dbotthepony.mc.otm.core.otmRandom
|
||||
import ru.dbotthepony.mc.otm.menu.tech.PoweredFurnaceMenu
|
||||
import ru.dbotthepony.mc.otm.recipe.MatteryCookingRecipe
|
||||
import ru.dbotthepony.mc.otm.recipe.MicrowaveRecipe
|
||||
@ -153,7 +153,7 @@ sealed class AbstractPoweredFurnaceBlockEntity<P : AbstractCookingRecipe, S : Ma
|
||||
recipe.getResultItem(level.registryAccess()).copyWithCount(toProcess),
|
||||
recipe.workTime * config.workTimeMultiplier,
|
||||
config.energyConsumption * toProcess,
|
||||
experience = recipe.experience.sample(level.random) * toProcess))
|
||||
experience = recipe.experience.sample(level.otmRandom) * toProcess))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,7 @@ import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage
|
||||
import ru.dbotthepony.mc.otm.player.matteryPlayer
|
||||
import ru.dbotthepony.mc.otm.config.MachinesConfig
|
||||
import ru.dbotthepony.mc.otm.core.getEntitiesInEllipsoid
|
||||
import ru.dbotthepony.mc.otm.core.otmRandom
|
||||
import ru.dbotthepony.mc.otm.core.shuffle
|
||||
import ru.dbotthepony.mc.otm.menu.tech.AndroidChargerMenu
|
||||
import ru.dbotthepony.mc.otm.registry.game.MBlockEntities
|
||||
@ -57,7 +58,7 @@ class AndroidChargerBlockEntity(blockPos: BlockPos, blockState: BlockState) : Ma
|
||||
|
||||
val ents = level.getEntitiesInEllipsoid(blockPos.center, Vec3(MachinesConfig.AndroidCharger.RADIUS_WIDTH, MachinesConfig.AndroidCharger.RADIUS_HEIGHT, MachinesConfig.AndroidCharger.RADIUS_WIDTH)) { it is Player }
|
||||
|
||||
ents.shuffle(level.random)
|
||||
ents.shuffle(level.otmRandom)
|
||||
|
||||
for ((ent) in ents) {
|
||||
val ply = (ent as Player).matteryPlayer
|
||||
|
@ -17,6 +17,7 @@ import ru.dbotthepony.mc.otm.player.matteryPlayer
|
||||
import ru.dbotthepony.mc.otm.capability.moveEnergy
|
||||
import ru.dbotthepony.mc.otm.config.MachinesConfig
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.core.otmRandom
|
||||
import ru.dbotthepony.mc.otm.core.shuffle
|
||||
import ru.dbotthepony.mc.otm.core.util.countingLazy
|
||||
import ru.dbotthepony.mc.otm.menu.tech.AndroidStationMenu
|
||||
@ -89,7 +90,7 @@ class AndroidStationBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Ma
|
||||
val y = blockPos.y.toDouble()
|
||||
val z = blockPos.z.toDouble()
|
||||
|
||||
for (ent in level.getEntitiesOfClass(ServerPlayer::class.java, AABB(x, y, z, x + 1.0, y + 2.0, z + 1.0)).shuffle(level.random)) {
|
||||
for (ent in level.getEntitiesOfClass(ServerPlayer::class.java, AABB(x, y, z, x + 1.0, y + 2.0, z + 1.0)).shuffle(level.otmRandom)) {
|
||||
if (ent.matteryPlayer.isAndroid)
|
||||
moveEnergy(energy, ent.matteryPlayer.androidEnergy, amount = energy.batteryLevel, simulate = false, ignoreFlowRestrictions = true)
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ import ru.dbotthepony.mc.otm.container.HandlerFilter
|
||||
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
||||
import ru.dbotthepony.mc.otm.core.immutableList
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.core.random
|
||||
import ru.dbotthepony.mc.otm.core.otmRandom
|
||||
import ru.dbotthepony.mc.otm.core.shuffle
|
||||
import ru.dbotthepony.mc.otm.menu.tech.BatteryBankMenu
|
||||
import ru.dbotthepony.mc.otm.registry.game.MBlockEntities
|
||||
@ -60,7 +60,7 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
|
||||
if (!howMuch.isPositive)
|
||||
return Decimal.ZERO
|
||||
|
||||
containerSlotIndices.shuffle(level!!.random)
|
||||
containerSlotIndices.shuffle(level!!.otmRandom)
|
||||
var summ = Decimal.ZERO
|
||||
var remaining = howMuch
|
||||
|
||||
|
@ -24,7 +24,7 @@ import ru.dbotthepony.mc.otm.core.math.RelativeSide
|
||||
import ru.dbotthepony.mc.otm.core.multiblock.BlockEntityTag
|
||||
import ru.dbotthepony.mc.otm.core.multiblock.IMultiblockAccess
|
||||
import ru.dbotthepony.mc.otm.core.multiblock.IMultiblockListener
|
||||
import ru.dbotthepony.mc.otm.core.random
|
||||
import ru.dbotthepony.mc.otm.core.otmRandom
|
||||
import ru.dbotthepony.mc.otm.core.util.InvalidableLazy
|
||||
import ru.dbotthepony.mc.otm.registry.game.MBlockEntities
|
||||
|
||||
@ -43,7 +43,7 @@ class EnergyInterfaceBlockEntity(
|
||||
multiblocks.keys.iterator().flatMap { it.blockEntities(TARGET).iterator() }.map { it.energyInterfaceTarget }.toList()
|
||||
}
|
||||
|
||||
val energy = CombinedProfiledEnergyStorage(FlowDirection.input(isInput), targets::value, { level?.random })
|
||||
val energy = CombinedProfiledEnergyStorage(FlowDirection.input(isInput), targets::value, { level?.otmRandom })
|
||||
|
||||
override fun onAddedToMultiblock(multiblock: IMultiblockAccess) {
|
||||
check(!isRemoved) { "Block was removed" }
|
||||
|
@ -28,7 +28,7 @@ import ru.dbotthepony.mc.otm.container.MatteryContainer
|
||||
import ru.dbotthepony.mc.otm.core.getEntitiesInEllipsoid
|
||||
import ru.dbotthepony.mc.otm.core.lookupOrThrow
|
||||
import ru.dbotthepony.mc.otm.core.math.Vector
|
||||
import ru.dbotthepony.mc.otm.core.random
|
||||
import ru.dbotthepony.mc.otm.core.otmRandom
|
||||
import ru.dbotthepony.mc.otm.core.util.countingLazy
|
||||
import ru.dbotthepony.mc.otm.item.consumables.EssenceCapsuleItem
|
||||
import ru.dbotthepony.mc.otm.item.EssenceServoItem
|
||||
@ -173,7 +173,7 @@ class EssenceStorageBlockEntity(blockPos: BlockPos, blockState: BlockState) : Ma
|
||||
|
||||
val diff = dmgPerExp - repairPoints.toFloat()
|
||||
if (diff > 0f) {
|
||||
repairPoints += if ((level?.random?.nextFloat() ?: 1f) <= diff) 1 else 0
|
||||
repairPoints += if ((level?.otmRandom?.nextFloat() ?: 1f) <= diff) 1 else 0
|
||||
}
|
||||
|
||||
experienceStored -= 1
|
||||
@ -202,7 +202,7 @@ class EssenceStorageBlockEntity(blockPos: BlockPos, blockState: BlockState) : Ma
|
||||
|
||||
level!!.playSound(null, ent.x, ent.y, ent.z,
|
||||
SoundEvents.EXPERIENCE_ORB_PICKUP, SoundSource.BLOCKS,
|
||||
0.1F, 0.5F + level!!.random.nextFloat() * 0.25F
|
||||
0.1F, 0.5F + level!!.otmRandom.nextFloat() * 0.25F
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ import ru.dbotthepony.mc.otm.container.HandlerFilter
|
||||
import ru.dbotthepony.mc.otm.container.balance
|
||||
import ru.dbotthepony.mc.otm.core.collect.filter
|
||||
import ru.dbotthepony.mc.otm.core.collect.maybe
|
||||
import ru.dbotthepony.mc.otm.core.random
|
||||
import ru.dbotthepony.mc.otm.core.otmRandom
|
||||
import ru.dbotthepony.mc.otm.menu.tech.PlatePressMenu
|
||||
import ru.dbotthepony.mc.otm.registry.game.MBlockEntities
|
||||
import ru.dbotthepony.mc.otm.registry.game.MRecipes
|
||||
@ -90,7 +90,7 @@ class PlatePressBlockEntity(
|
||||
recipe.getResultItem(level.registryAccess()).copyWithCount(toProcess),
|
||||
recipe.workTime * MachinesConfig.PLATE_PRESS.workTimeMultiplier,
|
||||
MachinesConfig.PLATE_PRESS.energyConsumption * toProcess,
|
||||
experience = recipe.experience.sample(level.random) * toProcess))
|
||||
experience = recipe.experience.sample(level.otmRandom) * toProcess))
|
||||
}
|
||||
|
||||
override fun tick() {
|
||||
|
17
src/main/kotlin/ru/dbotthepony/mc/otm/core/IMatteryLevel.kt
Normal file
17
src/main/kotlin/ru/dbotthepony/mc/otm/core/IMatteryLevel.kt
Normal file
@ -0,0 +1,17 @@
|
||||
package ru.dbotthepony.mc.otm.core
|
||||
|
||||
import net.minecraft.util.RandomSource
|
||||
import net.minecraft.world.level.Level
|
||||
import net.neoforged.fml.ModList
|
||||
|
||||
interface IMatteryLevel {
|
||||
/**
|
||||
* OTM provided [RandomSource], which has better statistical parameters
|
||||
*
|
||||
* Original Minecraft use LCG, which may show bad behavior when repeatedly sampled *a lot*,
|
||||
* which is what [Level]'s random is used for. OTM provided PRNG should behave better in this scenario.
|
||||
*/
|
||||
val otmRandom: RandomSource?
|
||||
}
|
||||
|
||||
val Level.otmRandom: RandomSource get() = (this as IMatteryLevel).otmRandom ?: random
|
@ -19,7 +19,7 @@ import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.gameevent.GameEvent
|
||||
import ru.dbotthepony.mc.otm.block.decorative.CargoCrateBlock
|
||||
import ru.dbotthepony.mc.otm.block.entity.decorative.CargoCrateBlockEntity
|
||||
import ru.dbotthepony.mc.otm.core.random
|
||||
import ru.dbotthepony.mc.otm.core.otmRandom
|
||||
import ru.dbotthepony.mc.otm.core.position
|
||||
import ru.dbotthepony.mc.otm.menu.decorative.MinecartCargoCrateMenu
|
||||
import ru.dbotthepony.mc.otm.registry.game.MItems
|
||||
@ -90,7 +90,7 @@ class MinecartCargoCrate(
|
||||
|
||||
if (interactingPlayers++ == 0) {
|
||||
if (!isRemoved) {
|
||||
level().playSound(null, this, MSoundEvents.CARGO_CRATE_OPEN, SoundSource.BLOCKS, 1f, 0.8f + level().random.nextFloat() * 0.2f)
|
||||
level().playSound(null, this, MSoundEvents.CARGO_CRATE_OPEN, SoundSource.BLOCKS, 1f, 0.8f + level().otmRandom.nextFloat() * 0.2f)
|
||||
this.gameEvent(GameEvent.CONTAINER_OPEN, player)
|
||||
PiglinAi.angerNearbyPiglins(player, true)
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import net.minecraft.world.item.Items
|
||||
import net.neoforged.bus.api.SubscribeEvent
|
||||
import net.neoforged.neoforge.event.entity.EntityJoinLevelEvent
|
||||
import ru.dbotthepony.mc.otm.config.ServerConfig
|
||||
import ru.dbotthepony.mc.otm.core.random
|
||||
import ru.dbotthepony.mc.otm.core.otmRandom
|
||||
import ru.dbotthepony.mc.otm.registry.game.MItems
|
||||
|
||||
|
||||
@ -17,8 +17,8 @@ object WitheredSkeletonSpawnHandler {
|
||||
val entity = event.entity
|
||||
|
||||
if (entity is WitherSkeleton) {
|
||||
val giveHelmet = event.level.random.nextFloat() < ServerConfig.WITHER_SKELETON_HELMET_CHANCE
|
||||
val giveSword = event.level.random.nextFloat() < ServerConfig.WITHER_SKELETON_SWORD_CHANCE
|
||||
val giveHelmet = event.level.otmRandom.nextFloat() < ServerConfig.WITHER_SKELETON_HELMET_CHANCE
|
||||
val giveSword = event.level.otmRandom.nextFloat() < ServerConfig.WITHER_SKELETON_SWORD_CHANCE
|
||||
|
||||
if (giveHelmet) {
|
||||
if (!entity.hasItemInSlot(EquipmentSlot.HEAD))
|
||||
|
@ -185,7 +185,7 @@ class CrudeBatteryItem : BatteryItem(ItemsConfig.Batteries.CRUDE) {
|
||||
if (player is ServerPlayer) {
|
||||
if (!mattery.androidEnergy.item.isEmpty) {
|
||||
mattery.androidEnergy.item.getCapability(Capabilities.EnergyStorage.ITEM)?.let {
|
||||
it.extractEnergy((it.maxEnergyStored * level.random.nextFloat() * .2f).roundToInt(), false)
|
||||
it.extractEnergy((it.maxEnergyStored * level.otmRandom.nextFloat() * .2f).roundToInt(), false)
|
||||
}
|
||||
|
||||
mattery.dropBattery()
|
||||
@ -195,7 +195,7 @@ class CrudeBatteryItem : BatteryItem(ItemsConfig.Batteries.CRUDE) {
|
||||
copyStack.count = 1
|
||||
mattery.androidEnergy.item = copyStack
|
||||
|
||||
val extraDamageMult = level.random.nextFloat()
|
||||
val extraDamageMult = level.otmRandom.nextFloat()
|
||||
player.hurt(MatteryDamageSource(level.registryAccess().damageType(MDamageTypes.EMP), inflictor = itemStack), 1.5f + extraDamageMult * 3.5f)
|
||||
|
||||
val debuffDuration = 100 + (100 * (1f - extraDamageMult)).roundToInt()
|
||||
|
@ -17,6 +17,7 @@ import ru.dbotthepony.mc.otm.player.matteryPlayer
|
||||
import ru.dbotthepony.mc.otm.client.isShiftDown
|
||||
import ru.dbotthepony.mc.otm.client.minecraft
|
||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||
import ru.dbotthepony.mc.otm.core.otmRandom
|
||||
import ru.dbotthepony.mc.otm.core.util.getLevelFromXp
|
||||
import ru.dbotthepony.mc.otm.item.MatteryItem
|
||||
import ru.dbotthepony.mc.otm.registry.game.MDataComponentTypes
|
||||
@ -80,7 +81,7 @@ class EssenceCapsuleItem(private val digital: Boolean) : MatteryItem(Properties(
|
||||
} else {
|
||||
if (level is ServerLevel) {
|
||||
level.levelEvent(2002, player.blockPosition(), PotionContents.getColor(Potions.WATER))
|
||||
ExperienceOrb.award(level, player.position(), (exp * (.5 + level.random.nextFloat() * .25)).toInt())
|
||||
ExperienceOrb.award(level, player.position(), (exp * (.5 + level.otmRandom.nextFloat() * .25)).toInt())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@ import net.minecraft.world.entity.item.ItemEntity
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.Level
|
||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||
import ru.dbotthepony.mc.otm.core.random
|
||||
import ru.dbotthepony.mc.otm.core.otmRandom
|
||||
import ru.dbotthepony.mc.otm.core.position
|
||||
import ru.dbotthepony.mc.otm.entity.BreadMonster
|
||||
import ru.dbotthepony.mc.otm.item.MatteryItem
|
||||
@ -39,7 +39,7 @@ class ImperfectBreadItem(properties: Properties) : MatteryItem(properties) {
|
||||
// roll multiple times so multiple bread monsters can spawn on tick
|
||||
// and also chance be less biased
|
||||
for (i in 0 until stack.count.coerceAtMost(16)) {
|
||||
if (entity.level().random.nextFloat() < 0.001f) {
|
||||
if (entity.level().otmRandom.nextFloat() < 0.001f) {
|
||||
val ent = BreadMonster(entity.level())
|
||||
ent.position = entity.position
|
||||
entity.level().addFreshEntity(ent)
|
||||
|
@ -84,7 +84,7 @@ class ExplosiveHammerItem(durability: Int = 512) : Item(Properties().stacksTo(1)
|
||||
itemStack.hurtAndBreak(8, level, player) {}
|
||||
|
||||
if (isPrimed(itemStack)) {
|
||||
itemStack.hurtAndBreak(level.random.nextInt(1, 20), level, player) {}
|
||||
itemStack.hurtAndBreak(level.otmRandom.nextInt(1, 20), level, player) {}
|
||||
unprime(itemStack)
|
||||
|
||||
val (ex, ey, ez) = Vector.atCenterOf(player.blockPosition())
|
||||
@ -226,7 +226,7 @@ class ExplosiveHammerItem(durability: Int = 512) : Item(Properties().stacksTo(1)
|
||||
|
||||
val copy = itemStack.copy()
|
||||
|
||||
itemStack.hurtAndBreak(level.random.nextInt(1, 20), attacker, EquipmentSlot.MAINHAND)
|
||||
itemStack.hurtAndBreak(level.otmRandom.nextInt(1, 20), attacker, EquipmentSlot.MAINHAND)
|
||||
|
||||
if (!itemStack.isEmpty && attacker.random.nextDouble() <= ToolsConfig.ExplosiveHammer.FLY_OFF_CHANCE) {
|
||||
attacker.setItemInHand(hand, ItemStack.EMPTY)
|
||||
|
@ -32,6 +32,7 @@ import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.core.math.DecimalConfigValue
|
||||
import ru.dbotthepony.mc.otm.core.math.defineDecimal
|
||||
import ru.dbotthepony.mc.otm.core.math.nextVariance
|
||||
import ru.dbotthepony.mc.otm.core.otmRandom
|
||||
import ru.dbotthepony.mc.otm.core.util.WriteOnce
|
||||
import ru.dbotthepony.mc.otm.item.MatteryItem
|
||||
import ru.dbotthepony.mc.otm.item.addSimpleDescription
|
||||
@ -96,10 +97,10 @@ class EnergySwordItem : MatteryItem(Properties().stacksTo(1).rarity(Rarity.RARE)
|
||||
|
||||
itemStack.getCapability(MatteryCapability.ITEM_ENERGY)?.let {
|
||||
if (it.extractEnergyExact(ENERGY_PER_SWING, false)) {
|
||||
it.extractEnergy(attacker.level().random.nextVariance(ENERGY_PER_SWING_VARIANCE), false)
|
||||
it.extractEnergy(attacker.level().otmRandom.nextVariance(ENERGY_PER_SWING_VARIANCE), false)
|
||||
victim.matteryPlayer?.let {
|
||||
if (it.isAndroid && it.androidEnergy.extractEnergyExact(ENERGY_ZAP, false)) {
|
||||
it.androidEnergy.extractEnergy(attacker.level().random.nextVariance(ENERGY_ZAP_VARIANCE), false)
|
||||
it.androidEnergy.extractEnergy(attacker.level().otmRandom.nextVariance(ENERGY_ZAP_VARIANCE), false)
|
||||
victim.hurt(MatteryDamageSource(attacker.level().registryAccess().damageType(MDamageTypes.EMP), attacker, itemStack), 8f)
|
||||
}
|
||||
}
|
||||
@ -142,12 +143,12 @@ class EnergySwordItem : MatteryItem(Properties().stacksTo(1).rarity(Rarity.RARE)
|
||||
|
||||
if (blockState.`is`(BlockTags.SWORD_EFFICIENT)) {
|
||||
if (energy?.extractEnergyExact(PLANT_POWER_COST, false) == true)
|
||||
energy.extractEnergyExact(user.level().random.nextVariance(PLANT_POWER_COST_VARIANCE), false)
|
||||
energy.extractEnergyExact(user.level().otmRandom.nextVariance(PLANT_POWER_COST_VARIANCE), false)
|
||||
}
|
||||
|
||||
if (blockState.`is`(Blocks.COBWEB)) {
|
||||
if (energy?.extractEnergyExact(COBWEB_POWER_COST, false) == true)
|
||||
energy.extractEnergyExact(user.level().random.nextVariance(COBWEB_POWER_COST_VARIANCE), false)
|
||||
energy.extractEnergyExact(user.level().otmRandom.nextVariance(COBWEB_POWER_COST_VARIANCE), false)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,7 @@ import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.core.math.DecimalConfigValue
|
||||
import ru.dbotthepony.mc.otm.core.math.defineDecimal
|
||||
import ru.dbotthepony.mc.otm.core.math.nextVariance
|
||||
import ru.dbotthepony.mc.otm.core.otmRandom
|
||||
import ru.dbotthepony.mc.otm.core.util.WriteOnce
|
||||
import ru.dbotthepony.mc.otm.item.MatteryItem
|
||||
import ru.dbotthepony.mc.otm.item.addSimpleDescription
|
||||
@ -96,10 +97,10 @@ class FallingSunItem : MatteryItem(Properties().stacksTo(1).rarity(Rarity.EPIC))
|
||||
|
||||
itemStack.getCapability(MatteryCapability.ITEM_ENERGY)?.let {
|
||||
if (it.extractEnergyExact(ENERGY_PER_SWING, false)) {
|
||||
it.extractEnergy(attacker.level().random.nextVariance(ENERGY_PER_SWING_VARIANCE), false)
|
||||
it.extractEnergy(attacker.level().otmRandom.nextVariance(ENERGY_PER_SWING_VARIANCE), false)
|
||||
victim.matteryPlayer?.let {
|
||||
if (it.isAndroid && it.androidEnergy.extractEnergyExact(ENERGY_ZAP, false)) {
|
||||
it.androidEnergy.extractEnergy(attacker.level().random.nextVariance(ENERGY_ZAP_VARIANCE), false)
|
||||
it.androidEnergy.extractEnergy(attacker.level().otmRandom.nextVariance(ENERGY_ZAP_VARIANCE), false)
|
||||
victim.hurt(MatteryDamageSource(attacker.level().registryAccess().damageType(MDamageTypes.EMP), attacker, itemStack), 8f)
|
||||
}
|
||||
}
|
||||
@ -142,12 +143,12 @@ class FallingSunItem : MatteryItem(Properties().stacksTo(1).rarity(Rarity.EPIC))
|
||||
|
||||
if (blockState.`is`(BlockTags.SWORD_EFFICIENT)) {
|
||||
if (energy?.extractEnergyExact(PLANT_POWER_COST, false) == true)
|
||||
energy.extractEnergyExact(user.level().random.nextVariance(PLANT_POWER_COST_VARIANCE), false)
|
||||
energy.extractEnergyExact(user.level().otmRandom.nextVariance(PLANT_POWER_COST_VARIANCE), false)
|
||||
}
|
||||
|
||||
if (blockState.`is`(Blocks.COBWEB)) {
|
||||
if (energy?.extractEnergyExact(COBWEB_POWER_COST, false) == true)
|
||||
energy.extractEnergyExact(user.level().random.nextVariance(COBWEB_POWER_COST_VARIANCE), false)
|
||||
energy.extractEnergyExact(user.level().otmRandom.nextVariance(COBWEB_POWER_COST_VARIANCE), false)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@ import ru.dbotthepony.mc.otm.core.math.component1
|
||||
import ru.dbotthepony.mc.otm.core.math.component2
|
||||
import ru.dbotthepony.mc.otm.core.math.component3
|
||||
import ru.dbotthepony.mc.otm.core.math.toRadians
|
||||
import ru.dbotthepony.mc.otm.core.otmRandom
|
||||
import ru.dbotthepony.mc.otm.core.position
|
||||
import ru.dbotthepony.mc.otm.core.readItem
|
||||
import ru.dbotthepony.mc.otm.core.writeItem
|
||||
@ -445,7 +446,7 @@ class ExopackSmokePacket(val player: UUID) : CustomPacketPayload {
|
||||
z += kotlin.math.sin(deg) * -0.4
|
||||
|
||||
val level = ply.level()
|
||||
val random = level.random
|
||||
val random = level.otmRandom
|
||||
|
||||
for (i in 0 .. random.nextInt(2, 4))
|
||||
level.addParticle(
|
||||
|
@ -13,7 +13,7 @@ import net.neoforged.neoforge.network.handling.IPayloadContext
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.client.minecraft
|
||||
import ru.dbotthepony.mc.otm.core.ResourceLocation
|
||||
import ru.dbotthepony.mc.otm.core.random
|
||||
import ru.dbotthepony.mc.otm.core.otmRandom
|
||||
|
||||
class SmokeParticlesPacket(val x: Double, val y: Double, val z: Double) : CustomPacketPayload {
|
||||
fun write(buff: FriendlyByteBuf) {
|
||||
@ -24,7 +24,7 @@ class SmokeParticlesPacket(val x: Double, val y: Double, val z: Double) : Custom
|
||||
|
||||
fun play(context: IPayloadContext) {
|
||||
minecraft.player?.level()?.let {
|
||||
makeSmoke(x, y, z, it.random, it)
|
||||
makeSmoke(x, y, z, it.otmRandom, it)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -528,7 +528,7 @@ class MatteryPlayer(val ply: Player) {
|
||||
override fun onJobTick(status: JobStatus<ItemJob>) {
|
||||
super.onJobTick(status)
|
||||
|
||||
if (isExopackVisible && ply.level().random.nextFloat() <= 0.05f) {
|
||||
if (isExopackVisible && ply.level().otmRandom.nextFloat() <= 0.05f) {
|
||||
PacketDistributor.sendToPlayersTrackingEntityAndSelf(ply, ExopackSmokePacket(ply.uuid))
|
||||
}
|
||||
}
|
||||
@ -1319,7 +1319,7 @@ class MatteryPlayer(val ply: Player) {
|
||||
|
||||
pos.mul(RenderSystem.getProjectionMatrix())
|
||||
pos.mul(poseStack.last().pose())
|
||||
makeSmoke(cam.x + pos.x, cam.y + pos.y, cam.z + pos.z, ply.level().random, ply.level())
|
||||
makeSmoke(cam.x + pos.x, cam.y + pos.y, cam.z + pos.z, ply.level().otmRandom, ply.level())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,6 +49,7 @@ import ru.dbotthepony.mc.otm.core.math.rotateXDegrees
|
||||
import ru.dbotthepony.mc.otm.core.math.rotateYDegrees
|
||||
import ru.dbotthepony.mc.otm.core.math.shortestDistanceBetween
|
||||
import ru.dbotthepony.mc.otm.core.math.times
|
||||
import ru.dbotthepony.mc.otm.core.otmRandom
|
||||
import ru.dbotthepony.mc.otm.milliTime
|
||||
import ru.dbotthepony.mc.otm.registry.game.AndroidFeatures
|
||||
import ru.dbotthepony.mc.otm.triggers.EnderTeleporterFallDeathTrigger
|
||||
@ -302,7 +303,7 @@ class EnderTeleporterFeature(capability: MatteryPlayer) : AndroidActiveFeature(A
|
||||
val event = EventHooks.onEnderTeleport(ply, blockPos.x + 0.5, blockPos.y.toDouble(), blockPos.z + 0.5)
|
||||
|
||||
if (event.isCanceled) {
|
||||
(ply as ServerPlayer).connection.send(ClientboundSoundEntityPacket(SoundEvents.ITEM_BREAK.holder, SoundSource.PLAYERS, ply, 0.3f, 0.5f, ply.level().random.nextLong()))
|
||||
(ply as ServerPlayer).connection.send(ClientboundSoundEntityPacket(SoundEvents.ITEM_BREAK.holder, SoundSource.PLAYERS, ply, 0.3f, 0.5f, ply.level().otmRandom.nextLong()))
|
||||
return false
|
||||
}
|
||||
|
||||
@ -310,9 +311,9 @@ class EnderTeleporterFeature(capability: MatteryPlayer) : AndroidActiveFeature(A
|
||||
lastTeleport = ply.server!!.tickCount
|
||||
android.androidEnergy.extractEnergy(PlayerConfig.EnderTeleporter.ENERGY_COST, false)
|
||||
|
||||
ply.level().playSound(null, ply, SoundEvents.ENDERMAN_TELEPORT, SoundSource.PLAYERS, 0.3f, 0.8f + ply.level().random.nextFloat() * 0.4f)
|
||||
ply.level().playSound(null, ply, SoundEvents.ENDERMAN_TELEPORT, SoundSource.PLAYERS, 0.3f, 0.8f + ply.level().otmRandom.nextFloat() * 0.4f)
|
||||
ply.teleportTo(event.targetX, event.targetY, event.targetZ)
|
||||
ply.level().playSound(null, ply, SoundEvents.ENDERMAN_TELEPORT, SoundSource.PLAYERS, 1f, 0.8f + ply.level().random.nextFloat() * 0.4f)
|
||||
ply.level().playSound(null, ply, SoundEvents.ENDERMAN_TELEPORT, SoundSource.PLAYERS, 1f, 0.8f + ply.level().otmRandom.nextFloat() * 0.4f)
|
||||
|
||||
ply.deltaMovement = Vector(0.0, 0.0, 0.0)
|
||||
ply.resetFallDistance()
|
||||
|
@ -17,7 +17,8 @@
|
||||
"HopperBlockEntityMixin",
|
||||
"DispenserBlockEntityMixin",
|
||||
"GuiGraphicsMixin",
|
||||
"BlockStateBaseMixin"
|
||||
"BlockStateBaseMixin",
|
||||
"LevelMixin"
|
||||
],
|
||||
"client": [
|
||||
"MixinGameRenderer",
|
||||
|
Loading…
Reference in New Issue
Block a user