diff --git a/src/main/java/com/volmit/iris/gen/ParallaxChunkGenerator.java b/src/main/java/com/volmit/iris/gen/ParallaxChunkGenerator.java index e39c08353..bb4896e24 100644 --- a/src/main/java/com/volmit/iris/gen/ParallaxChunkGenerator.java +++ b/src/main/java/com/volmit/iris/gen/ParallaxChunkGenerator.java @@ -100,19 +100,7 @@ public abstract class ParallaxChunkGenerator extends TerrainChunkGenerator imple @Override public int getHighest(int x, int z, boolean ignoreFluid) { - int h = (int) Math.round(ignoreFluid ? getTerrainHeight(x, z) : getTerrainWaterHeight(x, z)); - - if(getDimension().isCarving() && h >= getDimension().getCarvingMin()) - { - while(getGlCarve().isCarved(x, h, z)) - { - h--; - } - - return h; - } - - return h; + return getCarvedHeight(x, z, ignoreFluid); } @Override diff --git a/src/main/java/com/volmit/iris/gen/PostBlockChunkGenerator.java b/src/main/java/com/volmit/iris/gen/PostBlockChunkGenerator.java index 7097ce981..463ed2486 100644 --- a/src/main/java/com/volmit/iris/gen/PostBlockChunkGenerator.java +++ b/src/main/java/com/volmit/iris/gen/PostBlockChunkGenerator.java @@ -184,13 +184,13 @@ public abstract class PostBlockChunkGenerator extends ParallaxChunkGenerator imp @Override public int highestTerrainOrFluidBlock(int x, int z) { - return getHighest(x, z, false); + return (int) getTerrainWaterHeight(x, z); } @Override public int highestTerrainBlock(int x, int z) { - return getHighest(x, z, true); + return (int) getTerrainHeight(x, z); } @Override diff --git a/src/main/java/com/volmit/iris/gen/TerrainChunkGenerator.java b/src/main/java/com/volmit/iris/gen/TerrainChunkGenerator.java index ffe98ef8c..6baa05ac8 100644 --- a/src/main/java/com/volmit/iris/gen/TerrainChunkGenerator.java +++ b/src/main/java/com/volmit/iris/gen/TerrainChunkGenerator.java @@ -76,6 +76,36 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator glCarve = new GenLayerCarve(this, rng.nextParallelRNG(968346576)); } + public int getCarvedHeight(int x, int z, boolean ignoreFluid) + { + if(ignoreFluid) + { + return getCache().getCarvedHeightIgnoreWater(x, z, () -> + { + int h = (int) Math.round(getTerrainHeight(x, z)); + h = getGlCarve().getSurfaceCarve(x, h, z); + return h; + }); + } + + return getCache().getCarvedHeightIgnoreWater(x, z, () -> + { + int h = (int) Math.round(getTerrainWaterHeight(x, z)); + h = getGlCarve().getSurfaceCarve(x, h, z); + return h; + }); + } + + public int getCarvedHeight(int x, int z) + { + return getCarvedHeight(x, z, false); + } + + public int getCarvedWaterHeight(int x, int z) + { + return getCarvedHeight(x, z, true); + } + public KList getCaves(int x, int z) { return glCave.genCaves(x, z, x & 15, z & 15, null); @@ -104,9 +134,10 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator int depth = 0; double noise = getTerrainHeight(rx, rz); int height = (int) Math.round(noise); - boolean carvable = getDimension().isCarving() && height > getDimension().getCarvingMin(); + boolean carvable = getGlCarve().couldCarveBelow(rx, height, rz); IrisRegion region = sampleRegion(rx, rz); IrisBiome biome = sampleTrueBiome(rx, rz, noise); + IrisBiome landBiome = null; if(biome == null) { @@ -114,6 +145,7 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator } KList layers = biome.generateLayers(rx, rz, masterRandom, height, height - getFluidHeight()); + KList cavernLayers = null; KList seaLayers = biome.isAquatic() || biome.isShore() ? biome.generateSeaLayers(rx, rz, masterRandom, fluidHeight - height) : new KList<>(); boolean caverning = false; KList cavernHeights = new KList<>(); @@ -146,7 +178,12 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator { if(biomeMap != null) { - sliver.set(k, biome.getDerivative()); + if(landBiome == null) + { + landBiome = glBiome.generateData(InferredType.LAND, x, z, x, z, region); + } + + sliver.set(k, landBiome.getDerivative()); } sliver.set(k, CAVE_AIR); @@ -189,9 +226,19 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator } // Set Surface Material for cavern layer surfaces - else if(layers.hasIndex(lastCavernHeight - k)) + else if(carvable && cavernHeights.isNotEmpty() && lastCavernHeight - k >= 0 && lastCavernHeight - k < 5) { - block = layers.get(lastCavernHeight - k); + if(landBiome == null) + { + landBiome = glBiome.generateData(InferredType.LAND, x, z, x, z, region); + } + + if(cavernLayers == null) + { + cavernLayers = landBiome.generateLayers(rx, rz, masterRandom, 5, height - getFluidHeight()); + } + + block = cavernLayers.get(lastCavernHeight - k); } // Set Surface Material for true surface @@ -213,7 +260,12 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator // Decorate Cavern surfaces, but not the true surface if((carvable && cavernSurface) && !(k == Math.max(height, fluidHeight) && block.getMaterial().isSolid() && k < 255 && k >= fluidHeight)) { - decorateLand(biome, sliver, wx, k, wz, rx, rz, block); + if(landBiome == null) + { + landBiome = glBiome.generateData(InferredType.LAND, z, x, x, z, region); + } + + decorateLand(landBiome, sliver, wx, k, wz, rx, rz, block); } } @@ -233,7 +285,7 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator } KList floor = caveBiome.generateLayers(wx, wz, rockRandom, i.getFloor() - 2, i.getFloor() - 2); - KList ceiling = caveBiome.generateLayers(wx + 256, wz + 256, rockRandom, height - i.getCeiling() - 2, height - i.getCeiling() - 2); + KList ceiling = caveBiome.generateLayers(wx + 256, wz + 256, rockRandom, (carvable ? getCarvedWaterHeight(rx, rz) : height) - i.getCeiling() - 2, (carvable ? getCarvedWaterHeight(rx, rz) : height) - i.getCeiling() - 2); BlockData blockc = null; for(int j = 0; j < floor.size(); j++) { diff --git a/src/main/java/com/volmit/iris/gen/atomics/AtomicMulticache.java b/src/main/java/com/volmit/iris/gen/atomics/AtomicMulticache.java index d76edf064..2e61b83f0 100644 --- a/src/main/java/com/volmit/iris/gen/atomics/AtomicMulticache.java +++ b/src/main/java/com/volmit/iris/gen/atomics/AtomicMulticache.java @@ -16,6 +16,8 @@ public class AtomicMulticache private int hit = 0; private int miss = 0; private final KMap height; + private final KMap carvedHeight; + private final KMap carvedHeightIgnoreWater; private final KMap biome; private final KMap rawBiome; private final KMap region; @@ -25,6 +27,8 @@ public class AtomicMulticache x = new AtomicInteger(0); z = new AtomicInteger(0); height = new KMap(); + carvedHeight = new KMap(); + carvedHeightIgnoreWater = new KMap(); biome = new KMap(); rawBiome = new KMap(); region = new KMap(); @@ -52,6 +56,16 @@ public class AtomicMulticache height.clear(); } + if(carvedHeight.size() > getLimit()) + { + carvedHeight.clear(); + } + + if(carvedHeightIgnoreWater.size() > getLimit()) + { + carvedHeightIgnoreWater.clear(); + } + if(biome.size() > getLimit()) { biome.clear(); @@ -99,6 +113,56 @@ public class AtomicMulticache return r; } + public int getCarvedHeight(int x, int z, Supplier g) + { + if(broken) + { + return -57841; + } + + long pos = pos(x, z); + Integer r = carvedHeight.get(pos); + + if(r == null) + { + miss++; + r = g.get(); + carvedHeight.put(pos, r); + } + + else + { + hit++; + } + + return r; + } + + public int getCarvedHeightIgnoreWater(int x, int z, Supplier g) + { + if(broken) + { + return -57841; + } + + long pos = pos(x, z); + Integer r = carvedHeightIgnoreWater.get(pos); + + if(r == null) + { + miss++; + r = g.get(); + carvedHeightIgnoreWater.put(pos, r); + } + + else + { + hit++; + } + + return r; + } + public IrisRegion getRegion(int x, int z, Supplier g) { long pos = pos(x, z); diff --git a/src/main/java/com/volmit/iris/gen/atomics/AtomicSliver.java b/src/main/java/com/volmit/iris/gen/atomics/AtomicSliver.java index df6d18590..ea47b70ce 100644 --- a/src/main/java/com/volmit/iris/gen/atomics/AtomicSliver.java +++ b/src/main/java/com/volmit/iris/gen/atomics/AtomicSliver.java @@ -370,6 +370,11 @@ public class AtomicSliver BlockData b = block.get(i); if(b != null) { + if(b.getMaterial().equals(Material.AIR)) + { + continue; + } + currentData.setBlock(x, i, z, b); } } diff --git a/src/main/java/com/volmit/iris/gen/layer/GenLayerCarve.java b/src/main/java/com/volmit/iris/gen/layer/GenLayerCarve.java index 03a56daf2..27a745e08 100644 --- a/src/main/java/com/volmit/iris/gen/layer/GenLayerCarve.java +++ b/src/main/java/com/volmit/iris/gen/layer/GenLayerCarve.java @@ -1,37 +1,79 @@ package com.volmit.iris.gen.layer; import com.volmit.iris.gen.DimensionChunkGenerator; -import com.volmit.iris.noise.CellGenerator; +import com.volmit.iris.object.IrisCarveLayer; import com.volmit.iris.util.GenLayer; -import com.volmit.iris.util.IrisInterpolation; -import com.volmit.iris.util.M; import com.volmit.iris.util.RNG; public class GenLayerCarve extends GenLayer { - private CellGenerator cell; + private boolean couldCarve; + private int minimum; + private int maximum; public GenLayerCarve(DimensionChunkGenerator iris, RNG rng) { super(iris, rng); - cell = new CellGenerator(rng.nextParallelRNG(-135486678)); + + couldCarve = iris.getDimension().isCarving() && iris.getDimension().getCarveLayers().isNotEmpty(); + minimum = 512; + maximum = -256; + + for(IrisCarveLayer i : iris.getDimension().getCarveLayers()) + { + minimum = i.getMinHeight() < minimum ? i.getMinHeight() : minimum; + maximum = i.getMaxHeight() > maximum ? i.getMaxHeight() : maximum; + } + } + + public boolean couldCarve(int x, int y, int z) + { + return couldCarve && y >= minimum && y <= maximum; + } + + public boolean couldCarveBelow(int x, int y, int z) + { + return couldCarve && y <= maximum; + } + + public int getSurfaceCarve(int x, int y, int z) + { + if(couldCarveBelow(x, y, z)) + { + int h = y; + + while(isCarved(x, h, z)) + { + if(h <= 0) + { + break; + } + + h--; + } + + return h; + } + + return y; } public boolean isCarved(int xc, int y, int zc) { - if(y > iris.getDimension().getCarvingMax() || y < iris.getDimension().getCarvingMin()) + if(!couldCarve(xc, y, zc)) { return false; } - double x = ((double) xc / iris.getDimension().getCarvingZoom()); - double z = ((double) zc / iris.getDimension().getCarvingZoom()); + double x = ((double) xc); + double z = ((double) zc); - double opacity = Math.pow(IrisInterpolation.sinCenter(M.lerpInverse(iris.getDimension().getCarvingMin(), iris.getDimension().getCarvingMax(), y)), 4); - - if(cell.getDistance(x - (Math.cos(y / iris.getDimension().getCarvingRippleThickness()) + 0.5D) / 2D, y / iris.getDimension().getCarvingSliverThickness(), z + (Math.sin(y / iris.getDimension().getCarvingRippleThickness()) + 0.5D) / 2D) < opacity * iris.getDimension().getCarvingEnvelope()) + for(IrisCarveLayer i : iris.getDimension().getCarveLayers()) { - return true; + if(i.isCarved(rng, x, y, z)) + { + return true; + } } return false; diff --git a/src/main/java/com/volmit/iris/gen/post/PostSlabber.java b/src/main/java/com/volmit/iris/gen/post/PostSlabber.java index 287161186..03dfc36ba 100644 --- a/src/main/java/com/volmit/iris/gen/post/PostSlabber.java +++ b/src/main/java/com/volmit/iris/gen/post/PostSlabber.java @@ -59,13 +59,10 @@ public class PostSlabber extends IrisPostBlockFilter return; } - if(isAirOrWater(x, h + 2, z, currentPostX, currentPostZ, currentData)) + if(isAirOrWater(x, h + 1, z, currentPostX, currentPostZ, currentData)) { - queue(() -> - { - setPostBlock(x, h + 1, z, d, currentPostX, currentPostZ, currentData); - updateHeight(x, z, h + 1); - }); + setPostBlock(x, h + 1, z, d, currentPostX, currentPostZ, currentData); + updateHeight(x, z, h + 1); } } } diff --git a/src/main/java/com/volmit/iris/gen/post/PostWallPatcher.java b/src/main/java/com/volmit/iris/gen/post/PostWallPatcher.java index cebdeed86..a53ff5d8e 100644 --- a/src/main/java/com/volmit/iris/gen/post/PostWallPatcher.java +++ b/src/main/java/com/volmit/iris/gen/post/PostWallPatcher.java @@ -45,17 +45,8 @@ public class PostWallPatcher extends IrisPostBlockFilter if(ha < h - 2 || hb < h - 2 || hc < h - 2 || hd < h - 2) { + boolean brokeGround = false; int max = Math.abs(Math.max(h - ha, Math.max(h - hb, Math.max(h - hc, h - hd)))); - BlockData s = gen.sampleTrueBiome(x, z).getSlab().get(rng, x, h, z); - - if(s != null) - { - if(!s.getMaterial().equals(AIR)) - { - setPostBlock(x, h + 1, z, s, currentPostX, currentPostZ, currentData); - updateHeight(x, z, h + 1); - } - } for(int i = h; i > h - max; i--) { @@ -63,17 +54,18 @@ public class PostWallPatcher extends IrisPostBlockFilter if(d != null) { - if(d.getMaterial().equals(AIR)) - { - continue; - } - if(isAirOrWater(x, i, z, currentPostX, currentPostZ, currentData)) { + if(brokeGround) + { + return; + } + continue; } setPostBlock(x, i, z, d, currentPostX, currentPostZ, currentData); + brokeGround = true; } } } diff --git a/src/main/java/com/volmit/iris/gen/post/PostWaterlogger.java b/src/main/java/com/volmit/iris/gen/post/PostWaterlogger.java index 1aaacdecd..b568aaa95 100644 --- a/src/main/java/com/volmit/iris/gen/post/PostWaterlogger.java +++ b/src/main/java/com/volmit/iris/gen/post/PostWaterlogger.java @@ -36,21 +36,20 @@ public class PostWaterlogger extends IrisPostBlockFilter if(b instanceof Waterlogged) { Waterlogged ww = (Waterlogged) b; - - if(ww.isWaterlogged()) + boolean w = false; + if(isWaterOrWaterlogged(x, h + 1, z, currentPostX, currentPostZ, currentData)) { - return; + w = true; } - if(isWaterOrWaterlogged(x, h + 1, z, currentPostX, currentPostZ, currentData) && !ww.isWaterlogged()) + else if((isWaterOrWaterlogged(x + 1, h, z, currentPostX, currentPostZ, currentData) || isWaterOrWaterlogged(x - 1, h, z, currentPostX, currentPostZ, currentData) || isWaterOrWaterlogged(x, h, z + 1, currentPostX, currentPostZ, currentData) || isWaterOrWaterlogged(x, h, z - 1, currentPostX, currentPostZ, currentData))) { - ww.setWaterlogged(true); - setPostBlock(x, h, z, ww, currentPostX, currentPostZ, currentData); + w = true; } - else if(!ww.isWaterlogged() && (isWaterOrWaterlogged(x + 1, h, z, currentPostX, currentPostZ, currentData) || isWaterOrWaterlogged(x - 1, h, z, currentPostX, currentPostZ, currentData) || isWaterOrWaterlogged(x, h, z + 1, currentPostX, currentPostZ, currentData) || isWaterOrWaterlogged(x, h, z - 1, currentPostX, currentPostZ, currentData))) + if(w != ww.isWaterlogged()) { - ww.setWaterlogged(true); + ww.setWaterlogged(w); setPostBlock(x, h, z, ww, currentPostX, currentPostZ, currentData); } } diff --git a/src/main/java/com/volmit/iris/object/IrisCarveLayer.java b/src/main/java/com/volmit/iris/object/IrisCarveLayer.java new file mode 100644 index 000000000..50d55feb4 --- /dev/null +++ b/src/main/java/com/volmit/iris/object/IrisCarveLayer.java @@ -0,0 +1,60 @@ +package com.volmit.iris.object; + +import com.volmit.iris.gen.atomics.AtomicCache; +import com.volmit.iris.noise.CNG; +import com.volmit.iris.util.Desc; +import com.volmit.iris.util.DontObfuscate; +import com.volmit.iris.util.IrisInterpolation; +import com.volmit.iris.util.M; +import com.volmit.iris.util.MaxNumber; +import com.volmit.iris.util.MinNumber; +import com.volmit.iris.util.RNG; +import com.volmit.iris.util.Required; + +import lombok.Data; + +@Desc("Translate objects") +@Data +public class IrisCarveLayer +{ + @Required + @DontObfuscate + @Desc("The 4d slope this carve layer follows") + private IrisGeneratorStyle style = new IrisGeneratorStyle(); + + @MaxNumber(512) + @MinNumber(-128) + @DontObfuscate + @Desc("The max height") + private int maxHeight = 220; + + @MaxNumber(512) + @MinNumber(-128) + @DontObfuscate + @Desc("The min height") + private int minHeight = 147; + + @MaxNumber(1) + @MinNumber(0) + @DontObfuscate + @Desc("The threshold used as: \n\ncarved = noise(x,y,z) > threshold") + private double threshold = 0.5; + + private transient AtomicCache cng = new AtomicCache<>(); + + public IrisCarveLayer() + { + + } + + public boolean isCarved(RNG rng, double x, double y, double z) + { + if(y > getMaxHeight() || y < getMinHeight()) + { + return false; + } + + double opacity = Math.pow(IrisInterpolation.sinCenter(M.lerpInverse(getMinHeight(), getMaxHeight(), y)), 4); + return cng.aquire(() -> getStyle().create(rng.nextParallelRNG(-2340 * getMaxHeight() * getMinHeight()))).fitDouble(0D, 1D, x, y, z) * opacity > getThreshold(); + } +} diff --git a/src/main/java/com/volmit/iris/object/IrisDepositGenerator.java b/src/main/java/com/volmit/iris/object/IrisDepositGenerator.java index a18e52e51..a0f8c7e60 100644 --- a/src/main/java/com/volmit/iris/object/IrisDepositGenerator.java +++ b/src/main/java/com/volmit/iris/object/IrisDepositGenerator.java @@ -170,7 +170,7 @@ public class IrisDepositGenerator int x = rng.i(af, bf); int z = rng.i(af, bf); - int height = (int) (Math.round(g.getTerrainHeight((cx << 4) + x, (cz << 4) + z))) - 7; + int height = (int) (Math.round(g.getCarvedWaterHeight((cx << 4) + x, (cz << 4) + z))) - 7; if(height <= 0) { diff --git a/src/main/java/com/volmit/iris/object/IrisDimension.java b/src/main/java/com/volmit/iris/object/IrisDimension.java index 9ef86e5fd..de66aa67c 100644 --- a/src/main/java/com/volmit/iris/object/IrisDimension.java +++ b/src/main/java/com/volmit/iris/object/IrisDimension.java @@ -130,40 +130,6 @@ public class IrisDimension extends IrisRegistrant @Desc("Generate caves or not.") private boolean caves = true; - @DontObfuscate - @Desc("Carve terrain or not") - private double carvingZoom = 3.5; - - @MinNumber(-256) - @MaxNumber(256) - @DontObfuscate - @Desc("Carving starts at this height") - private int carvingMin = 115; - - @MinNumber(-256) - @MaxNumber(256) - @DontObfuscate - @Desc("The maximum height carving happens at") - private int carvingMax = 239; - - @MinNumber(0.0001) - @MaxNumber(256) - @DontObfuscate - @Desc("The thickness of carvings (vertical)") - private double carvingSliverThickness = 5.5D; - - @MinNumber(0.0001) - @MaxNumber(512) - @DontObfuscate - @Desc("The thickness of ripples on carved walls") - private double carvingRippleThickness = 3D; - - @MinNumber(0.0001) - @MaxNumber(512) - @DontObfuscate - @Desc("How much of 3D space is carved out. Higher values make carvings cross into 3d space more often (bigger)") - private double carvingEnvelope = 0.335D; - @DontObfuscate @Desc("Carve terrain or not") private boolean carving = true; @@ -290,6 +256,11 @@ public class IrisDimension extends IrisRegistrant @Desc("Define cave layers") private KList caveLayers = new KList<>(); + @ArrayType(min = 1, type = IrisCarveLayer.class) + @DontObfuscate + @Desc("Define carve layers") + private KList carveLayers = new KList<>(); + @DontObfuscate @Desc("The noise style for fluid types") private IrisGeneratorStyle fluidStyle = NoiseStyle.STATIC.style(); diff --git a/src/main/java/com/volmit/iris/object/IrisStructurePlacement.java b/src/main/java/com/volmit/iris/object/IrisStructurePlacement.java index 13ae6704c..6eb45f19e 100644 --- a/src/main/java/com/volmit/iris/object/IrisStructurePlacement.java +++ b/src/main/java/com/volmit/iris/object/IrisStructurePlacement.java @@ -120,7 +120,7 @@ public class IrisStructurePlacement public void placeLayer(ParallaxChunkGenerator g, RNG rng, RNG rnp, int i, int k, int j, int s, int sh) { - if(!hasStructure(rng, i, k, j)) + if(!hasStructure(g, rng, i, k, j)) { return; } @@ -176,8 +176,13 @@ public class IrisStructurePlacement return structure.aquire(() -> (g == null ? Iris.globaldata : g.getData()).getStructureLoader().load(getTileset())); } - public boolean hasStructure(RNG random, double x, double y, double z) + public boolean hasStructure(ParallaxChunkGenerator g, RNG random, double x, double y, double z) { + if(g.getGlCarve().isCarved((int) x, (int) y, (int) z)) + { + return false; + } + if(getChanceGenerator(random).getIndex(x / zoom, y / zoom, z / zoom, getRarity()) == getRarity() / 2) { return ratio > 0 ? getChanceGenerator(random).getDistance(x / zoom, z / zoom) > ratio : getChanceGenerator(random).getDistance(x / zoom, z / zoom) < Math.abs(ratio);