mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-04-23 00:20:42 +00:00
f
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -27,7 +27,6 @@ import art.arcane.iris.engine.object.*;
|
|||||||
import art.arcane.volmlib.util.collection.KList;
|
import art.arcane.volmlib.util.collection.KList;
|
||||||
import art.arcane.volmlib.util.collection.KMap;
|
import art.arcane.volmlib.util.collection.KMap;
|
||||||
import art.arcane.volmlib.util.collection.KSet;
|
import art.arcane.volmlib.util.collection.KSet;
|
||||||
import art.arcane.volmlib.util.io.IO;
|
|
||||||
import art.arcane.iris.util.common.format.C;
|
import art.arcane.iris.util.common.format.C;
|
||||||
import art.arcane.iris.util.common.misc.ServerProperties;
|
import art.arcane.iris.util.common.misc.ServerProperties;
|
||||||
import art.arcane.iris.util.common.plugin.VolmitSender;
|
import art.arcane.iris.util.common.plugin.VolmitSender;
|
||||||
@@ -42,8 +41,6 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.StandardCopyOption;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@@ -147,42 +144,24 @@ public class ServerConfigurator {
|
|||||||
|
|
||||||
File source = Iris.instance.getDataFolder("datapacks");
|
File source = Iris.instance.getDataFolder("datapacks");
|
||||||
source.mkdirs();
|
source.mkdirs();
|
||||||
File[] datapacks = source.listFiles();
|
ExternalDataPackPipeline.syncPinnedDatapacks(source);
|
||||||
if (datapacks == null || datapacks.length == 0) {
|
int removedLegacyCopies = ExternalDataPackPipeline.removeLegacyWorldDatapackCopies(source, folders);
|
||||||
return;
|
ExternalDataPackPipeline.ImportSummary summary = ExternalDataPackPipeline.importDatapackStructures(source);
|
||||||
|
if (removedLegacyCopies > 0) {
|
||||||
|
Iris.info("Removed " + removedLegacyCopies + " legacy external datapack world copies.");
|
||||||
}
|
}
|
||||||
|
if (summary.getSources() > 0) {
|
||||||
int copied = 0;
|
Iris.info("External datapack structure import: sources=" + summary.getSources()
|
||||||
for (File targetFolder : folders) {
|
+ ", cached=" + summary.getCachedSources()
|
||||||
targetFolder.mkdirs();
|
+ ", scanned=" + summary.getNbtScanned()
|
||||||
for (File entry : datapacks) {
|
+ ", converted=" + summary.getConverted()
|
||||||
if (entry == null || !entry.exists() || entry.getName().startsWith(".")) {
|
+ ", failed=" + summary.getFailed()
|
||||||
continue;
|
+ ", skipped=" + summary.getSkipped()
|
||||||
}
|
+ ", entitiesIgnored=" + summary.getEntitiesIgnored()
|
||||||
|
+ ", blockEntities=" + summary.getBlockEntities());
|
||||||
File output = new File(targetFolder, entry.getName());
|
|
||||||
try {
|
|
||||||
if (entry.isDirectory()) {
|
|
||||||
IO.copyDirectory(entry.toPath(), output.toPath());
|
|
||||||
} else if (entry.isFile()) {
|
|
||||||
File parent = output.getParentFile();
|
|
||||||
if (parent != null) {
|
|
||||||
parent.mkdirs();
|
|
||||||
}
|
|
||||||
Files.copy(entry.toPath(), output.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
copied++;
|
|
||||||
} catch (Throwable e) {
|
|
||||||
Iris.warn("Failed to install datapack \"" + entry.getName() + "\" into \"" + targetFolder.getPath() + "\"");
|
|
||||||
Iris.reportError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (summary.getSources() > 0 || summary.getConverted() > 0) {
|
||||||
if (copied > 0) {
|
Iris.info("External datapack world install is disabled; only structure template import is applied.");
|
||||||
Iris.info("Installed " + copied + " external datapack copy operation" + (copied == 1 ? "" : "s") + " from " + source.getPath());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -222,7 +222,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return getCaveBiome(x, z);
|
return getCaveBiome(x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ChunkCoordinates
|
@ChunkCoordinates
|
||||||
@@ -236,6 +236,28 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
|||||||
return getComplex().getCaveBiomeStream().get(x, z);
|
return getComplex().getCaveBiomeStream().get(x, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@BlockCoordinates
|
||||||
|
default IrisBiome getCaveBiome(int x, int y, int z) {
|
||||||
|
IrisBiome caveBiome = getCaveBiome(x, z);
|
||||||
|
IrisBiome surfaceBiome = getSurfaceBiome(x, z);
|
||||||
|
if (caveBiome == null) {
|
||||||
|
return surfaceBiome;
|
||||||
|
}
|
||||||
|
|
||||||
|
int surfaceY = getComplex().getHeightStream().get(x, z).intValue();
|
||||||
|
int depthBelowSurface = surfaceY - y;
|
||||||
|
if (depthBelowSurface <= 0) {
|
||||||
|
return surfaceBiome;
|
||||||
|
}
|
||||||
|
|
||||||
|
int minDepth = Math.max(0, caveBiome.getCaveMinDepthBelowSurface());
|
||||||
|
if (depthBelowSurface < minDepth) {
|
||||||
|
return surfaceBiome;
|
||||||
|
}
|
||||||
|
|
||||||
|
return caveBiome;
|
||||||
|
}
|
||||||
|
|
||||||
@BlockCoordinates
|
@BlockCoordinates
|
||||||
default IrisBiome getSurfaceBiome(int x, int z) {
|
default IrisBiome getSurfaceBiome(int x, int z) {
|
||||||
return getComplex().getTrueBiomeStream().get(x, z);
|
return getComplex().getTrueBiomeStream().get(x, z);
|
||||||
@@ -514,7 +536,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
|||||||
|
|
||||||
IrisRegion region = getComplex().getRegionStream().get(rx, rz);
|
IrisRegion region = getComplex().getRegionStream().get(rx, rz);
|
||||||
IrisBiome biomeSurface = getComplex().getTrueBiomeStream().get(rx, rz);
|
IrisBiome biomeSurface = getComplex().getTrueBiomeStream().get(rx, rz);
|
||||||
IrisBiome biomeUnder = ry < he ? getComplex().getCaveBiomeStream().get(rx, rz) : biomeSurface;
|
IrisBiome biomeUnder = ry < he ? getCaveBiome(rx, ry, rz) : biomeSurface;
|
||||||
|
|
||||||
double multiplier = 1D * getDimension().getLoot().getMultiplier() * region.getLoot().getMultiplier() * biomeSurface.getLoot().getMultiplier() * biomeUnder.getLoot().getMultiplier();
|
double multiplier = 1D * getDimension().getLoot().getMultiplier() * region.getLoot().getMultiplier() * biomeSurface.getLoot().getMultiplier() * biomeUnder.getLoot().getMultiplier();
|
||||||
boolean fallback = tables.isEmpty();
|
boolean fallback = tables.isEmpty();
|
||||||
@@ -796,7 +818,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
|||||||
|
|
||||||
default IrisBiome getBiome(int x, int y, int z) {
|
default IrisBiome getBiome(int x, int y, int z) {
|
||||||
if (y <= getHeight(x, z) - 2) {
|
if (y <= getHeight(x, z) - 2) {
|
||||||
return getCaveBiome(x, z);
|
return getCaveBiome(x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
return getSurfaceBiome(x, z);
|
return getSurfaceBiome(x, z);
|
||||||
|
|||||||
@@ -98,35 +98,132 @@ public class IrisCaveCarver3D {
|
|||||||
|
|
||||||
int x0 = chunkX << 4;
|
int x0 = chunkX << 4;
|
||||||
int z0 = chunkZ << 4;
|
int z0 = chunkZ << 4;
|
||||||
|
int[] columnSurface = new int[256];
|
||||||
|
int[] columnMaxY = new int[256];
|
||||||
|
int[] surfaceBreakFloorY = new int[256];
|
||||||
|
boolean[] surfaceBreakColumn = new boolean[256];
|
||||||
|
double[] columnThreshold = new double[256];
|
||||||
|
|
||||||
|
for (int lx = 0; lx < 16; lx++) {
|
||||||
|
int x = x0 + lx;
|
||||||
|
for (int lz = 0; lz < 16; lz++) {
|
||||||
|
int z = z0 + lz;
|
||||||
|
int index = (lx << 4) | lz;
|
||||||
|
int columnSurfaceY = engine.getHeight(x, z);
|
||||||
|
int clearanceTopY = Math.min(maxY, Math.max(minY, columnSurfaceY - surfaceClearance));
|
||||||
|
boolean breakColumn = allowSurfaceBreak
|
||||||
|
&& signed(surfaceBreakDensity.noise(x, z)) >= surfaceBreakNoiseThreshold;
|
||||||
|
int columnTopY = breakColumn
|
||||||
|
? Math.min(maxY, Math.max(minY, columnSurfaceY))
|
||||||
|
: clearanceTopY;
|
||||||
|
|
||||||
|
columnSurface[index] = columnSurfaceY;
|
||||||
|
columnMaxY[index] = columnTopY;
|
||||||
|
surfaceBreakFloorY[index] = Math.max(minY, columnSurfaceY - surfaceBreakDepth);
|
||||||
|
surfaceBreakColumn[index] = breakColumn;
|
||||||
|
columnThreshold[index] = profile.getDensityThreshold().get(thresholdRng, x, z, data) - profile.getThresholdBias();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int carved = carvePass(
|
||||||
|
writer,
|
||||||
|
x0,
|
||||||
|
z0,
|
||||||
|
minY,
|
||||||
|
maxY,
|
||||||
|
sampleStep,
|
||||||
|
surfaceBreakThresholdBoost,
|
||||||
|
waterMinDepthBelowSurface,
|
||||||
|
waterRequiresFloor,
|
||||||
|
columnSurface,
|
||||||
|
columnMaxY,
|
||||||
|
surfaceBreakFloorY,
|
||||||
|
surfaceBreakColumn,
|
||||||
|
columnThreshold,
|
||||||
|
0D,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
int minCarveCells = Math.max(0, profile.getMinCarveCells());
|
||||||
|
double recoveryThresholdBoost = Math.max(0, profile.getRecoveryThresholdBoost());
|
||||||
|
if (carved < minCarveCells && recoveryThresholdBoost > 0D) {
|
||||||
|
carved += carvePass(
|
||||||
|
writer,
|
||||||
|
x0,
|
||||||
|
z0,
|
||||||
|
minY,
|
||||||
|
maxY,
|
||||||
|
sampleStep,
|
||||||
|
surfaceBreakThresholdBoost,
|
||||||
|
waterMinDepthBelowSurface,
|
||||||
|
waterRequiresFloor,
|
||||||
|
columnSurface,
|
||||||
|
columnMaxY,
|
||||||
|
surfaceBreakFloorY,
|
||||||
|
surfaceBreakColumn,
|
||||||
|
columnThreshold,
|
||||||
|
recoveryThresholdBoost,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return carved;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int carvePass(
|
||||||
|
MantleWriter writer,
|
||||||
|
int x0,
|
||||||
|
int z0,
|
||||||
|
int minY,
|
||||||
|
int maxY,
|
||||||
|
int sampleStep,
|
||||||
|
double surfaceBreakThresholdBoost,
|
||||||
|
int waterMinDepthBelowSurface,
|
||||||
|
boolean waterRequiresFloor,
|
||||||
|
int[] columnSurface,
|
||||||
|
int[] columnMaxY,
|
||||||
|
int[] surfaceBreakFloorY,
|
||||||
|
boolean[] surfaceBreakColumn,
|
||||||
|
double[] columnThreshold,
|
||||||
|
double thresholdBoost,
|
||||||
|
boolean skipExistingCarved
|
||||||
|
) {
|
||||||
int carved = 0;
|
int carved = 0;
|
||||||
|
|
||||||
for (int x = x0; x < x0 + 16; x++) {
|
for (int lx = 0; lx < 16; lx++) {
|
||||||
for (int z = z0; z < z0 + 16; z++) {
|
int x = x0 + lx;
|
||||||
double threshold = profile.getDensityThreshold().get(thresholdRng, x, z, data) - profile.getThresholdBias();
|
for (int lz = 0; lz < 16; lz++) {
|
||||||
int columnSurface = engine.getHeight(x, z);
|
int z = z0 + lz;
|
||||||
int clearanceTopY = Math.min(maxY, Math.max(minY, columnSurface - surfaceClearance));
|
int index = (lx << 4) | lz;
|
||||||
boolean surfaceBreakColumn = allowSurfaceBreak
|
int columnTopY = columnMaxY[index];
|
||||||
&& signed(surfaceBreakDensity.noise(x, z)) >= surfaceBreakNoiseThreshold;
|
if (columnTopY < minY) {
|
||||||
int columnMaxY = surfaceBreakColumn
|
|
||||||
? Math.min(maxY, Math.max(minY, columnSurface))
|
|
||||||
: clearanceTopY;
|
|
||||||
int surfaceBreakFloorY = Math.max(minY, columnSurface - surfaceBreakDepth);
|
|
||||||
if (columnMaxY < minY) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int y = minY; y <= columnMaxY; y += sampleStep) {
|
boolean breakColumn = surfaceBreakColumn[index];
|
||||||
|
int breakFloorY = surfaceBreakFloorY[index];
|
||||||
|
int surfaceY = columnSurface[index];
|
||||||
|
double threshold = columnThreshold[index] + thresholdBoost;
|
||||||
|
|
||||||
|
for (int y = minY; y <= columnTopY; y += sampleStep) {
|
||||||
double localThreshold = threshold;
|
double localThreshold = threshold;
|
||||||
if (surfaceBreakColumn && y >= surfaceBreakFloorY) {
|
if (breakColumn && y >= breakFloorY) {
|
||||||
localThreshold += surfaceBreakThresholdBoost;
|
localThreshold += surfaceBreakThresholdBoost;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sampleDensity(x, y, z) <= localThreshold) {
|
localThreshold = applyVerticalEdgeFade(localThreshold, y, minY, maxY);
|
||||||
int carveMaxY = Math.min(columnMaxY, y + sampleStep - 1);
|
if (sampleDensity(x, y, z) > localThreshold) {
|
||||||
for (int yy = y; yy <= carveMaxY; yy++) {
|
continue;
|
||||||
writer.setData(x, yy, z, resolveMatter(x, yy, z, localThreshold, waterMinDepthBelowSurface, waterRequiresFloor));
|
}
|
||||||
carved++;
|
|
||||||
|
int carveMaxY = Math.min(columnTopY, y + sampleStep - 1);
|
||||||
|
for (int yy = y; yy <= carveMaxY; yy++) {
|
||||||
|
if (skipExistingCarved && writer.isCarved(x, yy, z)) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
writer.setData(x, yy, z, resolveMatter(x, yy, z, surfaceY, localThreshold, waterMinDepthBelowSurface, waterRequiresFloor));
|
||||||
|
carved++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -135,6 +232,25 @@ public class IrisCaveCarver3D {
|
|||||||
return carved;
|
return carved;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private double applyVerticalEdgeFade(double threshold, int y, int minY, int maxY) {
|
||||||
|
int fadeRange = Math.max(0, profile.getVerticalEdgeFade());
|
||||||
|
if (fadeRange <= 0 || maxY <= minY) {
|
||||||
|
return threshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
int floorDistance = y - minY;
|
||||||
|
int ceilingDistance = maxY - y;
|
||||||
|
int edgeDistance = Math.min(floorDistance, ceilingDistance);
|
||||||
|
if (edgeDistance >= fadeRange) {
|
||||||
|
return threshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
double t = Math.max(0D, Math.min(1D, edgeDistance / (double) fadeRange));
|
||||||
|
double smooth = t * t * (3D - (2D * t));
|
||||||
|
double fadeStrength = Math.max(0D, profile.getVerticalEdgeFadeStrength());
|
||||||
|
return threshold - ((1D - smooth) * fadeStrength);
|
||||||
|
}
|
||||||
|
|
||||||
private double sampleDensity(int x, int y, int z) {
|
private double sampleDensity(int x, int y, int z) {
|
||||||
double warpedX = x;
|
double warpedX = x;
|
||||||
double warpedY = y;
|
double warpedY = y;
|
||||||
@@ -142,9 +258,11 @@ public class IrisCaveCarver3D {
|
|||||||
double warpStrength = profile.getWarpStrength();
|
double warpStrength = profile.getWarpStrength();
|
||||||
|
|
||||||
if (warpStrength > 0) {
|
if (warpStrength > 0) {
|
||||||
double offsetX = signed(warpDensity.noise(x, y, z)) * warpStrength;
|
double warpA = signed(warpDensity.noise(x, y, z));
|
||||||
double offsetY = signed(warpDensity.noise(y, z, x)) * warpStrength;
|
double warpB = signed(warpDensity.noise(x + 31.37D, y - 17.21D, z + 23.91D));
|
||||||
double offsetZ = signed(warpDensity.noise(z, x, y)) * warpStrength;
|
double offsetX = warpA * warpStrength;
|
||||||
|
double offsetY = warpB * warpStrength;
|
||||||
|
double offsetZ = (warpA - warpB) * 0.5D * warpStrength;
|
||||||
warpedX += offsetX;
|
warpedX += offsetX;
|
||||||
warpedY += offsetY;
|
warpedY += offsetY;
|
||||||
warpedZ += offsetZ;
|
warpedZ += offsetZ;
|
||||||
@@ -169,7 +287,7 @@ public class IrisCaveCarver3D {
|
|||||||
return density / normalization;
|
return density / normalization;
|
||||||
}
|
}
|
||||||
|
|
||||||
private MatterCavern resolveMatter(int x, int y, int z, double localThreshold, int waterMinDepthBelowSurface, boolean waterRequiresFloor) {
|
private MatterCavern resolveMatter(int x, int y, int z, int surfaceY, double localThreshold, int waterMinDepthBelowSurface, boolean waterRequiresFloor) {
|
||||||
int lavaHeight = engine.getDimension().getCaveLavaHeight();
|
int lavaHeight = engine.getDimension().getCaveLavaHeight();
|
||||||
int fluidHeight = engine.getDimension().getFluidHeight();
|
int fluidHeight = engine.getDimension().getFluidHeight();
|
||||||
|
|
||||||
@@ -178,7 +296,6 @@ public class IrisCaveCarver3D {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (profile.isAllowWater() && y <= fluidHeight) {
|
if (profile.isAllowWater() && y <= fluidHeight) {
|
||||||
int surfaceY = engine.getHeight(x, z);
|
|
||||||
if (surfaceY - y < waterMinDepthBelowSurface) {
|
if (surfaceY - y < waterMinDepthBelowSurface) {
|
||||||
return carveAir;
|
return carveAir;
|
||||||
}
|
}
|
||||||
@@ -207,7 +324,6 @@ public class IrisCaveCarver3D {
|
|||||||
private boolean hasAquiferCupSupport(int x, int y, int z, double threshold) {
|
private boolean hasAquiferCupSupport(int x, int y, int z, double threshold) {
|
||||||
int floorY = Math.max(0, y - 1);
|
int floorY = Math.max(0, y - 1);
|
||||||
int deepFloorY = Math.max(0, y - 2);
|
int deepFloorY = Math.max(0, y - 2);
|
||||||
int aboveY = Math.min(engine.getHeight() - 1, y + 1);
|
|
||||||
if (!isDensitySolid(x, floorY, z, threshold)) {
|
if (!isDensitySolid(x, floorY, z, threshold)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -229,11 +345,8 @@ public class IrisCaveCarver3D {
|
|||||||
if (isDensitySolid(x, y, z - 1, threshold)) {
|
if (isDensitySolid(x, y, z - 1, threshold)) {
|
||||||
support++;
|
support++;
|
||||||
}
|
}
|
||||||
if (isDensitySolid(x, aboveY, z, threshold)) {
|
|
||||||
support++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return support >= 4;
|
return support >= 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isDensitySolid(int x, int y, int z, double threshold) {
|
private boolean isDensitySolid(int x, int y, int z, double threshold) {
|
||||||
|
|||||||
@@ -50,23 +50,47 @@ public class MantleCarvingComponent extends IrisMantleComponent {
|
|||||||
int xxx = 8 + (x << 4);
|
int xxx = 8 + (x << 4);
|
||||||
int zzz = 8 + (z << 4);
|
int zzz = 8 + (z << 4);
|
||||||
IrisRegion region = getComplex().getRegionStream().get(xxx, zzz);
|
IrisRegion region = getComplex().getRegionStream().get(xxx, zzz);
|
||||||
IrisBiome biome = getComplex().getTrueBiomeStream().get(xxx, zzz);
|
IrisBiome surfaceBiome = getComplex().getTrueBiomeStream().get(xxx, zzz);
|
||||||
carve(writer, rng, x, z, region, biome);
|
IrisCaveProfile caveBiomeProfile = resolveDominantCaveBiomeProfile(x, z);
|
||||||
|
carve(writer, rng, x, z, region, surfaceBiome, caveBiomeProfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ChunkCoordinates
|
@ChunkCoordinates
|
||||||
private void carve(MantleWriter writer, RNG rng, int cx, int cz, IrisRegion region, IrisBiome biome) {
|
private void carve(MantleWriter writer, RNG rng, int cx, int cz, IrisRegion region, IrisBiome surfaceBiome, IrisCaveProfile caveBiomeProfile) {
|
||||||
IrisCaveProfile dimensionProfile = getDimension().getCaveProfile();
|
IrisCaveProfile dimensionProfile = getDimension().getCaveProfile();
|
||||||
IrisCaveProfile biomeProfile = biome.getCaveProfile();
|
IrisCaveProfile surfaceBiomeProfile = surfaceBiome.getCaveProfile();
|
||||||
IrisCaveProfile regionProfile = region.getCaveProfile();
|
IrisCaveProfile regionProfile = region.getCaveProfile();
|
||||||
IrisCaveProfile activeProfile = resolveActiveProfile(dimensionProfile, regionProfile, biomeProfile);
|
IrisCaveProfile activeProfile = resolveActiveProfile(dimensionProfile, regionProfile, surfaceBiomeProfile, caveBiomeProfile);
|
||||||
if (isProfileEnabled(activeProfile)) {
|
if (isProfileEnabled(activeProfile)) {
|
||||||
carveProfile(activeProfile, writer, cx, cz);
|
int carved = carveProfile(activeProfile, writer, cx, cz);
|
||||||
return;
|
if (carved > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activeProfile != regionProfile && isProfileEnabled(regionProfile)) {
|
||||||
|
carved = carveProfile(regionProfile, writer, cx, cz);
|
||||||
|
if (carved > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activeProfile != surfaceBiomeProfile && isProfileEnabled(surfaceBiomeProfile)) {
|
||||||
|
carved = carveProfile(surfaceBiomeProfile, writer, cx, cz);
|
||||||
|
if (carved > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activeProfile != dimensionProfile && isProfileEnabled(dimensionProfile)) {
|
||||||
|
carved = carveProfile(dimensionProfile, writer, cx, cz);
|
||||||
|
if (carved > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
carve(getDimension().getCarving(), writer, nextCarveRng(rng, cx, cz), cx, cz);
|
carve(getDimension().getCarving(), writer, nextCarveRng(rng, cx, cz), cx, cz);
|
||||||
carve(biome.getCarving(), writer, nextCarveRng(rng, cx, cz), cx, cz);
|
carve(surfaceBiome.getCarving(), writer, nextCarveRng(rng, cx, cz), cx, cz);
|
||||||
carve(region.getCarving(), writer, nextCarveRng(rng, cx, cz), cx, cz);
|
carve(region.getCarving(), writer, nextCarveRng(rng, cx, cz), cx, cz);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,13 +104,13 @@ public class MantleCarvingComponent extends IrisMantleComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ChunkCoordinates
|
@ChunkCoordinates
|
||||||
private void carveProfile(IrisCaveProfile profile, MantleWriter writer, int cx, int cz) {
|
private int carveProfile(IrisCaveProfile profile, MantleWriter writer, int cx, int cz) {
|
||||||
if (!isProfileEnabled(profile)) {
|
if (!isProfileEnabled(profile)) {
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
IrisCaveCarver3D carver = getCarver(profile);
|
IrisCaveCarver3D carver = getCarver(profile);
|
||||||
carver.carve(writer, cx, cz);
|
return carver.carve(writer, cx, cz);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IrisCaveCarver3D getCarver(IrisCaveProfile profile) {
|
private IrisCaveCarver3D getCarver(IrisCaveProfile profile) {
|
||||||
@@ -106,9 +130,59 @@ public class MantleCarvingComponent extends IrisMantleComponent {
|
|||||||
return profile != null && profile.isEnabled();
|
return profile != null && profile.isEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
private IrisCaveProfile resolveActiveProfile(IrisCaveProfile dimensionProfile, IrisCaveProfile regionProfile, IrisCaveProfile biomeProfile) {
|
@ChunkCoordinates
|
||||||
if (isProfileEnabled(biomeProfile)) {
|
private IrisCaveProfile resolveDominantCaveBiomeProfile(int chunkX, int chunkZ) {
|
||||||
return biomeProfile;
|
int[] offsets = new int[]{1, 4, 8, 12, 15};
|
||||||
|
Map<IrisCaveProfile, Integer> profileVotes = new IdentityHashMap<>();
|
||||||
|
int validSamples = 0;
|
||||||
|
IrisCaveProfile dominantProfile = null;
|
||||||
|
int dominantVotes = 0;
|
||||||
|
|
||||||
|
for (int offsetX : offsets) {
|
||||||
|
for (int offsetZ : offsets) {
|
||||||
|
int sampleX = (chunkX << 4) + offsetX;
|
||||||
|
int sampleZ = (chunkZ << 4) + offsetZ;
|
||||||
|
int surfaceY = getEngineMantle().getEngine().getHeight(sampleX, sampleZ, true);
|
||||||
|
int sampleY = Math.max(1, surfaceY - 56);
|
||||||
|
IrisBiome caveBiome = getEngineMantle().getEngine().getCaveBiome(sampleX, sampleY, sampleZ);
|
||||||
|
if (caveBiome == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
IrisCaveProfile profile = caveBiome.getCaveProfile();
|
||||||
|
if (!isProfileEnabled(profile)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int votes = profileVotes.getOrDefault(profile, 0) + 1;
|
||||||
|
profileVotes.put(profile, votes);
|
||||||
|
validSamples++;
|
||||||
|
if (votes > dominantVotes) {
|
||||||
|
dominantVotes = votes;
|
||||||
|
dominantProfile = profile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dominantProfile == null || validSamples <= 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
int requiredVotes = Math.max(13, (int) Math.ceil(validSamples * 0.65D));
|
||||||
|
if (dominantVotes < requiredVotes) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dominantProfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IrisCaveProfile resolveActiveProfile(IrisCaveProfile dimensionProfile, IrisCaveProfile regionProfile, IrisCaveProfile surfaceBiomeProfile, IrisCaveProfile caveBiomeProfile) {
|
||||||
|
if (isProfileEnabled(caveBiomeProfile)) {
|
||||||
|
return caveBiomeProfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isProfileEnabled(surfaceBiomeProfile)) {
|
||||||
|
return surfaceBiomeProfile;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isProfileEnabled(regionProfile)) {
|
if (isProfileEnabled(regionProfile)) {
|
||||||
|
|||||||
@@ -64,7 +64,12 @@ public class MantleObjectComponent extends IrisMantleComponent {
|
|||||||
int zzz = 8 + (z << 4);
|
int zzz = 8 + (z << 4);
|
||||||
IrisRegion region = getComplex().getRegionStream().get(xxx, zzz);
|
IrisRegion region = getComplex().getRegionStream().get(xxx, zzz);
|
||||||
IrisBiome surfaceBiome = getComplex().getTrueBiomeStream().get(xxx, zzz);
|
IrisBiome surfaceBiome = getComplex().getTrueBiomeStream().get(xxx, zzz);
|
||||||
IrisBiome caveBiome = getComplex().getCaveBiomeStream().get(xxx, zzz);
|
int surfaceY = getEngineMantle().getEngine().getHeight(xxx, zzz, true);
|
||||||
|
int sampleY = Math.max(1, surfaceY - 48);
|
||||||
|
IrisBiome caveBiome = getEngineMantle().getEngine().getCaveBiome(xxx, sampleY, zzz);
|
||||||
|
if (caveBiome == null) {
|
||||||
|
caveBiome = surfaceBiome;
|
||||||
|
}
|
||||||
if (traceRegen) {
|
if (traceRegen) {
|
||||||
Iris.info("Regen object layer start: chunk=" + x + "," + z
|
Iris.info("Regen object layer start: chunk=" + x + "," + z
|
||||||
+ " surfaceBiome=" + surfaceBiome.getLoadKey()
|
+ " surfaceBiome=" + surfaceBiome.getLoadKey()
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ public class IrisCarveModifier extends EngineAssignedModifier<BlockData> {
|
|||||||
|
|
||||||
walls.forEach((i, v) -> {
|
walls.forEach((i, v) -> {
|
||||||
IrisBiome biome = v.getCustomBiome().isEmpty()
|
IrisBiome biome = v.getCustomBiome().isEmpty()
|
||||||
? getEngine().getCaveBiome(i.getX() + (x << 4), i.getZ() + (z << 4))
|
? getEngine().getCaveBiome(i.getX() + (x << 4), i.getY(), i.getZ() + (z << 4))
|
||||||
: getEngine().getData().getBiomeLoader().load(v.getCustomBiome());
|
: getEngine().getData().getBiomeLoader().load(v.getCustomBiome());
|
||||||
|
|
||||||
if (biome != null) {
|
if (biome != null) {
|
||||||
@@ -207,7 +207,7 @@ public class IrisCarveModifier extends EngineAssignedModifier<BlockData> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
IrisBiome biome = customBiome.isEmpty()
|
IrisBiome biome = customBiome.isEmpty()
|
||||||
? getEngine().getCaveBiome(xx, zz)
|
? getEngine().getCaveBiome(xx, center, zz)
|
||||||
: getEngine().getData().getBiomeLoader().load(customBiome);
|
: getEngine().getData().getBiomeLoader().load(customBiome);
|
||||||
|
|
||||||
if (biome == null) {
|
if (biome == null) {
|
||||||
|
|||||||
@@ -137,6 +137,10 @@ public class IrisBiome extends IrisRegistrant implements IRare {
|
|||||||
@RegistryListResource(IrisBiome.class)
|
@RegistryListResource(IrisBiome.class)
|
||||||
@Desc("The carving biome. If specified the biome will be used when under a carving instead of this current biome.")
|
@Desc("The carving biome. If specified the biome will be used when under a carving instead of this current biome.")
|
||||||
private String carvingBiome = "";
|
private String carvingBiome = "";
|
||||||
|
@MinNumber(0)
|
||||||
|
@MaxNumber(256)
|
||||||
|
@Desc("Minimum depth below terrain surface required before this cave biome can be selected.")
|
||||||
|
private int caveMinDepthBelowSurface = 0;
|
||||||
@Desc("The default slab if iris decides to place a slab in this biome. Default is no slab.")
|
@Desc("The default slab if iris decides to place a slab in this biome. Default is no slab.")
|
||||||
private IrisBiomePaletteLayer slab = new IrisBiomePaletteLayer().zero();
|
private IrisBiomePaletteLayer slab = new IrisBiomePaletteLayer().zero();
|
||||||
@Desc("The default wall if iris decides to place a wall higher than 2 blocks (steep hills or possibly cliffs)")
|
@Desc("The default wall if iris decides to place a wall higher than 2 blocks (steep hills or possibly cliffs)")
|
||||||
|
|||||||
@@ -24,6 +24,16 @@ public class IrisCaveProfile {
|
|||||||
@Desc("Global vertical bounds for profile cave carving.")
|
@Desc("Global vertical bounds for profile cave carving.")
|
||||||
private IrisRange verticalRange = new IrisRange(0, 384);
|
private IrisRange verticalRange = new IrisRange(0, 384);
|
||||||
|
|
||||||
|
@MinNumber(0)
|
||||||
|
@MaxNumber(128)
|
||||||
|
@Desc("Vertical fade range applied near cave profile min/max bounds to avoid abrupt hard-stop ceilings/floors.")
|
||||||
|
private int verticalEdgeFade = 20;
|
||||||
|
|
||||||
|
@MinNumber(0)
|
||||||
|
@MaxNumber(1)
|
||||||
|
@Desc("Strength of the vertical edge fade at cave profile min/max bounds.")
|
||||||
|
private double verticalEdgeFadeStrength = 0.18;
|
||||||
|
|
||||||
@Desc("Base density style for cave field generation.")
|
@Desc("Base density style for cave field generation.")
|
||||||
private IrisGeneratorStyle baseDensityStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style();
|
private IrisGeneratorStyle baseDensityStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style();
|
||||||
|
|
||||||
@@ -58,6 +68,16 @@ public class IrisCaveProfile {
|
|||||||
@Desc("Vertical sample step used while evaluating cave density.")
|
@Desc("Vertical sample step used while evaluating cave density.")
|
||||||
private int sampleStep = 2;
|
private int sampleStep = 2;
|
||||||
|
|
||||||
|
@MinNumber(0)
|
||||||
|
@MaxNumber(4096)
|
||||||
|
@Desc("Minimum carved cells expected from this profile before recovery boost applies.")
|
||||||
|
private int minCarveCells = 0;
|
||||||
|
|
||||||
|
@MinNumber(0)
|
||||||
|
@MaxNumber(1)
|
||||||
|
@Desc("Additional threshold boost used when profile carve output is too sparse.")
|
||||||
|
private double recoveryThresholdBoost = 0.08;
|
||||||
|
|
||||||
@MinNumber(0)
|
@MinNumber(0)
|
||||||
@MaxNumber(64)
|
@MaxNumber(64)
|
||||||
@Desc("Minimum solid clearance below terrain surface where carving may occur.")
|
@Desc("Minimum solid clearance below terrain surface where carving may occur.")
|
||||||
|
|||||||
@@ -205,9 +205,12 @@ public class CustomBiomeSource extends BiomeSource {
|
|||||||
int blockZ = z << 2;
|
int blockZ = z << 2;
|
||||||
int blockY = y << 2;
|
int blockY = y << 2;
|
||||||
int surfaceY = engine.getComplex().getHeightStream().get(blockX, blockZ).intValue();
|
int surfaceY = engine.getComplex().getHeightStream().get(blockX, blockZ).intValue();
|
||||||
boolean underground = blockY <= surfaceY - 2;
|
int caveSwitchY = Math.min(-8, engine.getMinHeight() + 40);
|
||||||
|
boolean deepUnderground = blockY <= caveSwitchY;
|
||||||
|
boolean belowSurface = blockY <= surfaceY - 8;
|
||||||
|
boolean underground = deepUnderground && belowSurface;
|
||||||
IrisBiome irisBiome = underground
|
IrisBiome irisBiome = underground
|
||||||
? engine.getComplex().getCaveBiomeStream().get(blockX, blockZ)
|
? engine.getCaveBiome(blockX, blockY, blockZ)
|
||||||
: engine.getComplex().getTrueBiomeStream().get(blockX, blockZ);
|
: engine.getComplex().getTrueBiomeStream().get(blockX, blockZ);
|
||||||
if (irisBiome == null && underground) {
|
if (irisBiome == null && underground) {
|
||||||
irisBiome = engine.getComplex().getTrueBiomeStream().get(blockX, blockZ);
|
irisBiome = engine.getComplex().getTrueBiomeStream().get(blockX, blockZ);
|
||||||
|
|||||||
Reference in New Issue
Block a user