Skip to content

Commit

Permalink
Fix: unsafe cast to worldgenrandom
Browse files Browse the repository at this point in the history
Fixes #959
  • Loading branch information
klikli-dev committed Jul 31, 2023
1 parent 27e515f commit e4be359
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
package com.klikli_dev.occultism.common.level.cave;

import com.klikli_dev.occultism.common.level.multichunk.IMultiChunkSubFeature;
import com.klikli_dev.occultism.common.level.multichunk.MultiChunkFeature;
import com.klikli_dev.occultism.common.level.multichunk.MultiChunkFeatureConfig;
import com.klikli_dev.occultism.registry.OccultismTags;
import com.klikli_dev.occultism.util.Math3DUtil;
Expand All @@ -35,7 +36,6 @@
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.levelgen.WorldgenRandom;
import net.minecraft.world.phys.AABB;

import java.util.ArrayList;
Expand Down Expand Up @@ -88,9 +88,10 @@ public boolean place(WorldGenLevel reader, ChunkGenerator generator, RandomSourc
sphericalCaves.add(rootPosition);

ChunkPos rootChunk = new ChunkPos(rootPosition);

//Seed with root chunk position
((WorldgenRandom) rand)
.setLargeFeatureWithSalt(reader.getSeed(), rootChunk.x, rootChunk.z, config.featureSeedSalt);
var seed = MultiChunkFeature.getLargeFeatureWithSaltSeed(reader.getSeed(), rootChunk.x, rootChunk.z, config.featureSeedSalt);
rand.setSeed(seed);

List<Sphere> spheres = new ArrayList<>();
int radiusBase = this.radius + rand.nextInt(this.maxRandomRadiusOffset);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@
import com.mojang.serialization.Codec;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.levelgen.WorldgenRandom;
import net.minecraft.world.level.levelgen.XoroshiroRandomSource;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;

Expand All @@ -45,8 +46,11 @@ public MultiChunkFeature(Codec<MultiChunkFeatureConfig> codec, IMultiChunkSubFea
this.subFeature = subFeature;
}

public static long getLargeFeatureWithSaltSeed(long pLevelSeed, int pRegionX, int pRegionZ, int pSalt) {
return (long) pRegionX * 341873128712L + (long) pRegionZ * 132897987541L + pLevelSeed + (long) pSalt;
}

protected List<BlockPos> getRootPositions(WorldGenLevel reader, ChunkGenerator generator, WorldgenRandom random,
protected List<BlockPos> getRootPositions(WorldGenLevel reader, ChunkGenerator generator, RandomSource random,
ChunkPos generatingChunk,
MultiChunkFeatureConfig config) {
ArrayList<BlockPos> result = new ArrayList<>(1);
Expand All @@ -56,8 +60,8 @@ protected List<BlockPos> getRootPositions(WorldGenLevel reader, ChunkGenerator g
ChunkPos currentChunk = new ChunkPos(generatingChunk.x + i, generatingChunk.z + j);

//Seed random for this chunk, this way we get the same result no matter how often this is called.
random.setLargeFeatureWithSalt(reader.getSeed(), currentChunk.x, currentChunk.z,
config.featureSeedSalt);
var seed = getLargeFeatureWithSaltSeed(reader.getSeed(), currentChunk.x, currentChunk.z, config.featureSeedSalt);
random.setSeed(seed);

if (random.nextInt(config.chanceToGenerate) == 0) {
//this chunk contains a root, so we generate a random
Expand All @@ -80,15 +84,21 @@ public boolean place(FeaturePlaceContext<MultiChunkFeatureConfig> context) {

if (context.level().getChunkSource() instanceof ServerChunkCache chunkSource) {
ChunkPos generatingChunk = new ChunkPos(pos);

//we create our own random here so that subsequent features are not affected by our custom seed gen.
//we also hand that to our sub feature so that that also doesn't modify the seed of the world random.
var random = new XoroshiroRandomSource(context.random().nextLong());

List<BlockPos> rootPositions =
this.getRootPositions(context.level(), context.chunkGenerator(), (WorldgenRandom) context.random(), generatingChunk, context.config());
this.getRootPositions(context.level(), context.chunkGenerator(), random, generatingChunk, context.config());

//If no root position was found in range, we exit
if (rootPositions.isEmpty()) {
return false;
}
boolean generatedAny = false;
for (BlockPos rootPosition : rootPositions) {
if (this.subFeature.place(context.level(), context.chunkGenerator(), context.random(), rootPosition,
if (this.subFeature.place(context.level(), context.chunkGenerator(), random, rootPosition,
Math3DUtil.bounds(generatingChunk, context.chunkGenerator().getGenDepth()), context.config()))
generatedAny = true;
}
Expand Down

0 comments on commit e4be359

Please sign in to comment.