From b49c1e6e4727810453fbc9ac2f2a8eec6600ae4d Mon Sep 17 00:00:00 2001 From: Daniel Mills Date: Sat, 25 Jan 2020 17:20:32 -0500 Subject: [PATCH] Caves --- .../java/ninja/bytecode/iris/Settings.java | 2 +- .../iris/generator/IrisGenerator.java | 211 +++++++++++++++--- .../iris/generator/layer/GenLayerCaves.java | 121 ++++++++++ .../ninja/bytecode/iris/pack/IrisBiome.java | 32 +-- .../ninja/bytecode/iris/util/BorderCheck.java | 7 + .../ninja/bytecode/iris/util/Borders.java | 44 ++++ .../ninja/bytecode/iris/util/ChunkPlan.java | 29 +++ 7 files changed, 396 insertions(+), 50 deletions(-) create mode 100644 src/main/java/ninja/bytecode/iris/generator/layer/GenLayerCaves.java create mode 100644 src/main/java/ninja/bytecode/iris/util/BorderCheck.java create mode 100644 src/main/java/ninja/bytecode/iris/util/Borders.java diff --git a/src/main/java/ninja/bytecode/iris/Settings.java b/src/main/java/ninja/bytecode/iris/Settings.java index 6e74d906a..7bc215a21 100644 --- a/src/main/java/ninja/bytecode/iris/Settings.java +++ b/src/main/java/ninja/bytecode/iris/Settings.java @@ -42,7 +42,7 @@ public class Settings public double heightScale = 0.56; public double baseHeight = 0.065; public int seaLevel = 63; - public double biomeScale = 1; + public double biomeScale = 0.5; public boolean flatBedrock = false; } } diff --git a/src/main/java/ninja/bytecode/iris/generator/IrisGenerator.java b/src/main/java/ninja/bytecode/iris/generator/IrisGenerator.java index 77ece3faf..4995ade1e 100644 --- a/src/main/java/ninja/bytecode/iris/generator/IrisGenerator.java +++ b/src/main/java/ninja/bytecode/iris/generator/IrisGenerator.java @@ -19,6 +19,7 @@ import ninja.bytecode.iris.generator.atomics.AtomicChunkData; import ninja.bytecode.iris.generator.genobject.GenObjectDecorator; import ninja.bytecode.iris.generator.genobject.PlacedObject; import ninja.bytecode.iris.generator.layer.GenLayerBiome; +import ninja.bytecode.iris.generator.layer.GenLayerCaves; import ninja.bytecode.iris.generator.layer.GenLayerCliffs; import ninja.bytecode.iris.generator.layer.GenLayerLayeredNoise; import ninja.bytecode.iris.generator.layer.GenLayerSnow; @@ -50,14 +51,15 @@ public class IrisGenerator extends ParallaxWorldGenerator MB.of(Material.STONE), MB.of(Material.STONE), MB.of(Material.STONE), + MB.of(Material.STONE), + MB.of(Material.STONE), + MB.of(Material.STONE), MB.of(Material.STONE, 5), MB.of(Material.STONE, 5), - MB.of(Material.COBBLESTONE), - MB.of(Material.COBBLESTONE), - MB.of(Material.SMOOTH_BRICK), - MB.of(Material.SMOOTH_BRICK, 1), - MB.of(Material.SMOOTH_BRICK, 2), - MB.of(Material.SMOOTH_BRICK, 3), + MB.of(Material.STONE, 5), + MB.of(Material.STONE, 5), + MB.of(Material.STONE, 5), + MB.of(Material.STONE, 5) }); //@done private boolean disposed; @@ -70,6 +72,7 @@ public class IrisGenerator extends ParallaxWorldGenerator private GenLayerBiome glBiome; private GenLayerSnow glSnow; private GenLayerCliffs glCliffs; + private GenLayerCaves glCaves; private RNG rTerrain; private CompiledDimension dim; private IrisMetrics metrics = new IrisMetrics(0, 512); @@ -125,6 +128,7 @@ public class IrisGenerator extends ParallaxWorldGenerator glBiome = new GenLayerBiome(this, world, random, rTerrain.nextParallelRNG(4), dim.getBiomes()); glSnow = new GenLayerSnow(this, world, random, rTerrain.nextParallelRNG(5)); glCliffs = new GenLayerCliffs(this, world, random, rTerrain.nextParallelRNG(9)); + glCaves = new GenLayerCaves(this, world, random, rTerrain.nextParallelRNG(10)); scatter = new CNG(rTerrain.nextParallelRNG(52), 1, 1).scale(10); if(Iris.settings.performance.objectMode.equals(ObjectMode.PARALLAX)) @@ -378,6 +382,7 @@ public class IrisGenerator extends ParallaxWorldGenerator hl = hl == 0 && !t.equals(Material.AIR) ? i : hl; } + glCaves.genCaves(wxxf, wzxf, x, z, data, plan); plan.setRealHeight(x, z, hl); plan.setRealWaterHeight(x, z, hw == 0 ? seaLevel : hw); plan.setBiome(x, z, biome); @@ -394,9 +399,9 @@ public class IrisGenerator extends ParallaxWorldGenerator { int x = 0; int z = 0; - int h = 0; + int hhx = 0; int v = 0; - int border = 0; + int borderh = 0; int above = 0; int below = 0; @@ -406,20 +411,20 @@ public class IrisGenerator extends ParallaxWorldGenerator { for(z = 0; z < 16; z++) { - h = plan.getRealHeight(x, z); - border = 0; + hhx = plan.getRealHeight(x, z); + borderh = 0; if(x == 0 || x == 15) { - border++; + borderh++; } if(z == 0 || z == 15) { - border++; + borderh++; } - if(h > Iris.settings.gen.seaLevel - 2) + if(hhx > Iris.settings.gen.seaLevel - 2) { above = 0; below = 0; @@ -428,12 +433,12 @@ public class IrisGenerator extends ParallaxWorldGenerator { v = plan.getRealHeight(x + 1, z); - if(v > h) + if(v > hhx) { above++; } - else if(v < h) + else if(v < hhx) { below++; } @@ -443,12 +448,12 @@ public class IrisGenerator extends ParallaxWorldGenerator { v = plan.getRealHeight(x - 1, z); - if(v > h) + if(v > hhx) { above++; } - else if(v < h) + else if(v < hhx) { below++; } @@ -458,12 +463,12 @@ public class IrisGenerator extends ParallaxWorldGenerator { v = plan.getRealHeight(x, z + 1); - if(v > h) + if(v > hhx) { above++; } - else if(v < h) + else if(v < hhx) { below++; } @@ -473,63 +478,201 @@ public class IrisGenerator extends ParallaxWorldGenerator { v = plan.getRealHeight(x, z - 1); - if(v > h) + if(v > hhx) { above++; } - else if(v < h) + else if(v < hhx) { below++; } } // Patch Hole - if(above >= 4 - border) + if(above >= 4 - borderh) { - data.setBlock(x, h + 1, z, data.getMB(x, h, z)); - plan.setRealHeight(x, z, h + 1); + data.setBlock(x, hhx + 1, z, data.getMB(x, hhx, z)); + plan.setRealHeight(x, z, hhx + 1); } // Remove Nipple - else if(below >= 4 - border) + else if(below >= 4 - borderh) { - data.setBlock(x, h - 1, z, data.getMB(x, h, z)); - data.setBlock(x, h, z, Material.AIR); - plan.setRealHeight(x, z, h - 1); + data.setBlock(x, hhx - 1, z, data.getMB(x, hhx, z)); + data.setBlock(x, hhx, z, Material.AIR); + plan.setRealHeight(x, z, hhx - 1); } // Slab Smoothing else if(below == 0 && above > 0 && f == Iris.settings.gen.blockSmoothing - 1) { - MB d = data.getMB(x, h, z); + MB d = data.getMB(x, hhx, z); if(d.material.equals(Material.STAINED_CLAY) && d.data == 1) { - data.setBlock(x, h + 1, z, Material.STONE_SLAB2); + data.setBlock(x, hhx + 1, z, Material.STONE_SLAB2); } else if(d.material.equals(Material.SAND)) { if(d.data == 0) { - data.setBlock(x, h + 1, z, Material.STEP, (byte) 1); + data.setBlock(x, hhx + 1, z, Material.STEP, (byte) 1); } if(d.data == 1) { - data.setBlock(x, h + 1, z, Material.STONE_SLAB2); + data.setBlock(x, hhx + 1, z, Material.STONE_SLAB2); } } else if(d.material.equals(Material.SNOW_BLOCK)) { - data.setBlock(x, h + 1, z, Material.SNOW, (byte) 4); + data.setBlock(x, hhx + 1, z, Material.SNOW, (byte) 4); } else if(d.material.equals(Material.STONE) || d.material.equals(Material.COBBLESTONE) || d.material.equals(Material.GRAVEL)) { - data.setBlock(x, h + 1, z, Material.STEP, (byte) 3); + data.setBlock(x, hhx + 1, z, Material.STEP, (byte) 3); + } + } + } + + KList hs = plan.getCaveHeights(x, z); + + if(hs != null && !hs.isEmpty()) + { + int h = 0; + int border = 0; + for(int hx : hs) + { + h = hx - 1; + border = 0; + + if(x == 0 || x == 15) + { + border++; + } + + if(z == 0 || z == 15) + { + border++; + } + + if(h > 1) + { + above = 0; + below = 0; + + if(x + 1 <= 15) + { + v = plan.getRealHeight(x + 1, z); + + if(v > h) + { + above++; + } + + else if(v < h) + { + below++; + } + } + + if(x - 1 >= 0) + { + v = plan.getRealHeight(x - 1, z); + + if(v > h) + { + above++; + } + + else if(v < h) + { + below++; + } + } + + if(z + 1 <= 15) + { + v = plan.getRealHeight(x, z + 1); + + if(v > h) + { + above++; + } + + else if(v < h) + { + below++; + } + } + + if(z - 1 >= 0) + { + v = plan.getRealHeight(x, z - 1); + + if(v > h) + { + above++; + } + + else if(v < h) + { + below++; + } + } + + // Patch Hole + if(above >= 4 - border) + { + data.setBlock(x, h + 1, z, data.getMB(x, h, z)); + plan.setRealHeight(x, z, h + 1); + } + + // Remove Nipple + else if(below >= 4 - border) + { + data.setBlock(x, h - 1, z, data.getMB(x, h, z)); + data.setBlock(x, h, z, Material.AIR); + plan.setRealHeight(x, z, h - 1); + } + + // Slab Smoothing + else if(below == 0 && above > 0 && f == Iris.settings.gen.blockSmoothing - 1) + { + MB d = data.getMB(x, h, z); + + if(d.material.equals(Material.STAINED_CLAY) && d.data == 1) + { + data.setBlock(x, h + 1, z, Material.STONE_SLAB2); + } + + else if(d.material.equals(Material.SAND)) + { + if(d.data == 0) + { + data.setBlock(x, h + 1, z, Material.STEP, (byte) 1); + } + + if(d.data == 1) + { + data.setBlock(x, h + 1, z, Material.STONE_SLAB2); + } + } + + else if(d.material.equals(Material.SNOW_BLOCK)) + { + data.setBlock(x, h + 1, z, Material.SNOW, (byte) 4); + } + + else if(d.material.equals(Material.STONE) || d.material.equals(Material.SMOOTH_BRICK) || d.material.equals(Material.COBBLESTONE) || d.material.equals(Material.GRAVEL)) + { + data.setBlock(x, h + 1, z, Material.STEP, (byte) 5); + } + } } } } diff --git a/src/main/java/ninja/bytecode/iris/generator/layer/GenLayerCaves.java b/src/main/java/ninja/bytecode/iris/generator/layer/GenLayerCaves.java new file mode 100644 index 000000000..3009f9b46 --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/generator/layer/GenLayerCaves.java @@ -0,0 +1,121 @@ +package ninja.bytecode.iris.generator.layer; + +import java.util.Random; + +import org.bukkit.Material; +import org.bukkit.World; + +import ninja.bytecode.iris.generator.IrisGenerator; +import ninja.bytecode.iris.generator.atomics.AtomicChunkData; +import ninja.bytecode.iris.util.Borders; +import ninja.bytecode.iris.util.ChunkPlan; +import ninja.bytecode.iris.util.GenLayer; +import ninja.bytecode.iris.util.PolygonGenerator; +import ninja.bytecode.shuriken.math.CNG; +import ninja.bytecode.shuriken.math.RNG; + +public class GenLayerCaves extends GenLayer +{ + private PolygonGenerator g; + private CNG gincline; + private CNG gfract; + + public GenLayerCaves(IrisGenerator iris, World world, Random random, RNG rng) + { + //@builder + super(iris, world, random, rng); + g = new PolygonGenerator(RNG.r, 3, 0.014, 1, (c) -> c); + gincline = new CNG(RNG.r, 1D, 3).scale(0.00652); + gfract = new CNG(RNG.r, 24D, 1).scale(0.0152); + //@done + } + + @Override + public double generateLayer(double gnoise, double dx, double dz) + { + return gnoise; + } + + public void genCaves(double xxf, double zzf, int x, int z, AtomicChunkData data, ChunkPlan plan) + { + int wxxf = (int) (xxf + gfract.noise(xxf, zzf)); + int wzxf = (int) (zzf - gfract.noise(zzf, xxf)); + double itr = 2; + double level = 8; + double incline = 157; + double baseWidth = 11; + double drop = 35; + + for(double m = 1; m <= itr; m += 0.65) + { + double w = baseWidth / m; + + if(w < 3.5) + { + break; + } + + int lowest = 325; + + double n = incline * gincline.noise((wxxf + (m * 10000)), (wzxf - (m * 10000))); + for(double i = 1; i <= w / 3D; i++) + { + if(Borders.isBorderWithin((wxxf + (m * 10000)), (wzxf - (m * 10000)), 17, w / 2D / i, (wxxf / 3D) + (wzxf / 3D), (xx, zz) -> g.getIndex(xx, zz))) + { + int h = (int) ((level + n) - drop); + if(dig(x, (int) (h + i), z, data) && h + i < lowest) + { + lowest = (int) (h + i); + } + + if(dig(x, (int) (h - i), z, data) && h - i < lowest) + { + lowest = (int) (h - i); + } + + if(i == 1) + { + if(dig(x, (int) (h), z, data) && h < lowest) + { + lowest = (int) (h); + } + } + } + } + + if(lowest < 256) + { + plan.setCaveHeight(x, z, lowest); + } + } + } + + public boolean dig(int x, int y, int z, AtomicChunkData data) + { + Material a = data.getType(x, y, z); + Material b = data.getType(x, y, z + 1); + Material c = data.getType(x, y + 1, z); + Material d = data.getType(x + 1, y, z); + Material e = data.getType(x, y, z - 1); + Material f = data.getType(x, y - 1, z); + Material g = data.getType(x - 1, y, z); + + if(can(a) && cann(b) && cann(c) && cann(d) && cann(e) && cann(f) && cann(g)) + { + data.setBlock(x, y, z, Material.AIR); + return true; + } + + return false; + } + + public boolean cann(Material m) + { + return m.isSolid() || m.equals(Material.AIR); + } + + public boolean can(Material m) + { + return m.isSolid(); + } +} diff --git a/src/main/java/ninja/bytecode/iris/pack/IrisBiome.java b/src/main/java/ninja/bytecode/iris/pack/IrisBiome.java index 251b1c02a..24b2fba7a 100644 --- a/src/main/java/ninja/bytecode/iris/pack/IrisBiome.java +++ b/src/main/java/ninja/bytecode/iris/pack/IrisBiome.java @@ -130,10 +130,10 @@ public class IrisBiome cliffScale = 1; cliffChance = 0.37; parent = ""; - dirtDepth = 2; + dirtDepth = 19; this.realBiome = realBiome; this.height = IDEAL_HEIGHT; - rockDepth = 11; + rockDepth = 23; surfaceScale = 1; subSurfaceScale = 1; rockScale = 1; @@ -147,19 +147,21 @@ public class IrisBiome surface(new MB(Material.GRASS)) .dirt(new MB(Material.DIRT), new MB(Material.DIRT, 1)) .rock(MB.of(Material.STONE), - MB.of(Material.STONE), - MB.of(Material.STONE), - MB.of(Material.STONE), - MB.of(Material.STONE), - MB.of(Material.STONE), - MB.of(Material.STONE, 5), - MB.of(Material.STONE, 5), - MB.of(Material.COBBLESTONE), - MB.of(Material.COBBLESTONE), - MB.of(Material.SMOOTH_BRICK), - MB.of(Material.SMOOTH_BRICK, 1), - MB.of(Material.SMOOTH_BRICK, 2), - MB.of(Material.SMOOTH_BRICK, 3)); + MB.of(Material.STONE), + MB.of(Material.STONE), + MB.of(Material.STONE), + MB.of(Material.STONE), + MB.of(Material.STONE), + MB.of(Material.STONE), + MB.of(Material.STONE), + MB.of(Material.STONE), + MB.of(Material.STONE), + MB.of(Material.STONE, 5), + MB.of(Material.STONE, 5), + MB.of(Material.STONE, 5), + MB.of(Material.STONE, 5), + MB.of(Material.STONE, 5), + MB.of(Material.STONE, 5)); //@done } diff --git a/src/main/java/ninja/bytecode/iris/util/BorderCheck.java b/src/main/java/ninja/bytecode/iris/util/BorderCheck.java new file mode 100644 index 000000000..28758325e --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/util/BorderCheck.java @@ -0,0 +1,7 @@ +package ninja.bytecode.iris.util; + +@FunctionalInterface +public interface BorderCheck +{ + public T get(double x, double z); +} diff --git a/src/main/java/ninja/bytecode/iris/util/Borders.java b/src/main/java/ninja/bytecode/iris/util/Borders.java new file mode 100644 index 000000000..adfe50a03 --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/util/Borders.java @@ -0,0 +1,44 @@ +package ninja.bytecode.iris.util; + +import ninja.bytecode.shuriken.math.M; + +public class Borders +{ + public static double getDistanceToBorder(double x, double z, int samples, double minRadius, double maxRadius, double jump, BorderCheck check) + { + double offset = 0; + double fract = 1; + + for(double i = minRadius; i < maxRadius; i += jump * fract) + { + offset += jump / 3D; + fract += 0.333; + + if(isBorderWithin(x, z, samples, maxRadius, offset, check)) + { + return minRadius; + } + } + + return maxRadius; + } + + public static boolean isBorderWithin(double x, double z, int samples, double radius, double offset, BorderCheck check) + { + T center = check.get(x, z); + double ajump = Math.toRadians(360D / (double) samples) + offset; + + for(int i = 0; i < samples; i++) + { + double dx = M.sin((float) ajump * i) * radius; + double dz = M.cos((float) ajump * i) * radius; + + if(!center.equals(check.get(x + dx, z + dz))) + { + return true; + } + } + + return false; + } +} diff --git a/src/main/java/ninja/bytecode/iris/util/ChunkPlan.java b/src/main/java/ninja/bytecode/iris/util/ChunkPlan.java index 8541d3f7e..cf59e0ba2 100644 --- a/src/main/java/ninja/bytecode/iris/util/ChunkPlan.java +++ b/src/main/java/ninja/bytecode/iris/util/ChunkPlan.java @@ -1,17 +1,20 @@ package ninja.bytecode.iris.util; import ninja.bytecode.iris.pack.IrisBiome; +import ninja.bytecode.shuriken.collections.KList; import ninja.bytecode.shuriken.collections.KMap; public class ChunkPlan { private final KMap realHeightCache; + private final KMap> caveHeightCache; private final KMap realWaterHeightCache; private final KMap heightCache; private final KMap biomeCache; public ChunkPlan() { + this.caveHeightCache = new KMap<>(); this.realHeightCache = new KMap<>(); this.realWaterHeightCache = new KMap<>(); this.heightCache = new KMap<>(); @@ -50,6 +53,17 @@ public class ChunkPlan return 0; } + public KList getCaveHeights(int x, int z) + { + SChunkVector c = new SChunkVector(x, z); + if(caveHeightCache.containsKey(c)) + { + return caveHeightCache.get(c); + } + + return null; + } + public int getRealWaterHeight(int x, int z) { SChunkVector c = new SChunkVector(x, z); @@ -77,6 +91,16 @@ public class ChunkPlan heightCache.put(c, h); } + public void setCaveHeight(SChunkVector c, int h) + { + if(!caveHeightCache.containsKey(c)) + { + caveHeightCache.put(c, new KList<>()); + } + + caveHeightCache.get(c).add(h); + } + public void setRealHeight(SChunkVector c, int h) { realHeightCache.put(c, h); @@ -87,6 +111,11 @@ public class ChunkPlan setRealHeight(new SChunkVector(x, z), h); } + public void setCaveHeight(int x, int z, int h) + { + setCaveHeight(new SChunkVector(x, z), h); + } + public void setRealWaterHeight(SChunkVector c, int h) { realWaterHeightCache.put(c, h);