diff --git a/core/src/main/java/com/volmit/iris/engine/IrisEngineMantle.java b/core/src/main/java/com/volmit/iris/engine/IrisEngineMantle.java index 665897e71..71a412290 100644 --- a/core/src/main/java/com/volmit/iris/engine/IrisEngineMantle.java +++ b/core/src/main/java/com/volmit/iris/engine/IrisEngineMantle.java @@ -24,7 +24,6 @@ import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.mantle.EngineMantle; import com.volmit.iris.engine.mantle.MantleComponent; import com.volmit.iris.engine.mantle.components.MantleCarvingComponent; -import com.volmit.iris.engine.mantle.components.MantleNoiseCarvingComponent; import com.volmit.iris.engine.mantle.components.MantleFluidBodyComponent; import com.volmit.iris.engine.mantle.components.MantleJigsawComponent; import com.volmit.iris.engine.mantle.components.MantleObjectComponent; @@ -59,7 +58,6 @@ public class IrisEngineMantle implements EngineMantle { this.mantle = new Mantle(new File(engine.getWorld().worldFolder(), "mantle"), engine.getTarget().getHeight()); components = new KMap<>(); registerComponent(new MantleCarvingComponent(this)); - registerComponent(new MantleNoiseCarvingComponent(this)); registerComponent(new MantleFluidBodyComponent(this)); jigsaw = new MantleJigsawComponent(this); registerComponent(jigsaw); diff --git a/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleNoiseCarvingComponent.java b/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleNoiseCarvingComponent.java deleted file mode 100644 index c7de1f724..000000000 --- a/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleNoiseCarvingComponent.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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 . - */ - -package com.volmit.iris.engine.mantle.components; - -import com.volmit.iris.engine.data.cache.AtomicCache; -import com.volmit.iris.engine.mantle.ComponentFlag; -import com.volmit.iris.engine.mantle.EngineMantle; -import com.volmit.iris.engine.mantle.IrisMantleComponent; -import com.volmit.iris.engine.mantle.MantleWriter; -import com.volmit.iris.util.context.ChunkContext; -import com.volmit.iris.util.mantle.flag.ReservedFlag; - -/** - * Runs noise carving last and only for the chunk being generated: it never reaches into other chunks, and sampling - * every column's biome and height is too expensive to repeat across the reach of the other components. - */ -@ComponentFlag(ReservedFlag.NOISE_CARVED) -public class MantleNoiseCarvingComponent extends IrisMantleComponent { - private static final int RUNS_AFTER_OBJECTS = 2; - - private final AtomicCache packUsesNoiseCarving = new AtomicCache<>(); - - public MantleNoiseCarvingComponent(EngineMantle engineMantle) { - super(engineMantle, ReservedFlag.NOISE_CARVED, RUNS_AFTER_OBJECTS); - } - - @Override - public void generateLayer(MantleWriter writer, int x, int z, ChunkContext context) { - if (!packUsesNoiseCarving()) { - return; - } - new NoiseTerrainCarver(getEngineMantle().getEngine()).carve(writer, x, z); - } - - @Override - public void hotload() { - super.hotload(); - packUsesNoiseCarving.reset(); - } - - private boolean packUsesNoiseCarving() { - return packUsesNoiseCarving.aquire(() -> getDimension().getAllBiomes(this::getData).stream() - .anyMatch(biome -> biome.getNoiseCarving() != null)); - } - - @Override - protected int computeRadius() { - return 0; - } -} diff --git a/core/src/main/java/com/volmit/iris/engine/mantle/components/NoiseTerrainCarver.java b/core/src/main/java/com/volmit/iris/engine/mantle/components/NoiseTerrainCarver.java deleted file mode 100644 index 5626e25d9..000000000 --- a/core/src/main/java/com/volmit/iris/engine/mantle/components/NoiseTerrainCarver.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * 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 . - */ - -package com.volmit.iris.engine.mantle.components; - -import com.volmit.iris.engine.framework.Engine; -import com.volmit.iris.engine.mantle.MantleWriter; -import com.volmit.iris.engine.object.IrisBiome; -import com.volmit.iris.engine.object.IrisNoiseCarving; -import com.volmit.iris.util.documentation.BlockCoordinates; -import com.volmit.iris.util.documentation.ChunkCoordinates; -import com.volmit.iris.util.math.RNG; -import com.volmit.iris.util.matter.slices.CavernMatter; - -/** - * Sculpts the rock behind cliff faces and slopes of biomes with noise carving, one column at a time. The carved blocks - * become caverns like any other carving, so they get cave walls, floors, ceilings and decoration from the carve pass. - */ -final class NoiseTerrainCarver { - private static final long NOISE_SEED_SALT = 4_096_217L; - private static final int BORDER_FADE_BLOCKS = 16; - private static final int[][] BORDER_PROBES = borderProbes(); - private static final double PROBES_CARVING_AT_BORDER = BORDER_PROBES.length / 2D; - private static final int FACE_RINGS = 3; - private static final int[][] RING_DIRECTIONS = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1}}; - - private final Engine engine; - private final RNG noiseRandom; - private final int fluidHeight; - - NoiseTerrainCarver(Engine engine) { - this.engine = engine; - this.noiseRandom = new RNG(engine.getSeedManager().getCarve()).nextParallelRNG(NOISE_SEED_SALT); - this.fluidHeight = engine.getDimension().getFluidHeight(); - } - - @ChunkCoordinates - void carve(MantleWriter writer, int chunkX, int chunkZ) { - int startX = chunkX << 4; - int startZ = chunkZ << 4; - for (int x = 0; x < 16; x++) { - for (int z = 0; z < 16; z++) { - carveColumn(writer, startX + x, startZ + z); - } - } - } - - // Carving stays above the sea, where hollows next to the water would flood. - @BlockCoordinates - private void carveColumn(MantleWriter writer, int x, int z) { - IrisNoiseCarving carving = noiseCarvingAt(x, z); - if (carving == null) { - return; - } - double borderStrength = borderStrength(x, z); - if (borderStrength <= 0) { - return; - } - int surface = surfaceAt(x, z); - int[] lowestSurfaceByRing = lowestSurfaceByRing(x, z, carving.getReach()); - int lowest = Math.max(lowestSurfaceByRing[FACE_RINGS - 1] + 1, fluidHeight + 1); - double steepness = (surface - lowestSurfaceByRing[0]) / (double) ringDistance(carving.getReach(), 0); - for (int y = lowest; y < surface; y++) { - double strength = borderStrength * faceNearness(y, lowestSurfaceByRing) * carving.strengthBelowCrust(surface - y, steepness); - if (carving.carves(noiseRandom, engine.getData(), x, y, z, strength)) { - writer.setData(x, y, z, CavernMatter.BASIC); - } - } - } - - /** - * The lowest surface on rings of growing size around the column, innermost first. A block above a ring's lowest - * surface has open air beside it within that ring's distance. - */ - private int[] lowestSurfaceByRing(int x, int z, int reach) { - int[] lowest = new int[FACE_RINGS]; - for (int ring = 0; ring < FACE_RINGS; ring++) { - int distance = ringDistance(reach, ring); - int ringLowest = Integer.MAX_VALUE; - for (int[] direction : RING_DIRECTIONS) { - ringLowest = Math.min(ringLowest, surfaceAt(x + direction[0] * distance, z + direction[1] * distance)); - } - lowest[ring] = ring == 0 ? ringLowest : Math.min(ringLowest, lowest[ring - 1]); - } - return lowest; - } - - private static int ringDistance(int reach, int ring) { - return Math.max(1, Math.round(reach * (ring + 1) / (float) FACE_RINGS)); - } - - /** - * How close the block is to a cliff face or slope: 1 when open air is right beside it, falling with each ring - * further out, and 0 deep inside the rock where carving would only make hidden caves. - */ - private static double faceNearness(int y, int[] lowestSurfaceByRing) { - for (int ring = 0; ring < lowestSurfaceByRing.length; ring++) { - if (y > lowestSurfaceByRing[ring]) { - return 1 - ring / (double) lowestSurfaceByRing.length; - } - } - return 0; - } - - private int surfaceAt(int x, int z) { - return (int) Math.round(engine.getComplex().getHeightStream().get(x, z)); - } - - private IrisNoiseCarving noiseCarvingAt(int x, int z) { - IrisBiome biome = engine.getComplex().getTrueBiomeStream().get(x, z); - return biome == null ? null : biome.getNoiseCarving(); - } - - /** - * How fully carving applies at the column: 1 well inside carving biomes, falling to 0 on the border with a biome - * that doesn't carve, so the hollows taper off instead of ending in a straight wall. - */ - private double borderStrength(int x, int z) { - int carvingProbes = 0; - for (int[] probe : BORDER_PROBES) { - if (noiseCarvingAt(x + probe[0], z + probe[1]) != null) { - carvingProbes++; - } - } - double strength = (carvingProbes - PROBES_CARVING_AT_BORDER) / PROBES_CARVING_AT_BORDER; - return Math.max(0, Math.min(1, strength)); - } - - private static int[][] borderProbes() { - int diagonal = (int) Math.round(BORDER_FADE_BLOCKS / Math.sqrt(2)); - return new int[][]{ - {BORDER_FADE_BLOCKS, 0}, {-BORDER_FADE_BLOCKS, 0}, {0, BORDER_FADE_BLOCKS}, {0, -BORDER_FADE_BLOCKS}, - {diagonal, diagonal}, {diagonal, -diagonal}, {-diagonal, diagonal}, {-diagonal, -diagonal} - }; - } -} diff --git a/core/src/main/java/com/volmit/iris/engine/object/IrisBiome.java b/core/src/main/java/com/volmit/iris/engine/object/IrisBiome.java index 24a843125..9ac7ba1bd 100644 --- a/core/src/main/java/com/volmit/iris/engine/object/IrisBiome.java +++ b/core/src/main/java/com/volmit/iris/engine/object/IrisBiome.java @@ -102,8 +102,6 @@ public class IrisBiome extends IrisRegistrant implements IRare { private int lockLayersMax = 7; @Desc("Carving configuration for the dimension") private IrisCarving carving = new IrisCarving(); - @Desc("Sculpts overhangs, arches and cliffs into this biome's terrain with 3D noise. Fades out toward the edges of the biome.") - private IrisNoiseCarving noiseCarving = null; @Desc("Configuration of fluid bodies such as rivers & lakes") private IrisFluidBodies fluidBodies = new IrisFluidBodies(); @MinNumber(1) diff --git a/core/src/main/java/com/volmit/iris/engine/object/IrisNoiseCarving.java b/core/src/main/java/com/volmit/iris/engine/object/IrisNoiseCarving.java deleted file mode 100644 index 7c64cd943..000000000 --- a/core/src/main/java/com/volmit/iris/engine/object/IrisNoiseCarving.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * 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 . - */ - -package com.volmit.iris.engine.object; - -import com.volmit.iris.core.loader.IrisData; -import com.volmit.iris.engine.object.annotations.Desc; -import com.volmit.iris.engine.object.annotations.MaxNumber; -import com.volmit.iris.engine.object.annotations.MinNumber; -import com.volmit.iris.engine.object.annotations.Snippet; -import com.volmit.iris.util.documentation.BlockCoordinates; -import com.volmit.iris.util.math.RNG; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import lombok.experimental.Accessors; - -@Snippet("noise-carving") -@Accessors(chain = true) -@NoArgsConstructor -@AllArgsConstructor -@Desc("Sculpts the rock behind cliff faces and slopes with 3D noise, carving overhangs, arches and ragged cliffs into tall terrain such as mountains. Flat ground and the top of the terrain stay intact, so trees and grass keep their footing.") -@Data -public class IrisNoiseCarving { - private static final int CRUST_FADE_BLOCKS = 3; - private static final int CLIFF_CRUST_THICKNESS = 1; - private static final double GENTLE_SLOPE_RISE_PER_BLOCK = 1; - private static final double CLIFF_RISE_PER_BLOCK = 2; - - @Desc("The 3D noise that shapes the hollows. Rock is removed wherever this noise is below the threshold. Raise the zoom for larger hollows.") - private IrisGeneratorStyle style = new IrisGeneratorStyle(NoiseStyle.SIMPLEX).zoomed(0.3); - - @MinNumber(0) - @MaxNumber(1) - @Desc("How much rock is removed. Rock is carved wherever the noise is below this value, so 0 carves nothing and higher values carve more.") - private double threshold = 0.3; - - @MinNumber(0.1) - @MaxNumber(10) - @Desc("Above 1 stretches the hollows upward into tall arches and spires. Below 1 flattens them into ledges and layered overhangs.") - private double verticalStretch = 1; - - @MinNumber(1) - @Desc("How many blocks of rock under gentle ground are never carved, so it keeps its trees and decoration. Steep cliffs keep only their outer block, so overhangs can open up in them.") - private int crustThickness = 3; - - @MinNumber(3) - @MaxNumber(64) - @Desc("How many blocks into the rock carving reaches from a cliff face or slope. Carving is strongest at the face and fades out toward this distance.") - private int reach = 16; - - /** - * @param strength how strongly carving applies here, from 0 for none to 1 for full - */ - @BlockCoordinates - public boolean carves(RNG rng, IrisData data, int x, int y, int z, double strength) { - double localThreshold = threshold * strength; - if (localThreshold <= 0) { - return false; - } - return style.create(rng, data).noise(x, y / verticalStretch, z) < localThreshold; - } - - /** - * How strongly carving applies at a depth under the surface: 0 inside the crust, easing in below it so the hollows - * don't get a flat ceiling that follows the surface. - * - * @param depth how many blocks below the column's surface the block is - * @param steepness how many blocks the surface around the column drops per block outward - */ - public double strengthBelowCrust(int depth, double steepness) { - double belowCrust = (depth - crustThicknessOn(steepness) + 1) / CRUST_FADE_BLOCKS; - return Math.max(0, Math.min(1, belowCrust)); - } - - private double crustThicknessOn(double steepness) { - double cliffness = (steepness - GENTLE_SLOPE_RISE_PER_BLOCK) / (CLIFF_RISE_PER_BLOCK - GENTLE_SLOPE_RISE_PER_BLOCK); - cliffness = Math.max(0, Math.min(1, cliffness)); - return crustThickness + (CLIFF_CRUST_THICKNESS - crustThickness) * cliffness; - } -} diff --git a/core/src/main/java/com/volmit/iris/util/mantle/flag/MantleFlag.java b/core/src/main/java/com/volmit/iris/util/mantle/flag/MantleFlag.java index f687999e9..77aaa8e89 100644 --- a/core/src/main/java/com/volmit/iris/util/mantle/flag/MantleFlag.java +++ b/core/src/main/java/com/volmit/iris/util/mantle/flag/MantleFlag.java @@ -41,7 +41,6 @@ public sealed interface MantleFlag permits CustomFlag, ReservedFlag { MantleFlag DISCOVERED = ReservedFlag.DISCOVERED; MantleFlag CUSTOM_ACTIVE = ReservedFlag.CUSTOM_ACTIVE; MantleFlag SCRIPT = ReservedFlag.SCRIPT; - MantleFlag NOISE_CARVED = ReservedFlag.NOISE_CARVED; int RESERVED_FLAGS = ReservedFlag.values().length; diff --git a/core/src/main/java/com/volmit/iris/util/mantle/flag/ReservedFlag.java b/core/src/main/java/com/volmit/iris/util/mantle/flag/ReservedFlag.java index 4844269a4..6fb0c97b9 100644 --- a/core/src/main/java/com/volmit/iris/util/mantle/flag/ReservedFlag.java +++ b/core/src/main/java/com/volmit/iris/util/mantle/flag/ReservedFlag.java @@ -17,8 +17,7 @@ public enum ReservedFlag implements MantleFlag { CUSTOM, DISCOVERED, CUSTOM_ACTIVE, - SCRIPT, - NOISE_CARVED; + SCRIPT; @Override public boolean isCustom() {