From bfe9767be9390c80ca62cd72208566736ada0f22 Mon Sep 17 00:00:00 2001 From: valoeghese Date: Sat, 29 Feb 2020 23:22:26 +1300 Subject: [PATCH] start caves --- .../litecraft/types/block/Block.java | 13 ++- .../litecraft/types/block/Blocks.java | 10 +- .../halotroop/litecraft/world/World.java | 7 ++ .../litecraft/world/dimension/Dimension.java | 1 + .../litecraft/world/dimension/Dimensions.java | 2 +- .../litecraft/world/gen/CavesModifier.java | 108 ++++++++++++++++++ .../gen/{ => modifier}/WorldModifier.java | 3 +- 7 files changed, 136 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/github/halotroop/litecraft/world/gen/CavesModifier.java rename src/main/java/com/github/halotroop/litecraft/world/gen/{ => modifier}/WorldModifier.java (71%) diff --git a/src/main/java/com/github/halotroop/litecraft/types/block/Block.java b/src/main/java/com/github/halotroop/litecraft/types/block/Block.java index 8d9d073..6a785fb 100644 --- a/src/main/java/com/github/halotroop/litecraft/types/block/Block.java +++ b/src/main/java/com/github/halotroop/litecraft/types/block/Block.java @@ -11,6 +11,7 @@ public class Block { // add properties to this builder! private boolean visible = true; private boolean fullCube = true; + private boolean canCaveCarve = false; private final String identifier; public Properties(String identifier) @@ -27,10 +28,16 @@ public class Block this.visible = visible; return this; } + + public Properties canCaveCarve(boolean canCaveCarve) + { + this.canCaveCarve = canCaveCarve; + return this; + } } public final TexturedModel model; - private final boolean visible, fullCube; + private final boolean visible, fullCube, canCaveCarve; public final String identifier; public boolean isFullCube() @@ -39,6 +46,9 @@ public class Block public boolean isVisible() { return this.visible; } + public boolean canCaveCarve() + { return this.canCaveCarve; } + protected Block(Properties properties) { this((TexturedModel) null, properties); } @@ -51,6 +61,7 @@ public class Block this.visible = properties.visible; this.fullCube = properties.fullCube; this.identifier = properties.identifier; + this.canCaveCarve = properties.canCaveCarve; IDENTIFIER_TO_BLOCK.put(this.identifier, this); } diff --git a/src/main/java/com/github/halotroop/litecraft/types/block/Blocks.java b/src/main/java/com/github/halotroop/litecraft/types/block/Blocks.java index 6a6f29f..11dc827 100644 --- a/src/main/java/com/github/halotroop/litecraft/types/block/Blocks.java +++ b/src/main/java/com/github/halotroop/litecraft/types/block/Blocks.java @@ -5,11 +5,11 @@ import com.github.halotroop.litecraft.types.block.Block.Properties; public final class Blocks { public static final Block AIR = new Block(new Properties("air").visible(false)); - public static final Block DIRT = new Block("block/cubes/soil/dirt.png", new Properties("dirt")); - public static final Block ANDESITE = new Block("block/cubes/stone/basic/andesite.png", new Properties("andesite")); - public static final Block DIORITE = new Block("block/cubes/stone/basic/diorite.png", new Properties("diorite")); - public static final Block GRANITE = new Block("block/cubes/stone/basic/granite.png", new Properties("granite")); - public static final Block GNEISS = new Block("block/cubes/stone/basic/gneiss.png", new Properties("gneiss")); + public static final Block DIRT = new Block("block/cubes/soil/dirt.png", new Properties("dirt").canCaveCarve(true)); + public static final Block ANDESITE = new Block("block/cubes/stone/basic/andesite.png", new Properties("andesite").canCaveCarve(true)); + public static final Block DIORITE = new Block("block/cubes/stone/basic/diorite.png", new Properties("diorite").canCaveCarve(true)); + public static final Block GRANITE = new Block("block/cubes/stone/basic/granite.png", new Properties("granite").canCaveCarve(true)); + public static final Block GNEISS = new Block("block/cubes/stone/basic/gneiss.png", new Properties("gneiss").canCaveCarve(true)); public static Block setup() { return AIR; diff --git a/src/main/java/com/github/halotroop/litecraft/world/World.java b/src/main/java/com/github/halotroop/litecraft/world/World.java index ae312de..61e397b 100644 --- a/src/main/java/com/github/halotroop/litecraft/world/World.java +++ b/src/main/java/com/github/halotroop/litecraft/world/World.java @@ -10,6 +10,7 @@ import com.github.halotroop.litecraft.types.block.*; import com.github.halotroop.litecraft.world.block.BlockRenderer; import com.github.halotroop.litecraft.world.dimension.Dimension; import com.github.halotroop.litecraft.world.gen.*; +import com.github.halotroop.litecraft.world.gen.modifier.WorldModifier; import com.github.hydos.ginger.engine.api.Ginger; import com.github.hydos.ginger.engine.elements.objects.Player; import com.github.hydos.ginger.engine.obj.ModelLoader; @@ -29,6 +30,7 @@ public class World implements BlockAccess, WorldGenConstants public Player player; int renderBound; int renderBoundVertical; + // dummy block instance for retrieving the default block model private final BlockInstance dummy; public World(long seed, int renderSize, Dimension dim, LitecraftSave save) { @@ -39,6 +41,11 @@ public class World implements BlockAccess, WorldGenConstants this.seed = seed; this.chunkGenerator = dim.createChunkGenerator(seed); this.worldModifiers = dim.getWorldModifierArray(); + // initialize world modifiers with seed + for (WorldModifier modifier : this.worldModifiers) + { + modifier.initialize(seed); + } this.genBlockAccess = new GenerationWorld(this); this.save = save; this.dimension = dim.id; diff --git a/src/main/java/com/github/halotroop/litecraft/world/dimension/Dimension.java b/src/main/java/com/github/halotroop/litecraft/world/dimension/Dimension.java index 2ef0180..9739796 100644 --- a/src/main/java/com/github/halotroop/litecraft/world/dimension/Dimension.java +++ b/src/main/java/com/github/halotroop/litecraft/world/dimension/Dimension.java @@ -3,6 +3,7 @@ package com.github.halotroop.litecraft.world.dimension; import java.util.*; import com.github.halotroop.litecraft.world.gen.*; +import com.github.halotroop.litecraft.world.gen.modifier.WorldModifier; import it.unimi.dsi.fastutil.ints.*; diff --git a/src/main/java/com/github/halotroop/litecraft/world/dimension/Dimensions.java b/src/main/java/com/github/halotroop/litecraft/world/dimension/Dimensions.java index 4aa8117..4ce8887 100644 --- a/src/main/java/com/github/halotroop/litecraft/world/dimension/Dimensions.java +++ b/src/main/java/com/github/halotroop/litecraft/world/dimension/Dimensions.java @@ -4,5 +4,5 @@ import com.github.halotroop.litecraft.world.gen.*; public final class Dimensions { - public static final Dimension OVERWORLD = new EarthDimension(0, "earth"); + public static final Dimension OVERWORLD = new EarthDimension(0, "earth").addWorldModifier(new CavesModifier()); } diff --git a/src/main/java/com/github/halotroop/litecraft/world/gen/CavesModifier.java b/src/main/java/com/github/halotroop/litecraft/world/gen/CavesModifier.java new file mode 100644 index 0000000..8289577 --- /dev/null +++ b/src/main/java/com/github/halotroop/litecraft/world/gen/CavesModifier.java @@ -0,0 +1,108 @@ +package com.github.halotroop.litecraft.world.gen; + +import java.util.Random; + +import com.github.halotroop.litecraft.types.block.Blocks; +import com.github.halotroop.litecraft.util.noise.OctaveSimplexNoise; +import com.github.halotroop.litecraft.world.BlockAccess; +import com.github.halotroop.litecraft.world.gen.modifier.WorldModifier; + +public class CavesModifier implements WorldModifier, WorldGenConstants +{ + private OctaveSimplexNoise caveNoise; + private static final double THRESHOLD = 0.3; + // + @Override + public void initialize(long seed) + { + Random rand = new Random(seed); + this.caveNoise = new OctaveSimplexNoise(rand, 2, 45.0, 1.0, 1.0); + } + + @Override + public void modifyWorld(BlockAccess world, Random rand, int chunkStartX, int chunkStartY, int chunkStartZ) + { + final int subChunks = CHUNK_SIZE >> 2; // in 4x4x4 blocks + + for (int subChunkX = 0; subChunkX < subChunks; subChunkX++) + { + int scOffsetX = subChunkX << 2; // sub chunk offset x + int scTotalX = scOffsetX + chunkStartX; + for (int subChunkZ = 0; subChunkZ < subChunks; subChunkZ++) + { + int scOffsetZ = subChunkZ << 2; // sub chunk offset z + int scTotalZ = scOffsetZ + chunkStartZ; + for (int subChunkY = 0; subChunkY < subChunks; subChunkY++) + { + int scOffsetY = subChunkY << 2; // sub chunk offset y + int scTotalY = scOffsetY + chunkStartY; + // calculate noise at each corner of the cube [lower|upper][south|north][west|east] + double noiseLSW = this.caveNoise.sample(scOffsetX, scOffsetY, scOffsetZ); // base = lower south west + double noiseUSW = this.caveNoise.sample(scOffsetX, scOffsetY + 1, scOffsetZ); + double noiseLNW = this.caveNoise.sample(scOffsetX, scOffsetY, scOffsetZ + 1); + double noiseUNW = this.caveNoise.sample(scOffsetX, scOffsetY + 1, scOffsetZ + 1); + double noiseLSE = this.caveNoise.sample(scOffsetX + 1, scOffsetY, scOffsetZ); + double noiseUSE = this.caveNoise.sample(scOffsetX + 1, scOffsetY + 1, scOffsetZ); + double noiseLNE = this.caveNoise.sample(scOffsetX + 1, scOffsetY, scOffsetZ + 1); + double noiseUNE = this.caveNoise.sample(scOffsetX + 1, scOffsetY + 1, scOffsetZ + 1); + // calculate y lerp progresses + // lerp = low + progress * (high - low) + double ypSW = 0.25 * (noiseUSW - noiseLSW); + double ypNW = 0.25 * (noiseUNW - noiseLNW); + double ypSE = 0.25 * (noiseUSE - noiseLSE); + double ypNE = 0.25 * (noiseUNE - noiseLNE); + // initial Y noises + double ySW = noiseLSW; + double ySE = noiseLSE; + double yNW = noiseLNW; + double yNE = noiseLNE; + // loop over y, adding the progress each time + for (int subY = 0; subY < 4; ++subY) + { + int totalY = subY + scTotalY; + // calculate z lerp progresses + double zpW = 0.25 * (yNW - ySW); + double zpE = 0.25 * (yNE - ySE); + // initial Z noises + double zW = ySW; + double zE = ySE; + // loop over z, adding the progress each time + for (int subZ = 0; subZ < 4; ++subZ) + { + int totalZ = subZ + scTotalZ; + // calculate x lerp progress + double lerpProg = 0.25 * (zE - zW); + // initial x noise + double lerpNoise = zW; + // loop over x, adding the progress each time + for (int subX = 0; subX < 4; ++subX) + { + int totalX = subX + scTotalX; + // calculate whether to replace block with air + // if the noise is within the threshold for caves + if (lerpNoise > -THRESHOLD && lerpNoise < THRESHOLD) + { + // if the cave can carve into the block + if (world.getBlock(totalX, totalY, totalZ).canCaveCarve()) + { + world.setBlock(totalX, totalY, totalZ, Blocks.AIR); + } + } + // add progress to the noise + lerpNoise += lerpProg; + } + // add z progresses + zW += zpW; + zE += zpE; + } + // add y progresses + ySW += ypSW; + ySE += ypSE; + yNW += ypNW; + yNE += ypNE; + } + } + } + } + } +} diff --git a/src/main/java/com/github/halotroop/litecraft/world/gen/WorldModifier.java b/src/main/java/com/github/halotroop/litecraft/world/gen/modifier/WorldModifier.java similarity index 71% rename from src/main/java/com/github/halotroop/litecraft/world/gen/WorldModifier.java rename to src/main/java/com/github/halotroop/litecraft/world/gen/modifier/WorldModifier.java index f956dd4..4ab25af 100644 --- a/src/main/java/com/github/halotroop/litecraft/world/gen/WorldModifier.java +++ b/src/main/java/com/github/halotroop/litecraft/world/gen/modifier/WorldModifier.java @@ -1,4 +1,4 @@ -package com.github.halotroop.litecraft.world.gen; +package com.github.halotroop.litecraft.world.gen.modifier; import java.util.Random; @@ -7,4 +7,5 @@ import com.github.halotroop.litecraft.world.BlockAccess; public interface WorldModifier { void modifyWorld(BlockAccess world, Random rand, int chunkStartX, int chunkStartY, int chunkStartZ); + void initialize(long seed); }