Skip to content

Commit

Permalink
patch a race condition in vein generation. (#368) (#374)
Browse files Browse the repository at this point in the history
* fix a race condition in vein generation.

* oh fuck i forgot to convert to local pos

* I stg if this doesnt work...

* i guess that you shouldn't make veins that big...
aw mannn
  • Loading branch information
screret authored Sep 15, 2023
1 parent f73e421 commit b573a97
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@
import lombok.Setter;
import lombok.experimental.Accessors;
import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.BulkSectionAccess;
import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.level.levelgen.LegacyRandomSource;
import net.minecraft.world.level.levelgen.WorldgenRandom;
import net.minecraft.world.level.levelgen.feature.configurations.OreConfiguration;
Expand Down Expand Up @@ -64,6 +67,7 @@ public boolean generate(WorldGenLevel level, RandomSource random, GTOreDefinitio
WorldgenRandom worldgenRandom = new WorldgenRandom(new LegacyRandomSource(level.getSeed()));
NormalNoise normalNoise = NormalNoise.create(worldgenRandom, -2, 4.0D);
ChunkPos chunkPos = new ChunkPos(origin);
BulkSectionAccess access = new BulkSectionAccess(level);

float density = entry.getDensity();
int size = entry.getClusterSize();
Expand All @@ -84,31 +88,43 @@ public boolean generate(WorldGenLevel level, RandomSource random, GTOreDefinitio
if (dist > size * 2) {
continue;
}
BlockPos pos = new BlockPos(basePos.getX() + dX, dY, basePos.getZ() + dZ);
if (!level.ensureCanWrite(pos))
continue;
LevelChunkSection section = access.getSection(pos);
if (section == null)
continue;
if (normalNoise.getValue(dX, dY, dZ) >= 0.5 && random.nextFloat() <= density) {
if (placeBlock(level, random, new BlockPos(basePos.getX() + dX, dY, basePos.getZ() + dZ), entry)) {
if (placeBlock(access, section, random, pos, entry)) {
++blocksPlaced;
}
}
}
}
}

access.close();
return blocksPlaced > 0;
}

