mirror of
https://github.com/Creators-of-Create/Create.git
synced 2025-02-04 17:34:58 +01:00
Increase layered ore shape variation (#6158)
This commit is contained in:
parent
a41053b896
commit
c92bbdda2d
1 changed files with 112 additions and 64 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue