adding mroe of this

This commit is contained in:
Brian Neumann-Fopiano committed 2026-08-18 11:52:33 -04:00
1 parent 03746468ec
commit 4adef4576f
17 files changed
+576 -35

No files matched your search

@@ -39,6 +39,10 @@ public final class CarveOrphanSweep {
void markCarved(int localX, int y, int localZ);
default boolean isProtected(int localX, int y, int localZ) {
return false;
}
/**
* Cheap pre-check: may any block in [minY, maxY] be carved at all? Default true keeps
* every implementor correct; the mantle-backed access answers from section slice
@@ -52,12 +56,20 @@ public final class CarveOrphanSweep {
private CarveOrphanSweep() {
}
static int sweepChunk(MantleChunk<Matter> chunk, int[] surfaceHeights, int maxSurfaceBreakDepth, int worldCeilingY) {
static int sweepChunk(
MantleChunk<Matter> chunk,
int[] surfaceHeights,
int maxSurfaceBreakDepth,
int worldCeilingY,
int[] surfaceFluidBoundaryStartY,
int fluidHeight
) {
if (chunk == null) {
return 0;
}
return sweep(surfaceHeights, maxSurfaceBreakDepth, 0, worldCeilingY, new MantleCarveAccess(chunk));
return sweep(surfaceHeights, maxSurfaceBreakDepth, 0, worldCeilingY,
new MantleCarveAccess(chunk, surfaceFluidBoundaryStartY, fluidHeight));
}
public static int sweep(int[] surfaceHeights, int maxSurfaceBreakDepth, int worldFloorY, int worldCeilingY, CarveAccess access) {
@@ -141,7 +153,9 @@ public final class CarveOrphanSweep {
int y = bandFloor + (current / CHUNK_AREA);
if (!anchored) {
if (localX == 0 || localX == CHUNK_SIZE - 1 || localZ == 0 || localZ == CHUNK_SIZE - 1) {
if (access.isProtected(localX, y, localZ)) {
anchored = true;
} else if (localX == 0 || localX == CHUNK_SIZE - 1 || localZ == 0 || localZ == CHUNK_SIZE - 1) {
anchored = true;
} else if (y == bandFloor && isSolidBelowBand(access, surfaceHeights, columnIndex, localX, localZ, bandFloor - 1, worldFloorY)) {
anchored = true;
@@ -215,11 +229,15 @@ public final class CarveOrphanSweep {
private static final class MantleCarveAccess implements CarveAccess {
private final MantleChunk<Matter> chunk;
private final int[] surfaceFluidBoundaryStartY;
private final int fluidHeight;
private MatterSlice<MatterCavern> cachedSlice;
private int cachedSectionIndex = -1;
private MantleCarveAccess(MantleChunk<Matter> chunk) {
private MantleCarveAccess(MantleChunk<Matter> chunk, int[] surfaceFluidBoundaryStartY, int fluidHeight) {
this.chunk = chunk;
this.surfaceFluidBoundaryStartY = surfaceFluidBoundaryStartY;
this.fluidHeight = fluidHeight;
}
@Override
@@ -240,6 +258,12 @@ public final class CarveOrphanSweep {
cachedSlice = null;
}
@Override
public boolean isProtected(int localX, int y, int localZ) {
int columnIndex = PowerOfTwoCoordinates.packLocal16(localX, localZ);
return SurfaceFluidBoundaryPlan.protects(surfaceFluidBoundaryStartY, columnIndex, y, fluidHeight);
}
@Override
public boolean mayContainCarvedCells(int minY, int maxY) {
int minSection = Math.max(0, minY >> 4);
@@ -183,7 +183,7 @@ public class IrisCaveCarver3D {
) {
CaveFluidSupportPlan fluidSupportPlan = new CaveFluidSupportPlan();
int carved = carve(writer, chunkX, chunkZ, columnWeights, minWeight, thresholdPenalty,
worldYRange, precomputedSurfaceHeights, overrideVerticalRange, fluidSupportPlan);
worldYRange, precomputedSurfaceHeights, null, overrideVerticalRange, fluidSupportPlan);
fluidSupportPlan.resolve(writer.acquireChunk(chunkX, chunkZ));
return carved;
}
@@ -197,6 +197,7 @@ public class IrisCaveCarver3D {
double thresholdPenalty,
IrisRange worldYRange,
int[] precomputedSurfaceHeights,
int[] surfaceFluidBoundaryStartY,
IrisRange overrideVerticalRange,
CaveFluidSupportPlan fluidSupportPlan
) {
@@ -317,6 +318,7 @@ public class IrisCaveCarver3D {
surfaceBreakThresholdBoost,
columnMaxY,
fluidMaxY,
surfaceFluidBoundaryStartY,
surfaceBreakFloorY,
surfaceBreakColumn,
columnThreshold,
@@ -339,6 +341,7 @@ public class IrisCaveCarver3D {
surfaceBreakThresholdBoost,
columnMaxY,
fluidMaxY,
surfaceFluidBoundaryStartY,
surfaceBreakFloorY,
surfaceBreakColumn,
columnThreshold,
@@ -364,6 +367,7 @@ public class IrisCaveCarver3D {
surfaceBreakThresholdBoost,
columnMaxY,
fluidMaxY,
surfaceFluidBoundaryStartY,
surfaceBreakFloorY,
surfaceBreakColumn,
columnThreshold,
@@ -387,6 +391,7 @@ public class IrisCaveCarver3D {
surfaceBreakThresholdBoost,
columnMaxY,
fluidMaxY,
surfaceFluidBoundaryStartY,
surfaceBreakFloorY,
surfaceBreakColumn,
columnThreshold,
@@ -417,6 +422,7 @@ public class IrisCaveCarver3D {
double surfaceBreakThresholdBoost,
int[] columnMaxY,
int[] fluidMaxY,
int[] surfaceFluidBoundaryStartY,
int[] surfaceBreakFloorY,
boolean[] surfaceBreakColumn,
double[] columnThreshold,
@@ -472,6 +478,9 @@ public class IrisCaveCarver3D {
}
int columnIndex = activeColumnIndices[activeIndex];
if (SurfaceFluidBoundaryPlan.protects(surfaceFluidBoundaryStartY, columnIndex, y, fluidHeight)) {
continue;
}
planeColumnIndices[planeCount] = columnIndex;
double localThreshold = passThreshold[columnIndex];
if (surfaceBreakColumn[columnIndex] && y >= surfaceBreakFloorY[columnIndex]) {
@@ -544,6 +553,7 @@ public class IrisCaveCarver3D {
double surfaceBreakThresholdBoost,
int[] columnMaxY,
int[] fluidMaxY,
int[] surfaceFluidBoundaryStartY,
int[] surfaceBreakFloorY,
boolean[] surfaceBreakColumn,
double[] columnThreshold,
@@ -605,6 +615,9 @@ public class IrisCaveCarver3D {
}
int columnIndex = activeColumnIndices[activeIndex];
if (SurfaceFluidBoundaryPlan.protects(surfaceFluidBoundaryStartY, columnIndex, y, fluidHeight)) {
continue;
}
planeColumnIndices[planeCount] = columnIndex;
double localThreshold = passThreshold[columnIndex];
if (surfaceBreakColumn[columnIndex] && y >= surfaceBreakFloorY[columnIndex]) {
@@ -699,6 +712,7 @@ public class IrisCaveCarver3D {
double surfaceBreakThresholdBoost,
int[] columnMaxY,
int[] fluidMaxY,
int[] surfaceFluidBoundaryStartY,
int[] surfaceBreakFloorY,
boolean[] surfaceBreakColumn,
double[] columnThreshold,
@@ -800,6 +814,9 @@ public class IrisCaveCarver3D {
}
int index = tileIndices[columnIndex];
if (SurfaceFluidBoundaryPlan.protects(surfaceFluidBoundaryStartY, index, yy, fluidHeight)) {
continue;
}
double localThreshold = passThreshold[index];
if (surfaceBreakColumn[index] && yy >= surfaceBreakFloorY[index]) {
localThreshold += surfaceBreakThresholdBoost;
@@ -844,6 +861,7 @@ public class IrisCaveCarver3D {
double surfaceBreakThresholdBoost,
int[] columnMaxY,
int[] fluidMaxY,
int[] surfaceFluidBoundaryStartY,
int[] surfaceBreakFloorY,
boolean[] surfaceBreakColumn,
double[] columnThreshold,
@@ -891,6 +909,9 @@ public class IrisCaveCarver3D {
int carveMaxY = Math.min(columnTopY, y + sampleStep - 1);
for (int yy = y; yy <= carveMaxY; yy++) {
if (SurfaceFluidBoundaryPlan.protects(surfaceFluidBoundaryStartY, index, yy, fluidHeight)) {
continue;
}
MatterCavern verticalMatter = matterByY[yy - minY];
MatterCavern matter = resolveMatter(verticalMatter, x, yy, z,
index, fluidMaxY, localThreshold);
@@ -30,6 +30,8 @@ import art.arcane.iris.engine.object.IrisDimensionCarvingEntry;
import art.arcane.iris.engine.object.IrisDimensionCarvingResolver;
import art.arcane.iris.engine.object.IrisRegion;
import art.arcane.iris.engine.object.IrisRange;
import art.arcane.iris.spi.PlatformBlockState;
import art.arcane.iris.util.common.data.B;
import art.arcane.iris.util.project.context.ChunkContext;
import art.arcane.iris.util.project.stream.ProceduralStream;
import art.arcane.iris.util.project.stream.utility.ChunkFillableDoubleStream2D;
@@ -102,9 +104,20 @@ public class MantleCarvingComponent extends IrisMantleComponent {
PrecisionStopwatch resolveStopwatch = PrecisionStopwatch.start();
List<WeightedProfile> weightedProfiles = resolveWeightedProfiles(x, z, complex, resolverState);
getEngineMantle().getEngine().getMetrics().getCarveResolve().put(resolveStopwatch.getMilliseconds());
int fluidHeight = getDimension().getFluidHeight();
int[] surfaceFluidBoundaryStartY = blendScratch.surfaceFluidBoundaryStartY;
SurfaceFluidBoundaryPlan.fill(
chunkSurfaceHeights,
blendScratch.fieldSurfaceHeights,
blendScratch.fieldHasFluid,
FIELD_SIZE,
BLEND_RADIUS,
fluidHeight,
surfaceFluidBoundaryStartY
);
CaveFluidSupportPlan fluidSupportPlan = new CaveFluidSupportPlan();
for (WeightedProfile weightedProfile : weightedProfiles) {
carveProfile(weightedProfile, writer, x, z, chunkSurfaceHeights, fluidSupportPlan);
carveProfile(weightedProfile, writer, x, z, chunkSurfaceHeights, surfaceFluidBoundaryStartY, fluidSupportPlan);
}
UpperDimensionContext upperCtx = getEngineMantle().getEngine().getUpperContext();
@@ -118,7 +131,9 @@ public class MantleCarvingComponent extends IrisMantleComponent {
writer.acquireChunk(x, z),
chunkSurfaceHeights,
maxSurfaceBreakDepth(weightedProfiles),
writer.getMantle().getWorldHeight() - 1
writer.getMantle().getWorldHeight() - 1,
surfaceFluidBoundaryStartY,
fluidHeight
);
}
}
@@ -133,10 +148,11 @@ public class MantleCarvingComponent extends IrisMantleComponent {
@ChunkCoordinates
private void carveProfile(WeightedProfile weightedProfile, MantleWriter writer, int cx, int cz,
int[] chunkSurfaceHeights, CaveFluidSupportPlan fluidSupportPlan) {
int[] chunkSurfaceHeights, int[] surfaceFluidBoundaryStartY,
CaveFluidSupportPlan fluidSupportPlan) {
IrisCaveCarver3D carver = getCarver(weightedProfile.profile);
carver.carve(writer, cx, cz, weightedProfile.columnWeights, MIN_WEIGHT, THRESHOLD_PENALTY,
weightedProfile.worldYRange, chunkSurfaceHeights, null, fluidSupportPlan);
weightedProfile.worldYRange, chunkSurfaceHeights, surfaceFluidBoundaryStartY, null, fluidSupportPlan);
}
private void carveUpperTerrain(UpperDimensionContext upperCtx, List<WeightedProfile> normalProfiles,
@@ -189,7 +205,7 @@ public class MantleCarvingComponent extends IrisMantleComponent {
}
IrisCaveCarver3D carver = getCarver(weightedProfile.profile);
carver.carve(writer, cx, cz, weightedProfile.columnWeights, MIN_WEIGHT, THRESHOLD_PENALTY,
constrainedRange, ceilingSurfaceHeights, fullVerticalRange, fluidSupportPlan);
constrainedRange, ceilingSurfaceHeights, null, fullVerticalRange, fluidSupportPlan);
}
}
@@ -459,6 +475,7 @@ public class MantleCarvingComponent extends IrisMantleComponent {
private void prefillProfileFieldSamples(int startX, int startZ, IrisComplex complex, BlendScratch blendScratch) {
fillFieldHeights(complex.getHeightStream(), startX, startZ, blendScratch.fieldSurfaceHeights);
fillFieldFluidPresence(complex.getFluidStream(), startX, startZ, blendScratch.fieldHasFluid);
fillFieldObjects(complex.getRegionStream(), startX, startZ, blendScratch.fieldRegions);
fillFieldObjects(complex.getTrueBiomeStream(), startX, startZ, blendScratch.fieldSurfaceBiomes);
fillFieldObjects(complex.getCaveBiomeStream(), startX, startZ, blendScratch.fieldCaveBiomes);
@@ -482,6 +499,15 @@ public class MantleCarvingComponent extends IrisMantleComponent {
}
}
private void fillFieldFluidPresence(ProceduralStream<PlatformBlockState> stream, int startX, int startZ, boolean[] target) {
for (int fieldX = 0; fieldX < FIELD_SIZE; fieldX++) {
int worldX = startX + fieldX;
for (int fieldZ = 0; fieldZ < FIELD_SIZE; fieldZ++) {
target[(fieldX * FIELD_SIZE) + fieldZ] = B.isFluid(stream.get(worldX, startZ + fieldZ));
}
}
}
private IrisCaveCarver3D getCarver(IrisCaveProfile profile) {
IrisCaveCarver3D carver = profileCarvers.get(profile);
if (carver != null) {
@@ -671,10 +697,12 @@ public class MantleCarvingComponent extends IrisMantleComponent {
private final IdentityHashMap<IrisCaveProfile, Boolean> activeProfiles = new IdentityHashMap<>();
private final List<IrisCaveProfile> profileOrder = new ArrayList<>();
private final double[] fieldSurfaceHeights = new double[FIELD_SIZE * FIELD_SIZE];
private final boolean[] fieldHasFluid = new boolean[FIELD_SIZE * FIELD_SIZE];
private final IrisRegion[] fieldRegions = new IrisRegion[FIELD_SIZE * FIELD_SIZE];
private final IrisBiome[] fieldSurfaceBiomes = new IrisBiome[FIELD_SIZE * FIELD_SIZE];
private final IrisBiome[] fieldCaveBiomes = new IrisBiome[FIELD_SIZE * FIELD_SIZE];
private final int[] chunkSurfaceHeights = new int[CHUNK_AREA];
private final int[] surfaceFluidBoundaryStartY = new int[CHUNK_AREA];
private final double[] chunkSurfaceHeightSamples = new double[CHUNK_AREA];
}
}
@@ -57,6 +57,7 @@ import art.arcane.volmlib.util.documentation.BlockCoordinates;
import art.arcane.volmlib.util.documentation.ChunkCoordinates;
import art.arcane.volmlib.util.mantle.flag.ReservedFlag;
import art.arcane.volmlib.util.math.RNG;
import art.arcane.volmlib.util.matter.MatterCavern;
import art.arcane.volmlib.util.matter.MatterStructurePOI;
import art.arcane.iris.util.project.noise.CNG;
import art.arcane.iris.util.project.noise.NoiseType;
@@ -77,6 +78,7 @@ import java.util.concurrent.atomic.AtomicLong;
public class MantleObjectComponent extends IrisMantleComponent {
private static final long CAVE_REJECT_LOG_THROTTLE_MS = 5000L;
private static final int BEDROCK_CLEARANCE = 6;
private static final byte LIQUID_FORCED_AIR = 3;
private static final Map<String, CaveRejectLogState> CAVE_REJECT_LOG_STATE = new ConcurrentHashMap<>();
private static final Set<String> MISSING_LOAD_KEY_WARNED = ConcurrentHashMap.newKeySet();
@@ -384,11 +386,11 @@ public class MantleObjectComponent extends IrisMantleComponent {
private void placeProceduralObjects(MantleWriter writer, RNG rng, int x, int z, IrisBiome surfaceBiome, IrisBiome caveBiome, IrisRegion region) {
IrisCaveProfile surfaceCaveProfile = resolveCaveProfile(surfaceBiome.getCaveProfile(), region.getCaveProfile());
IrisCaveProfile regionCaveProfile = resolveCaveProfile(region.getCaveProfile(), caveBiome == null ? null : caveBiome.getCaveProfile());
placeProceduralFrom(writer, rng, x, z, surfaceBiome.getProceduralObjects(), surfaceBiome.getName(), surfaceCaveProfile);
placeProceduralFrom(writer, rng, x, z, region.getProceduralObjects(), region.getName(), regionCaveProfile);
placeProceduralFrom(writer, rng, x, z, surfaceBiome.getProceduralObjects(), surfaceBiome.getName(), surfaceCaveProfile, surfaceBiome.getLoadKey());
placeProceduralFrom(writer, rng, x, z, region.getProceduralObjects(), region.getName(), regionCaveProfile, null);
if (caveBiome != null && caveBiome != surfaceBiome) {
IrisCaveProfile caveProfile = resolveCaveProfile(caveBiome.getCaveProfile(), region.getCaveProfile());
placeProceduralFrom(writer, rng, x, z, caveBiome.getProceduralObjects(), caveBiome.getName(), caveProfile);
placeProceduralFrom(writer, rng, x, z, caveBiome.getProceduralObjects(), caveBiome.getName(), caveProfile, caveBiome.getLoadKey());
}
}
@@ -400,7 +402,8 @@ public class MantleObjectComponent extends IrisMantleComponent {
int z,
IrisProceduralObjects proceduralObjects,
String scope,
IrisCaveProfile caveProfile
IrisCaveProfile caveProfile,
String expectedCaveBiomeKey
) {
if (proceduralObjects == null || proceduralObjects.isEmpty()) {
return;
@@ -457,7 +460,8 @@ public class MantleObjectComponent extends IrisMantleComponent {
anchorScanStep,
minDepthBelowSurface,
anchorSearchAttempts,
null,
expectedCaveBiomeKey,
placement.isUnderwater(),
caveAnchorCache
);
}
@@ -561,6 +565,7 @@ public class MantleObjectComponent extends IrisMantleComponent {
int minDepthBelowSurface,
int searchAttempts,
String expectedCaveBiomeKey,
boolean underwater,
CaveAnchorCache anchorCache
) {
for (int search = 0; search < searchAttempts; search++) {
@@ -576,7 +581,13 @@ public class MantleObjectComponent extends IrisMantleComponent {
minDepthBelowSurface,
anchorCache
);
if (candidateY < 0 || caveAnchorBiomeConflicts(candidateX, candidateY, candidateZ, expectedCaveBiomeKey)) {
if (candidateY < 0
|| caveAnchorBiomeConflicts(candidateX, candidateY, candidateZ, expectedCaveBiomeKey)
|| !acceptsCaveAnchorFluid(
underwater,
writer.getDataIfPresent(candidateX, candidateY, candidateZ, MatterCavern.class),
candidateY,
getDimension().getCaveLavaHeight())) {
continue;
}
return new CavePlacementAnchor(candidateX, candidateY, candidateZ);
@@ -584,6 +595,16 @@ public class MantleObjectComponent extends IrisMantleComponent {
return null;
}
static boolean acceptsCaveAnchorFluid(boolean underwater, MatterCavern cavern, int y, int lavaHeight) {
if (cavern == null || !cavern.isCavern()) {
return false;
}
if (underwater || cavern.getLiquid() == LIQUID_FORCED_AIR) {
return true;
}
return cavern.isAir() && y > lavaHeight;
}
private ContainedPlacementResult placeContainedCaveObject(
IObjectPlacer placer,
IrisObject object,
@@ -732,14 +753,18 @@ public class MantleObjectComponent extends IrisMantleComponent {
}
Engine engine = getEngineMantle().getEngine();
IrisBiome at = engine.getCaveBiome(x, y, z);
if (at == null) {
IrisBiome surface = engine.getSurfaceBiome(x, z);
return caveAnchorBiomeConflicts(at, surface, expectedCaveBiomeKey);
}
static boolean caveAnchorBiomeConflicts(IrisBiome at, IrisBiome surface, String expectedCaveBiomeKey) {
if (expectedCaveBiomeKey == null || at == null) {
return false;
}
String atKey = at.getLoadKey();
if (atKey == null || atKey.equals(expectedCaveBiomeKey)) {
return false;
}
IrisBiome surface = engine.getSurfaceBiome(x, z);
if (surface != null && atKey.equals(surface.getLoadKey())) {
return false;
}
@@ -818,6 +843,7 @@ public class MantleObjectComponent extends IrisMantleComponent {
objectMinDepthBelowSurface,
anchorSearchAttempts,
expectedCaveBiomeKey,
objectPlacement.isUnderwater(),
anchorCache
);
@@ -0,0 +1,94 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2022 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package art.arcane.iris.engine.mantle.components;
import art.arcane.volmlib.util.math.PowerOfTwoCoordinates;
final class SurfaceFluidBoundaryPlan {
static final int NO_BOUNDARY = Integer.MAX_VALUE;
private static final int CHUNK_SIZE = 16;
private static final int CHUNK_AREA = CHUNK_SIZE * CHUNK_SIZE;
private SurfaceFluidBoundaryPlan() {
}
static void fill(
int[] chunkSurfaceHeights,
double[] fieldSurfaceHeights,
boolean[] fieldHasFluid,
int fieldSize,
int padding,
int fluidHeight,
int[] boundaryStartY
) {
if (chunkSurfaceHeights == null || chunkSurfaceHeights.length < CHUNK_AREA
|| boundaryStartY == null || boundaryStartY.length < CHUNK_AREA
|| padding < 1 || fieldSize < CHUNK_SIZE + (padding * 2)
|| fieldSurfaceHeights == null || fieldSurfaceHeights.length < fieldSize * fieldSize
|| fieldHasFluid == null || fieldHasFluid.length < fieldSize * fieldSize) {
throw new IllegalArgumentException("Surface fluid boundary fields do not cover a padded chunk");
}
for (int localX = 0; localX < CHUNK_SIZE; localX++) {
int fieldX = localX + padding;
for (int localZ = 0; localZ < CHUNK_SIZE; localZ++) {
int fieldZ = localZ + padding;
int columnIndex = PowerOfTwoCoordinates.packLocal16(localX, localZ);
int boundaryY = NO_BOUNDARY;
int surfaceY = chunkSurfaceHeights[columnIndex];
int fieldIndex = (fieldX * fieldSize) + fieldZ;
if (fieldHasFluid[fieldIndex] && surfaceY < fluidHeight) {
boundaryY = surfaceY;
}
boundaryY = lowerBoundary(boundaryY, fieldSurfaceHeights, fieldHasFluid,
((fieldX - 1) * fieldSize) + fieldZ, fluidHeight);
boundaryY = lowerBoundary(boundaryY, fieldSurfaceHeights, fieldHasFluid,
((fieldX + 1) * fieldSize) + fieldZ, fluidHeight);
boundaryY = lowerBoundary(boundaryY, fieldSurfaceHeights, fieldHasFluid,
(fieldX * fieldSize) + fieldZ - 1, fluidHeight);
boundaryY = lowerBoundary(boundaryY, fieldSurfaceHeights, fieldHasFluid,
(fieldX * fieldSize) + fieldZ + 1, fluidHeight);
boundaryStartY[columnIndex] = boundaryY;
}
}
}
static boolean protects(int[] boundaryStartY, int columnIndex, int y, int fluidHeight) {
return boundaryStartY != null
&& columnIndex >= 0
&& columnIndex < boundaryStartY.length
&& y >= boundaryStartY[columnIndex]
&& y <= fluidHeight;
}
private static int lowerBoundary(
int currentBoundaryY,
double[] fieldSurfaceHeights,
boolean[] fieldHasFluid,
int fieldIndex,
int fluidHeight
) {
int neighborSurfaceY = (int) Math.round(fieldSurfaceHeights[fieldIndex]);
if (!fieldHasFluid[fieldIndex] || neighborSurfaceY >= fluidHeight) {
return currentBoundaryY;
}
return Math.min(currentBoundaryY, neighborSurfaceY + 1);
}
}
@@ -35,7 +35,6 @@ import art.arcane.iris.spi.PlatformBlockState;
public class IrisPostModifier extends EngineAssignedModifier<PlatformBlockState> {
private static final class States {
private static final PlatformBlockState AIR = B.getState("AIR");
private static final PlatformBlockState WATER = B.getState("WATER");
}
private final RNG rng;
@@ -245,10 +244,6 @@ public class IrisPostModifier extends EngineAssignedModifier<PlatformBlockState>
if (w != "true".equals(IrisProceduralBlocks.propertyValue(b, "waterlogged"))) {
setPostBlock(x, h, z, b.withProperty("waterlogged", String.valueOf(w)), originX, originZ, currentData);
}
} else if (IrisProceduralBlocks.materialKey(b).equals("minecraft:air") && h <= fluidHeight) {
if ((isWaterOrWaterlogged(x + 1, h, z, originX, originZ, currentData) || isWaterOrWaterlogged(x - 1, h, z, originX, originZ, currentData) || isWaterOrWaterlogged(x, h, z + 1, originX, originZ, currentData) || isWaterOrWaterlogged(x, h, z - 1, originX, originZ, currentData))) {
setPostBlock(x, h, z, States.WATER, originX, originZ, currentData);
}
}
// Foliage
@@ -1,6 +1,11 @@
package art.arcane.iris.engine.object;
import art.arcane.iris.engine.object.annotations.Desc;
@Desc("Selects which biome identity is checked by a deposit's include and exclude filters.")
public enum IrisDepositBiomeScope {
@Desc("Checks the surface biome selected for the deposit column.")
SURFACE,
@Desc("Checks the cave biome selected at the deposit origin.")
CAVE
}
@@ -1,7 +1,13 @@
package art.arcane.iris.engine.object;
import art.arcane.iris.engine.object.annotations.Desc;
@Desc("Controls how a deposit chooses its origin height within the configured vertical band.")
public enum IrisDepositHeightDistribution {
@Desc("Samples uniformly after clipping the configured band to the terrain and build-height bounds.")
CLIPPED_UNIFORM,
@Desc("Samples uniformly from the configured band, then rejects origins outside the terrain or build-height bounds.")
UNIFORM,
@Desc("Samples toward the middle of the configured band with a triangular distribution, then rejects invalid origins.")
TRIANGLE
}
@@ -1,7 +1,13 @@
package art.arcane.iris.engine.object;
import art.arcane.iris.engine.object.annotations.Desc;
@Desc("Controls which vertical part of the world may contain a deposit origin.")
public enum IrisDepositPlacementScope {
@Desc("Places in solid terrain below the generated surface while preserving the configured surface clearance.")
TERRAIN,
@Desc("Places only in existing solid hosts above the generated terrain surface.")
ABOVE_TERRAIN,
@Desc("Places in existing solid hosts anywhere within the dimension build height.")
FULL_HEIGHT
}
@@ -1,7 +1,13 @@
package art.arcane.iris.engine.object;
import art.arcane.iris.engine.object.annotations.Desc;
@Desc("Selects the geometry used to build each deposit clump.")
public enum IrisDepositShape {
@Desc("Builds the traditional Iris fixed-block-count cube clump.")
IRIS,
@Desc("Builds a chain of overlapping ellipsoids matching Minecraft's ordinary ore-vein geometry.")
VANILLA_ELLIPSOID,
@Desc("Builds sparse candidate offsets matching Minecraft's scattered-ore geometry.")
VANILLA_SCATTERED
}