minecraft-src/net/minecraft/world/level/levelgen/WorldgenRandom.java
2025-07-04 01:41:11 +03:00

116 lines
4.1 KiB
Java

package net.minecraft.world.level.levelgen;
import java.util.function.LongFunction;
import net.minecraft.util.RandomSource;
public class WorldgenRandom extends LegacyRandomSource {
private final RandomSource randomSource;
private int count;
public WorldgenRandom(RandomSource randomSource) {
super(0L);
this.randomSource = randomSource;
}
public int getCount() {
return this.count;
}
@Override
public RandomSource fork() {
return this.randomSource.fork();
}
@Override
public PositionalRandomFactory forkPositional() {
return this.randomSource.forkPositional();
}
@Override
public int next(int size) {
this.count++;
return this.randomSource instanceof LegacyRandomSource legacyRandomSource ? legacyRandomSource.next(size) : (int)(this.randomSource.nextLong() >>> 64 - size);
}
@Override
public synchronized void setSeed(long seed) {
if (this.randomSource != null) {
this.randomSource.setSeed(seed);
}
}
/**
* Seeds the current random for chunk decoration, including spawning mobs and for use in feature placement.
* The coordinates correspond to the minimum block position within a given chunk.
*/
public long setDecorationSeed(long levelSeed, int minChunkBlockX, int minChunkBlockZ) {
this.setSeed(levelSeed);
long l = this.nextLong() | 1L;
long m = this.nextLong() | 1L;
long n = minChunkBlockX * l + minChunkBlockZ * m ^ levelSeed;
this.setSeed(n);
return n;
}
/**
* Seeds the current random for placing features.
* Each feature is seeded differently in order to seem more random. However, it does not do a good job of this, and issues can arise from the salt being small with features that have the same decoration step and are close together in the feature lists.
*
* @param decorationSeed The seed computed by {@link #setDecorationSeed(long, int, int)}
* @param index The cumulative index of the generating feature within the biome's list of features.
* @param decorationStep The ordinal of the {@link net.minecraft.world.level.levelgen.GenerationStep.Decoration} of the generating feature.
*/
public void setFeatureSeed(long decorationSeed, int index, int decorationStep) {
long l = decorationSeed + index + 10000 * decorationStep;
this.setSeed(l);
}
/**
* Seeds the current random for placing large features such as caves, strongholds, and mineshafts.
*
* @param baseSeed This is passed in as the level seed, or in some cases such as carvers, as an offset from the level seed unique to each carver.
*/
public void setLargeFeatureSeed(long baseSeed, int chunkX, int chunkZ) {
this.setSeed(baseSeed);
long l = this.nextLong();
long m = this.nextLong();
long n = chunkX * l ^ chunkZ * m ^ baseSeed;
this.setSeed(n);
}
/**
* Seeds the current random for placing the starts of structure features.
* The region coordinates are the region which the target chunk lies in. For example, witch hut regions are 32x32 chunks, so all chunks within that region would be seeded identically.
* The size of the regions themselves are determined by the {@code spacing} of the structure settings.
*
* @param salt A salt unique to each structure.
*/
public void setLargeFeatureWithSalt(long levelSeed, int regionX, int regionZ, int salt) {
long l = regionX * 341873128712L + regionZ * 132897987541L + levelSeed + salt;
this.setSeed(l);
}
/**
* Creates a new {@code RandomSource}, seeded for determining whether a chunk is a slime chunk or not.
*
* @param salt For vanilla slimes, this is always {@code 987234911L}
*/
public static RandomSource seedSlimeChunk(int chunkX, int chunkZ, long levelSeed, long salt) {
return RandomSource.create(levelSeed + chunkX * chunkX * 4987142 + chunkX * 5947611 + chunkZ * chunkZ * 4392871L + chunkZ * 389711 ^ salt);
}
public static enum Algorithm {
LEGACY(LegacyRandomSource::new),
XOROSHIRO(XoroshiroRandomSource::new);
private final LongFunction<RandomSource> constructor;
private Algorithm(final LongFunction<RandomSource> constructor) {
this.constructor = constructor;
}
public RandomSource newInstance(long seed) {
return (RandomSource)this.constructor.apply(seed);
}
}
}