private boolean placeBlock(WorldGenLevel level, RandomSource rand, BlockPos pos, GTOreDefinition entry) {
private boolean placeBlock(BulkSectionAccess level, LevelChunkSection section, RandomSource rand, BlockPos pos, GTOreDefinition entry) {
List<? extends Map.Entry<Integer, DikeBlockDefinition>> entries = blocks.stream().map(b -> Map.entry(b.weight, b)).toList();
DikeBlockDefinition blockDefinition = blocks.get(GTUtil.getRandomItem(rand, entries, entries.size()));
BlockState current = level.getBlockState(pos);
MutableBoolean returnValue = new MutableBoolean(false);

int x = SectionPos.sectionRelative(pos.getX());
int y = SectionPos.sectionRelative(pos.getY());
int z = SectionPos.sectionRelative(pos.getZ());

if (pos.getY() >= blockDefinition.minY() && pos.getY() <= blockDefinition.maxY()) {
blockDefinition.block.ifLeft(blockStates -> {
for (OreConfiguration.TargetBlockState targetState : blockStates) {
if (!GTOreFeature.canPlaceOre(current, level::getBlockState, rand, entry, targetState, pos.mutable()))
continue;
if (targetState.state.isAir())
continue;
level.setBlock(pos, targetState.state, 2);
section.setBlockState(x, y, z, targetState.state, false);
returnValue.setTrue();
break;
}
Expand All @@ -121,7 +137,7 @@ private boolean placeBlock(WorldGenLevel level, RandomSource rand, BlockPos pos,
Block toPlace = ChemicalHelper.getBlock(prefix, material);
if (toPlace == null || toPlace.defaultBlockState().isAir())
return;
level.setBlock(pos, toPlace.defaultBlockState(), 2);
section.setBlockState(x, y, z, toPlace.defaultBlockState(), false);
returnValue.setTrue();
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.registries.Registries;
import net.minecraft.core.SectionPos;
import net.minecraft.tags.BlockTags;
import net.minecraft.tags.TagKey;
import net.minecraft.util.ExtraCodecs;
Expand All @@ -31,6 +32,8 @@
import net.minecraft.world.level.block.BuddingAmethystBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.chunk.BulkSectionAccess;
import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.level.levelgen.GeodeCrackSettings;
import net.minecraft.world.level.levelgen.GeodeLayerSettings;
import net.minecraft.world.level.levelgen.LegacyRandomSource;
Expand Down Expand Up @@ -116,6 +119,8 @@ public List<Map.Entry<Either<BlockState, Material>, Integer>> getAllEntries() {

@Override
public boolean generate(WorldGenLevel level, RandomSource random, GTOreDefinition entry, BlockPos origin) {
BulkSectionAccess access = new BulkSectionAccess(level);

BlockState blockState;
int offset;
int offset2;
Expand All @@ -137,7 +142,7 @@ public boolean generate(WorldGenLevel level, RandomSource random, GTOreDefinitio
for (offset2 = 0; offset2 < distributionSample; ++offset2) {
offset = this.outerWallDistance.sample(random);
BlockPos origin2 = origin.offset(offset, this.outerWallDistance.sample(random), this.outerWallDistance.sample(random));
blockState = level.getBlockState(origin2);
blockState = access.getBlockState(origin2);
if ((blockState.isAir() || blockState.is(BlockTags.GEODE_INVALID_BLOCKS)) && ++invalidBlocksCount > this.invalidBlocksThreshold) {
return false;
}
Expand Down Expand Up @@ -177,8 +182,13 @@ public boolean generate(WorldGenLevel level, RandomSource random, GTOreDefinitio
t += Mth.fastInvSqrt(pos.distSqr(origin4) + (double)geodeCrackSettings.crackPointOffset) + noiseValue;
}
if (s < outerSize) continue;
if (!level.ensureCanWrite(pos))
continue;
LevelChunkSection section = access.getSection(pos);
if (section == null)
continue;
if (doCrack && t >= crackSize && s < fillingSize) {
this.safeSetBlock(level, pos, Blocks.AIR.defaultBlockState(), placementPredicate);
this.safeSetBlock(access, section, pos, Blocks.AIR.defaultBlockState(), placementPredicate);
for (Direction direction : DIRECTIONS) {
BlockPos origin5 = pos.relative(direction);
FluidState fluidState = level.getFluidState(origin5);
Expand All @@ -188,26 +198,26 @@ public boolean generate(WorldGenLevel level, RandomSource random, GTOreDefinitio
continue;
}
if (s >= fillingSize) {
this.safeSetBlock(level, pos, getStateFromEither(geodeBlockSettings.fillingProvider, geodeBlockSettings, random, pos), placementPredicate);
this.safeSetBlock(access, section, pos, getStateFromEither(geodeBlockSettings.fillingProvider, geodeBlockSettings, random, pos), placementPredicate);
continue;
}
if (s >= innerSize) {
boolean useAltLayer = (double)random.nextFloat() < this.useAlternateLayer0Chance;
if (useAltLayer) {
this.safeSetBlock(level, pos, getStateFromEither(geodeBlockSettings.alternateInnerLayerProvider, geodeBlockSettings, random, pos), placementPredicate);
this.safeSetBlock(access, section, pos, getStateFromEither(geodeBlockSettings.alternateInnerLayerProvider, geodeBlockSettings, random, pos), placementPredicate);
} else {
this.safeSetBlock(level, pos, getStateFromEither(geodeBlockSettings.innerLayerProvider, geodeBlockSettings, random, pos), placementPredicate);
this.safeSetBlock(access, section, pos, getStateFromEither(geodeBlockSettings.innerLayerProvider, geodeBlockSettings, random, pos), placementPredicate);
}
if (this.placementsRequireLayer0Alternate && !useAltLayer || !((double)random.nextFloat() < this.usePotentialPlacementsChance)) continue;
positions.add(pos.immutable());
continue;
}
if (s >= middleSize) {
this.safeSetBlock(level, pos, getStateFromEither(geodeBlockSettings.middleLayerProvider, geodeBlockSettings, random, pos), placementPredicate);
this.safeSetBlock(access, section, pos, getStateFromEither(geodeBlockSettings.middleLayerProvider, geodeBlockSettings, random, pos), placementPredicate);
continue;
}
if (!(s >= outerSize)) continue;
this.safeSetBlock(level, pos, getStateFromEither(geodeBlockSettings.outerLayerProvider, geodeBlockSettings, random, pos), placementPredicate);
this.safeSetBlock(access, section, pos, getStateFromEither(geodeBlockSettings.outerLayerProvider, geodeBlockSettings, random, pos), placementPredicate);
}
List<BlockState> innerPlacements = geodeBlockSettings.innerPlacements;
block5: for (BlockPos origin2 : positions) {
Expand All @@ -217,22 +227,32 @@ public boolean generate(WorldGenLevel level, RandomSource random, GTOreDefinitio
blockState = blockState.setValue(BlockStateProperties.FACING, direction2);
}
BlockPos origin6 = origin2.relative(direction2);
BlockState blockState2 = level.getBlockState(origin6);
BlockState blockState2 = access.getBlockState(origin6);
if (blockState.hasProperty(BlockStateProperties.WATERLOGGED)) {
blockState = blockState.setValue(BlockStateProperties.WATERLOGGED, blockState2.getFluidState().isSource());
}
if (!BuddingAmethystBlock.canClusterGrowAtState(blockState2)) continue;
this.safeSetBlock(level, origin6, blockState, placementPredicate);
if (!level.ensureCanWrite(origin6))
continue;
LevelChunkSection section = access.getSection(origin6);
if (section == null)
continue;
this.safeSetBlock(access, section, origin6, blockState, placementPredicate);
continue block5;
}
}

access.close();
return true;
}


protected void safeSetBlock(WorldGenLevel level, BlockPos pos, BlockState state, Predicate<BlockState> oldState) {
protected void safeSetBlock(BulkSectionAccess level, LevelChunkSection section, BlockPos pos, BlockState state, Predicate<BlockState> oldState) {
if (oldState.test(level.getBlockState(pos))) {
level.setBlock(pos, state, 2);
int x = SectionPos.sectionRelative(pos.getX());
int y = SectionPos.sectionRelative(pos.getY());
int z = SectionPos.sectionRelative(pos.getZ());
section.setBlockState(x, y, z, state, false);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry;
import net.minecraft.core.SectionPos;
import net.minecraft.core.registries.Registries;
import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.util.Mth;
Expand All @@ -24,6 +25,8 @@
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.BulkSectionAccess;
import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.level.levelgen.*;
import net.minecraft.world.level.levelgen.blending.Blender;
import net.minecraft.world.level.levelgen.feature.configurations.OreConfiguration;
Expand Down Expand Up @@ -110,6 +113,7 @@ public boolean generate(WorldGenLevel level, RandomSource random, GTOreDefinitio
List<? extends Map.Entry<Integer, VeinBlockDefinition>> commonEntries = oreBlocks.stream().map(b -> Map.entry(b.weight, b)).toList();
List<? extends Map.Entry<Integer, VeinBlockDefinition>> rareEntries = rareBlocks == null ? null : rareBlocks.stream().map(b -> Map.entry(b.weight, b)).toList(); // never accessed if rareBlocks is null

BulkSectionAccess access = new BulkSectionAccess(level);
RandomState randomState = level.getLevel().getChunkSource().randomState();
Blender blender;
if (level instanceof WorldGenRegion region) {
Expand Down Expand Up @@ -179,21 +183,29 @@ public Blender getBlender() {
double chance = Mth.clampedMap(absToggleNoise, veininessThreshold, maxRichnessThreshold, minRichness, maxRichness);

BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(finalX, finalY, finalZ);
BlockState current = level.getBlockState(pos);
LevelChunkSection section = access.getSection(pos);
if (section == null)
continue;
int sectionX = SectionPos.sectionRelative(pos.getX());
int sectionY = SectionPos.sectionRelative(pos.getY());
int sectionZ = SectionPos.sectionRelative(pos.getZ());
if (!level.ensureCanWrite(pos))
continue;
BlockState current = section.getBlockState(sectionX, sectionY, sectionZ);
boolean placed = false;
if (random.nextFloat() <= entry.getDensity()) {
if (random.nextFloat() < chance) {
if (rareBlocks != null && rareBlocks.size() > 0 && random.nextFloat() < rareBlockChance) {
placed = placeOre(rareBlocks.get(GTUtil.getRandomItem(random, rareEntries, rareEntries.size())).block, current, level, random, pos, entry);
if (rareBlocks != null && !rareBlocks.isEmpty() && random.nextFloat() < rareBlockChance) {
placed = placeOre(rareBlocks.get(GTUtil.getRandomItem(random, rareEntries, rareEntries.size())).block, current, access, section, random, pos, entry);
} else {
placed = placeOre(oreBlocks.get(GTUtil.getRandomItem(random, commonEntries, commonEntries.size())).block, current, level, random, pos, entry);
placed = placeOre(oreBlocks.get(GTUtil.getRandomItem(random, commonEntries, commonEntries.size())).block, current, access, section, random, pos, entry);
}
} else {
if (fillerBlock == null || fillerBlock.isAir())
continue;
if (!GTOreFeature.canPlaceOre(current, level::getBlockState, random, entry, pos))
continue;
level.setBlock(pos, fillerBlock, 2);
section.setBlockState(sectionX, sectionY, sectionZ, fillerBlock, false);
if (level.getBlockState(pos) != current) placed = true;
}
}
Expand All @@ -205,18 +217,25 @@ public Blender getBlender() {
}

}

access.close();
return placedCount > 0;
}

protected static boolean placeOre(Either<List<OreConfiguration.TargetBlockState>, Material> block, BlockState current, WorldGenLevel level, RandomSource random, BlockPos.MutableBlockPos pos, GTOreDefinition entry) {
protected static boolean placeOre(Either<List<OreConfiguration.TargetBlockState>, Material> block, BlockState current, BulkSectionAccess level, LevelChunkSection section, RandomSource random, BlockPos.MutableBlockPos pos, GTOreDefinition entry) {
MutableBoolean returnValue = new MutableBoolean(false);

int x = SectionPos.sectionRelative(pos.getX());
int y = SectionPos.sectionRelative(pos.getY());
int z = SectionPos.sectionRelative(pos.getZ());

block.ifLeft(blockStates -> {
for (OreConfiguration.TargetBlockState targetState : blockStates) {
if (!GTOreFeature.canPlaceOre(current, level::getBlockState, random, entry, targetState, pos))
continue;
if (targetState.state.isAir())
continue;
level.setBlock(pos, targetState.state, 2);
section.setBlockState(x, y, z, targetState.state, false);
returnValue.setTrue();
break;
}
Expand All @@ -229,7 +248,7 @@ protected static boolean placeOre(Either<List<OreConfiguration.TargetBlockState>
Block toPlace = ChemicalHelper.getBlock(prefix, material);
if (toPlace == null || toPlace.defaultBlockState().isAir())
return;
level.setBlock(pos, toPlace.defaultBlockState(), 2);
section.setBlockState(x, y, z, toPlace.defaultBlockState(), false);
returnValue.setTrue();
});
return returnValue.isTrue();
Expand Down
Loading

0 comments on commit b573a97

Please sign in to comment.