Increase layered ore shape variation (#6158)

This commit is contained in:
KdotJPG 2024-03-21 07:01:31 -04:00 committed by GitHub
parent a41053b896
commit c92bbdda2d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,6 +1,7 @@
package com.simibubi.create.infrastructure.worldgen;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
@ -20,17 +21,24 @@ import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
import net.minecraft.world.level.levelgen.feature.configurations.OreConfiguration;
import net.minecraft.world.level.levelgen.feature.configurations.OreConfiguration.TargetBlockState;
import net.minecraft.world.level.levelgen.synth.SimplexNoise;
public class LayeredOreFeature extends Feature<LayeredOreConfiguration> {
public LayeredOreFeature() {
super(LayeredOreConfiguration.CODEC);
}
private static final float MAX_LAYER_DISPLACEMENT = 1.75f;
private static final float LAYER_NOISE_FREQUENCY = 0.125f;
private static final float MAX_RADIAL_THRESHOLD_REDUCTION = 0.25f;
private static final float RADIAL_NOISE_FREQUENCY = 0.125f;
@Override
public boolean place(FeaturePlaceContext<LayeredOreConfiguration> pContext) {
RandomSource random = pContext.random();
BlockPos blockpos = pContext.origin();
WorldGenLevel worldgenlevel = pContext.level();
BlockPos origin = pContext.origin();
WorldGenLevel worldGenLevel = pContext.level();
LayeredOreConfiguration config = pContext.config();
List<LayerPattern> patternPool = config.layerPatterns;
@ -40,89 +48,120 @@ public class LayeredOreFeature extends Feature<LayeredOreConfiguration> {
LayerPattern layerPattern = patternPool.get(random.nextInt(patternPool.size()));
int placedAmount = 0;
int size = config.size;
int radius = Mth.ceil(config.size / 2f);
int x0 = blockpos.getX() - radius;
int y0 = blockpos.getY() - radius;
int z0 = blockpos.getZ() - radius;
int width = size + 1;
int length = size + 1;
int height = size + 1;
int size = config.size + 1;
float radius = config.size * 0.5f;
int radiusBound = Mth.ceil(radius) - 1;
int x0 = origin.getX();
int y0 = origin.getY();
int z0 = origin.getZ();
if (blockpos.getY() >= worldgenlevel.getHeight(Heightmap.Types.OCEAN_FLOOR_WG, blockpos.getX(),
blockpos.getZ()))
if (origin.getY() >= worldGenLevel.getHeight(Heightmap.Types.OCEAN_FLOOR_WG, origin.getX(), origin.getZ()))
return false;
List<LayerPattern.Layer> resolvedLayers = new ArrayList<>();
List<Float> layerDiameterOffsets = new ArrayList<>();
List<TemporaryLayerEntry> tempLayers = new ArrayList<>();
float layerSizeTotal = 0.0f;
LayerPattern.Layer current = null;
while (layerSizeTotal < size) {
Layer next = layerPattern.rollNext(current, random);
float layerSize = Mth.randomBetween(random, next.minSize, next.maxSize);
tempLayers.add(new TemporaryLayerEntry(next, layerSize));
layerSizeTotal += layerSize;
current = next;
}
List<ResolvedLayerEntry> resolvedLayers = new ArrayList<>(tempLayers.size());
float cumulativeLayerSize = -(layerSizeTotal - size) * random.nextFloat();
for (TemporaryLayerEntry tempLayerEntry : tempLayers) {
float rampStartValue = resolvedLayers.size() == 0 ?
Float.NEGATIVE_INFINITY :
cumulativeLayerSize * (2.0f / size) - 1.0f;
cumulativeLayerSize += tempLayerEntry.size();
if (cumulativeLayerSize < 0)
continue;
float radialThresholdMultiplier = Mth.randomBetween(random, 0.5f, 1.0f);
resolvedLayers.add(new ResolvedLayerEntry(tempLayerEntry.layer, radialThresholdMultiplier, rampStartValue));
}
// Choose stacking direction
float gy = Mth.randomBetween(random, -1.0f, 1.0f);
gy = (float) Math.cbrt(gy); // Make layer alignment tend towards horizontal more than vertical
float xzRescale = Mth.sqrt(1.0f - gy * gy);
float theta = random.nextFloat() * Mth.TWO_PI;
float gx = Mth.cos(theta) * xzRescale;
float gz = Mth.sin(theta) * xzRescale;
SimplexNoise layerDisplacementNoise = new SimplexNoise(random);
SimplexNoise radiusNoise = new SimplexNoise(random);
MutableBlockPos mutablePos = new MutableBlockPos();
BulkSectionAccess bulksectionaccess = new BulkSectionAccess(worldgenlevel);
int layerCoordinate = random.nextInt(4);
int slantyCoordinate = random.nextInt(3);
float slope = random.nextFloat() * .75f;
BulkSectionAccess bulkSectionAccess = new BulkSectionAccess(worldGenLevel);
try {
for (int x = 0; x < width; x++) {
float dx = x * 2f / width - 1;
if (dx * dx > 1)
for (int dzBlock = -radiusBound; dzBlock <= radiusBound; dzBlock++) {
float dz = dzBlock * (1.0f / radius);
if (dz * dz > 1)
continue;
for (int y = 0; y < height; y++) {
float dy = y * 2f / height - 1;
if (dx * dx + dy * dy > 1)
continue;
if (worldgenlevel.isOutsideBuildHeight(y0 + y))
for (int dxBlock = -radiusBound; dxBlock <= radiusBound; dxBlock++) {
float dx = dxBlock * (1.0f / radius);
if (dz * dz + dx * dx > 1)
continue;
for (int z = 0; z < length; z++) {
float dz = z * 2f / height - 1;
int layerIndex = layerCoordinate == 0 ? z : layerCoordinate == 1 ? x : y;
if (slantyCoordinate != layerCoordinate)
layerIndex += Mth.floor(slantyCoordinate == 0 ? z : slantyCoordinate == 1 ? x : y) * slope;
while (layerIndex >= resolvedLayers.size()) {
Layer next = layerPattern.rollNext(
resolvedLayers.isEmpty() ? null : resolvedLayers.get(resolvedLayers.size() - 1),
random);
float offset = random.nextFloat() * .5f + .5f;
for (int i = 0; i < next.minSize + random.nextInt(1 + next.maxSize - next.minSize); i++) {
resolvedLayers.add(next);
layerDiameterOffsets.add(offset);
}
}
if (dx * dx + dy * dy + dz * dz > 1 * layerDiameterOffsets.get(layerIndex))
for (int dyBlock = -radiusBound; dyBlock <= radiusBound; dyBlock++) {
float dy = dyBlock * (1.0f / radius);
float distanceSquared = dz * dz + dx * dx + dy * dy;
if (distanceSquared > 1)
continue;
if (worldGenLevel.isOutsideBuildHeight(y0 + dyBlock))
continue;
LayerPattern.Layer layer = resolvedLayers.get(layerIndex);
List<TargetBlockState> state = layer.rollBlock(random);
int currentX = x0 + dxBlock;
int currentY = y0 + dyBlock;
int currentZ = z0 + dzBlock;
int currentX = x0 + x;
int currentY = y0 + y;
int currentZ = z0 + z;
float rampValue = gx * dx + gy * dy + gz * dz;
rampValue += layerDisplacementNoise.getValue(
currentX * LAYER_NOISE_FREQUENCY, currentY * LAYER_NOISE_FREQUENCY, currentZ * LAYER_NOISE_FREQUENCY
) * (MAX_LAYER_DISPLACEMENT / size);
int layerIndex = Collections.binarySearch(resolvedLayers, new ResolvedLayerEntry(null, 0, rampValue));
if (layerIndex < 0) layerIndex = -2 - layerIndex; // Counter (-insertionIndex - 1) return result, where insertionIndex = layerIndex + 1
ResolvedLayerEntry layerEntry = resolvedLayers.get(layerIndex);
if (distanceSquared > layerEntry.radialThresholdMultiplier)
continue;
float thresholdNoiseValue = Mth.map(
(float) radiusNoise.getValue(currentX * RADIAL_NOISE_FREQUENCY, currentY * RADIAL_NOISE_FREQUENCY, currentZ * RADIAL_NOISE_FREQUENCY),
-1.0f, 1.0f, 1.0f - MAX_RADIAL_THRESHOLD_REDUCTION, 1.0f
);
if (distanceSquared > layerEntry.radialThresholdMultiplier * thresholdNoiseValue)
continue;
LayerPattern.Layer layer = layerEntry.layer;
List<TargetBlockState> targetBlockStates = layer.rollBlock(random);
mutablePos.set(currentX, currentY, currentZ);
if (!worldgenlevel.ensureCanWrite(mutablePos))
if (!worldGenLevel.ensureCanWrite(mutablePos))
continue;
LevelChunkSection levelchunksection = bulksectionaccess.getSection(mutablePos);
if (levelchunksection == null)
LevelChunkSection levelChunkSection = bulkSectionAccess.getSection(mutablePos);
if (levelChunkSection == null)
continue;
int i3 = SectionPos.sectionRelative(currentX);
int j3 = SectionPos.sectionRelative(currentY);
int k3 = SectionPos.sectionRelative(currentZ);
BlockState blockstate = levelchunksection.getBlockState(i3, j3, k3);
int localX = SectionPos.sectionRelative(currentX);
int localY = SectionPos.sectionRelative(currentY);
int localZ = SectionPos.sectionRelative(currentZ);
BlockState blockState = levelChunkSection.getBlockState(localX, localY, localZ);
for (OreConfiguration.TargetBlockState oreconfiguration$targetblockstate : state) {
if (!canPlaceOre(blockstate, bulksectionaccess::getBlockState, random, config,
oreconfiguration$targetblockstate, mutablePos))
for (OreConfiguration.TargetBlockState targetBlockState : targetBlockStates) {
if (!canPlaceOre(blockState, bulkSectionAccess::getBlockState, random, config,
targetBlockState, mutablePos))
continue;
if (oreconfiguration$targetblockstate.state.isAir())
if (targetBlockState.state.isAir())
continue;
levelchunksection.setBlockState(i3, j3, k3, oreconfiguration$targetblockstate.state, false);
levelChunkSection.setBlockState(localX, localY, localZ, targetBlockState.state, false);
++placedAmount;
break;
}
@ -133,7 +172,7 @@ public class LayeredOreFeature extends Feature<LayeredOreConfiguration> {
} catch (Throwable throwable1) {
try {
bulksectionaccess.close();
bulkSectionAccess.close();
} catch (Throwable throwable) {
throwable1.addSuppressed(throwable);
}
@ -141,7 +180,7 @@ public class LayeredOreFeature extends Feature<LayeredOreConfiguration> {
throw throwable1;
}
bulksectionaccess.close();
bulkSectionAccess.close();
return placedAmount > 0;
}
@ -159,4 +198,13 @@ public class LayeredOreFeature extends Feature<LayeredOreConfiguration> {
protected boolean shouldSkipAirCheck(RandomSource pRandom, float pChance) {
return pChance <= 0 ? true : pChance >= 1 ? false : pRandom.nextFloat() >= pChance;
}
private record TemporaryLayerEntry(Layer layer, float size) { }
private record ResolvedLayerEntry(Layer layer, float radialThresholdMultiplier, float rampStartValue) implements Comparable<ResolvedLayerEntry> {
@Override
public int compareTo(LayeredOreFeature.ResolvedLayerEntry b) {
return Float.compare(rampStartValue, b.rampStartValue);
}
}
}