diff --git a/pom.xml b/pom.xml index da68dc77b..1bb4c38dc 100644 --- a/pom.xml +++ b/pom.xml @@ -95,7 +95,7 @@ org.polydev gaea - 1.10.48 + 1.10.80 me.lucko diff --git a/src/main/java/com/dfsek/terra/TerraCommand.java b/src/main/java/com/dfsek/terra/TerraCommand.java index 78a61bdc6..f0ebaea5e 100644 --- a/src/main/java/com/dfsek/terra/TerraCommand.java +++ b/src/main/java/com/dfsek/terra/TerraCommand.java @@ -10,14 +10,13 @@ import com.dfsek.terra.generation.TerraChunkGenerator; import com.dfsek.terra.image.WorldImageGenerator; import com.dfsek.terra.structure.GaeaStructure; import com.dfsek.terra.structure.InitializationException; -import com.dfsek.terra.structure.StructureSpawn; +import com.dfsek.terra.procgen.GridSpawn; import com.sk89q.worldedit.IncompleteRegionException; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; import org.bukkit.Location; -import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; @@ -33,7 +32,6 @@ import java.io.File; import java.io.IOException; import java.util.Collections; import java.util.List; -import java.util.Map; import java.util.Random; public class TerraCommand implements CommandExecutor, TabExecutor { @@ -189,7 +187,7 @@ public class TerraCommand implements CommandExecutor, TabExecutor { } return true; } else if("getspawn".equals(args[1])) { - Vector v = new StructureSpawn(250, 250).getNearestSpawn(pl.getLocation().getBlockX(), pl.getLocation().getBlockZ(), pl.getWorld().getSeed()); + Vector v = new GridSpawn(250, 250).getNearestSpawn(pl.getLocation().getBlockX(), pl.getLocation().getBlockZ(), pl.getWorld().getSeed()); sender.sendMessage(v.getBlockX() + ":" + v.getBlockZ()); } } diff --git a/src/main/java/com/dfsek/terra/TerraTree.java b/src/main/java/com/dfsek/terra/TerraTree.java index 2805057dd..94c2c16b9 100644 --- a/src/main/java/com/dfsek/terra/TerraTree.java +++ b/src/main/java/com/dfsek/terra/TerraTree.java @@ -45,8 +45,8 @@ public enum TerraTree implements Tree { } @Override - public void plant(Location location, Random random, boolean b, JavaPlugin javaPlugin) { - if(!validSpawns.contains(location.clone().subtract(0, 1, 0).getBlock().getType())) return; + public boolean plant(Location location, Random random, boolean b, JavaPlugin javaPlugin) { + if(!validSpawns.contains(location.clone().subtract(0, 1, 0).getBlock().getType())) return false; NMSStructure temp = getInstance(location, random); int[] size = temp.getDimensions(); switch(random.nextInt(4)) { @@ -67,6 +67,6 @@ public enum TerraTree implements Tree { break; } temp.paste(); - //location.getBlock().setType(Material.GOLD_BLOCK); + return true; } } diff --git a/src/main/java/com/dfsek/terra/carving/Cavern.java b/src/main/java/com/dfsek/terra/carving/Cavern.java new file mode 100644 index 000000000..1bb0925ea --- /dev/null +++ b/src/main/java/com/dfsek/terra/carving/Cavern.java @@ -0,0 +1,50 @@ +package com.dfsek.terra.carving; + +import com.dfsek.terra.procgen.GridSpawn; +import com.dfsek.terra.procgen.voxel.DeformedSphere; +import com.dfsek.terra.procgen.voxel.Tube; +import com.dfsek.terra.procgen.voxel.VoxelGeometry; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.util.Vector; +import org.polydev.gaea.math.FastNoise; +import org.polydev.gaea.math.MathUtil; +import org.polydev.gaea.world.carving.CarvingData; + +import java.util.Random; + +public class Cavern { + private final Node node; + private final long seed; + public Cavern(World w) { + this.node = new Node(w); + this.seed = w.getSeed(); + } + public VoxelGeometry carveChunk(int chunkX, int chunkZ) { + long seedC = MathUtil.getCarverChunkSeed(chunkX, chunkZ, seed); + Random chunk = new Random(seedC); + Vector org = node.getNodeLocation((chunkX << 4)+8, (chunkZ << 4)+8).clone().setY(chunk.nextInt(128)); + VoxelGeometry carve = VoxelGeometry.getBlank(); + + FastNoise smpl = new FastNoise((int) seedC); + smpl.setFrequency(0.01f); + smpl.setNoiseType(FastNoise.NoiseType.Simplex); + Bukkit.getLogger().info("Cavern: " + org.toString()); + carve.merge(new DeformedSphere(org.clone(), chunk.nextInt(4)+3, 0.75, smpl)); + + Vector _00 = new Vector(org.getX()+16, new Random(MathUtil.getCarverChunkSeed(chunkX+1, chunkZ, seed)).nextInt(128), org.getZ()); + + carve.merge(new Tube(org, _00, 4)); + return carve; + } + public static class Node { + private final long seed; + private final GridSpawn spawn = new GridSpawn(16, 0); + public Node(World w) { + this.seed = w.getSeed(); + } + public Vector getNodeLocation(int x, int z) { + return spawn.getNearestSpawn(x, z, seed); + } + } +} diff --git a/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java b/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java index c68d5b8ff..4d27d6ac2 100644 --- a/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java +++ b/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java @@ -10,6 +10,8 @@ import org.polydev.gaea.generation.GenerationPhase; import org.polydev.gaea.world.carving.Carver; import org.polydev.gaea.world.carving.Worm; +import java.util.HashMap; +import java.util.Map; import java.util.Random; public class UserDefinedCarver extends Carver { @@ -21,6 +23,7 @@ public class UserDefinedCarver extends Carver { private final int hash; private final int topCut; private final int bottomCut; + public UserDefinedCarver(Range height, Range radius, Range length, double[] start, double[] mutate, double[] radiusMultiplier, int hash, int topCut, int bottomCut) { super(height.getMin(), height.getMax()); this.radius = radius; @@ -36,7 +39,7 @@ public class UserDefinedCarver extends Carver { @Override public Worm getWorm(long l, Vector vector) { Random r = new Random(l+hash); - return new UserDefinedWorm(length.get(r), r, vector, radius.getMax(), topCut, bottomCut); + return new UserDefinedWorm((int) (length.get(r)/2), r, vector, radius.getMax(), topCut, bottomCut); } @Override @@ -54,7 +57,7 @@ public class UserDefinedCarver extends Carver { super.setBottomCut(bottomCut); runningRadius = radius.get(r); this.maxRad = maxRad; - direction = new Vector((r.nextDouble()-0.5D)*start[0], (r.nextDouble()-0.5D)*start[1], (r.nextDouble()-0.5D)*start[2]).normalize(); + direction = new Vector((r.nextDouble()-0.5D)*start[0], (r.nextDouble()-0.5D)*start[1], (r.nextDouble()-0.5D)*start[2]).normalize().multiply(2); } @Override @@ -62,9 +65,9 @@ public class UserDefinedCarver extends Carver { setRadius(new int[] {(int) (runningRadius*radiusMultiplier[0]), (int) (runningRadius*radiusMultiplier[1]), (int) (runningRadius*radiusMultiplier[2])}); runningRadius += (getRandom().nextDouble()-0.5)*mutate[3]; runningRadius = Math.max(Math.min(runningRadius, maxRad), 1); - direction.rotateAroundX(Math.toRadians(getRandom().nextDouble()*mutate[0])); - direction.rotateAroundY(Math.toRadians(getRandom().nextDouble()*mutate[1])); - direction.rotateAroundZ(Math.toRadians(getRandom().nextDouble()*mutate[2])); + direction.rotateAroundX(Math.toRadians(getRandom().nextDouble()*mutate[0]*2)); + direction.rotateAroundY(Math.toRadians(getRandom().nextDouble()*mutate[1]*2)); + direction.rotateAroundZ(Math.toRadians(getRandom().nextDouble()*mutate[2]*2)); getRunning().add(direction); } } diff --git a/src/main/java/com/dfsek/terra/config/genconfig/OreConfig.java b/src/main/java/com/dfsek/terra/config/genconfig/OreConfig.java index 835b83773..722cdeae5 100644 --- a/src/main/java/com/dfsek/terra/config/genconfig/OreConfig.java +++ b/src/main/java/com/dfsek/terra/config/genconfig/OreConfig.java @@ -1,6 +1,5 @@ package com.dfsek.terra.config.genconfig; -import com.dfsek.terra.config.ConfigLoader; import com.dfsek.terra.config.ConfigUtil; import com.dfsek.terra.config.TerraConfigObject; import org.bukkit.Bukkit; @@ -9,7 +8,6 @@ import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; import org.bukkit.configuration.InvalidConfigurationException; -import org.bukkit.plugin.java.JavaPlugin; import org.polydev.gaea.math.FastNoise; import java.io.File; diff --git a/src/main/java/com/dfsek/terra/config/genconfig/StructureConfig.java b/src/main/java/com/dfsek/terra/config/genconfig/StructureConfig.java index 177c6da69..6690d6ed9 100644 --- a/src/main/java/com/dfsek/terra/config/genconfig/StructureConfig.java +++ b/src/main/java/com/dfsek/terra/config/genconfig/StructureConfig.java @@ -6,9 +6,7 @@ import com.dfsek.terra.config.ConfigUtil; import com.dfsek.terra.config.TerraConfigObject; import com.dfsek.terra.population.StructurePopulator; import com.dfsek.terra.structure.GaeaStructure; -import com.dfsek.terra.structure.StructureSpawn; -import com.dfsek.terra.structure.StructureSpawnRequirement; -import org.bukkit.Bukkit; +import com.dfsek.terra.procgen.GridSpawn; import org.bukkit.configuration.InvalidConfigurationException; import java.io.File; @@ -20,7 +18,7 @@ import java.util.Objects; public class StructureConfig extends TerraConfigObject { private static final Map configs = new HashMap<>(); private GaeaStructure structure; - private StructureSpawn spawn; + private GridSpawn spawn; private String id; private Range searchStart; private Range bound; @@ -42,7 +40,7 @@ public class StructureConfig extends TerraConfigObject { } if(!contains("id")) throw new InvalidConfigurationException("No ID specified!"); id = getString("id"); - spawn = new StructureSpawn(getInt("spawn.width", 500), getInt("spawn.padding", 100)); + spawn = new GridSpawn(getInt("spawn.width", 500), getInt("spawn.padding", 100)); searchStart = new Range(getInt("spawn.start.min", 72), getInt("spawn.start.max", 72)); bound = new Range(getInt("spawn.bound.min", 48), getInt("spawn.bound.max", 72)); try { @@ -62,7 +60,7 @@ public class StructureConfig extends TerraConfigObject { return structure; } - public StructureSpawn getSpawn() { + public GridSpawn getSpawn() { return spawn; } diff --git a/src/main/java/com/dfsek/terra/generation/SlabGenerator.java b/src/main/java/com/dfsek/terra/generation/SlabGenerator.java index 8483c6133..02028b196 100644 --- a/src/main/java/com/dfsek/terra/generation/SlabGenerator.java +++ b/src/main/java/com/dfsek/terra/generation/SlabGenerator.java @@ -37,59 +37,13 @@ public class SlabGenerator extends GenerationPopulator { if(config.getSlabs() == null) continue; double thresh = config.getSlabThreshold(); for(int y = 0; y < world.getMaxHeight(); y++) { - if(chunk.getType(x, y, z).isSolid()) continue; - prepareBlockPart(interp, chunk, new Vector(x, y, z), config.getSlabs(), config.getStairs(), thresh); + } } } return chunk; } - private static void prepareBlockPart(ChunkInterpolator interp, ChunkGenerator.ChunkData chunk, Vector block, Map> slabs, Map> stairs, double thresh) { - BlockData down = chunk.getBlockData(block.getBlockX(), block.getBlockY()-1, block.getBlockZ()); - double _11 = interp.getNoise(block.getBlockX(), block.getBlockY() - 0.4, block.getBlockZ()); - if(_11 > thresh) { - BlockData orig = chunk.getBlockData(block.getBlockX(), block.getBlockY(), block.getBlockZ()); - //double _00 = interp.getNoise(block.getBlockX() - 0.5, block.getBlockY(), block.getBlockZ() - 0.5); - double _01 = interp.getNoise(block.getBlockX() - 0.5, block.getBlockY(), block.getBlockZ()); - //double _02 = interp.getNoise(block.getBlockX() - 0.5, block.getBlockY(), block.getBlockZ() + 0.5); - double _10 = interp.getNoise(block.getBlockX(), block.getBlockY(), block.getBlockZ() - 0.5); - double _12 = interp.getNoise(block.getBlockX(), block.getBlockY(), block.getBlockZ() + 0.5); - //double _20 = interp.getNoise(block.getBlockX() + 0.5, block.getBlockY(), block.getBlockZ() - 0.5); - double _21 = interp.getNoise(block.getBlockX() + 0.5, block.getBlockY(), block.getBlockZ()); - //double _22 = interp.getNoise(block.getBlockX() + 0.5, block.getBlockY(), block.getBlockZ() + 0.5); - if(stairs != null) { - Palette stairPalette = stairs.get(down.getMaterial()); - if(stairPalette != null) { - BlockData stair = stairPalette.get(0, block.getBlockX(), block.getBlockZ()); - Stairs finalStair = getStair(new double[] {_01, _10, _12, _21}, (Stairs) stair, thresh); - if(finalStair != null) { - if(orig.matches(WATER)) finalStair.setWaterlogged(true); - chunk.setBlock(block.getBlockX(), block.getBlockY(), block.getBlockZ(), finalStair); - return; - } - } - } - BlockData slab = slabs.getOrDefault(down.getMaterial(), AIRPALETTE).get(0, block.getBlockX(), block.getBlockZ()); - if(slab instanceof Waterlogged) { - ((Waterlogged) slab).setWaterlogged(orig.matches(WATER)); - } else if(orig.matches(WATER)) return; - chunk.setBlock(block.getBlockX(), block.getBlockY(), block.getBlockZ(), slab); - } - } - private static Stairs getStair(double[] vals, Stairs stair, double thresh) { - if(vals.length != 4) throw new IllegalArgumentException(); - Stairs stairNew = (Stairs) stair.clone(); - if(vals[0] > thresh) { - stairNew.setFacing(BlockFace.WEST); - } else if(vals[1] > thresh) { - stairNew.setFacing(BlockFace.NORTH); - } else if(vals[2] > thresh) { - stairNew.setFacing(BlockFace.SOUTH); - } else if(vals[3] > thresh) { - stairNew.setFacing(BlockFace.EAST); - } else return null; - return stairNew; - } + } diff --git a/src/main/java/com/dfsek/terra/generation/TerraChunkGenerator.java b/src/main/java/com/dfsek/terra/generation/TerraChunkGenerator.java index c805b3d2c..313f485e0 100644 --- a/src/main/java/com/dfsek/terra/generation/TerraChunkGenerator.java +++ b/src/main/java/com/dfsek/terra/generation/TerraChunkGenerator.java @@ -1,8 +1,8 @@ package com.dfsek.terra.generation; +import com.dfsek.terra.Terra; import com.dfsek.terra.biome.TerraBiomeGrid; import com.dfsek.terra.biome.UserDefinedBiome; -import com.dfsek.terra.config.WorldConfig; import com.dfsek.terra.config.genconfig.BiomeConfig; import com.dfsek.terra.population.CavePopulator; import com.dfsek.terra.population.FloraPopulator; @@ -13,11 +13,15 @@ import com.dfsek.terra.structure.StructureSpawnRequirement; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.World; +import org.bukkit.block.BlockFace; import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.Waterlogged; +import org.bukkit.block.data.type.Stairs; import org.bukkit.generator.BlockPopulator; +import org.bukkit.generator.ChunkGenerator; +import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; import org.polydev.gaea.biome.Biome; -import org.polydev.gaea.biome.BiomeGrid; import org.polydev.gaea.generation.GaeaChunkGenerator; import org.polydev.gaea.generation.GenerationPhase; import org.polydev.gaea.generation.GenerationPopulator; @@ -25,6 +29,7 @@ import org.polydev.gaea.math.ChunkInterpolator; import org.polydev.gaea.math.FastNoise; import org.polydev.gaea.population.PopulationManager; import org.polydev.gaea.world.palette.Palette; +import org.polydev.gaea.world.palette.RandomPalette; import java.io.FileNotFoundException; import java.io.IOException; @@ -36,10 +41,10 @@ import java.util.Map; import java.util.Random; public class TerraChunkGenerator extends GaeaChunkGenerator { - private static final BlockData STONE = Material.STONE.createBlockData(); - private static final BlockData WATER = Material.WATER.createBlockData(); - private final PopulationManager popMan = new PopulationManager(); + private final PopulationManager popMan = new PopulationManager(Terra.getInstance()); private boolean needsLoad = true; + + private static final Map popMap = new HashMap<>(); public TerraChunkGenerator() { @@ -58,21 +63,79 @@ public class TerraChunkGenerator extends GaeaChunkGenerator { int zOrig = (chunkZ << 4); for(byte x = 0; x < 16; x++) { for(byte z = 0; z < 16; z++) { + int paletteLevel = 0; + int cx = xOrig + x; + int cz = zOrig + z; Biome b = getBiomeGrid(world).getBiome(xOrig+x, zOrig+z, GenerationPhase.PALETTE_APPLY); BiomeConfig c = BiomeConfig.fromBiome((UserDefinedBiome) b); int sea = c.getSeaLevel(); Palette seaPalette = c.getOceanPalette(); - for(int y = 0; y < 256; y++) { - if(super.getInterpolatedNoise(x, y, z) > 0) chunk.setBlock(x, y, z, STONE); - else if(y <= sea) { + for(int y = world.getMaxHeight()-1; y >= 0; y--) { + BlockData data; + if(super.getInterpolatedNoise(x, y, z) > 0) { + data = b.getGenerator().getPalette(y).get(paletteLevel, cx, cz); + chunk.setBlock(x, y, z, data); + if(paletteLevel == 0 && c.getSlabs() != null) { + prepareBlockPart(data, chunk.getBlockData(x, y+1, z), chunk, new Vector(x, y+1, z), c.getSlabs(), c.getStairs(), c.getSlabThreshold()); + } + paletteLevel++; + } else if(y <= sea) { chunk.setBlock(x, y, z, seaPalette.get(sea-y, x+xOrig, z+zOrig)); - } + paletteLevel = 0; + } else paletteLevel = 0; } } } return chunk; } + private void prepareBlockPart(BlockData down, BlockData orig, ChunkData chunk, Vector block, Map> slabs, Map> stairs, double thresh) { + double _11 = getInterpolatedNoise(block.getBlockX(), block.getBlockY() - 0.4, block.getBlockZ()); + if(_11 > thresh) { + //double _00 = interp.getNoise(block.getBlockX() - 0.5, block.getBlockY(), block.getBlockZ() - 0.5); + double _01 = getInterpolatedNoise(block.getBlockX() - 0.5, block.getBlockY(), block.getBlockZ()); + //double _02 = interp.getNoise(block.getBlockX() - 0.5, block.getBlockY(), block.getBlockZ() + 0.5); + double _10 = getInterpolatedNoise(block.getBlockX(), block.getBlockY(), block.getBlockZ() - 0.5); + double _12 = getInterpolatedNoise(block.getBlockX(), block.getBlockY(), block.getBlockZ() + 0.5); + //double _20 = interp.getNoise(block.getBlockX() + 0.5, block.getBlockY(), block.getBlockZ() - 0.5); + double _21 = getInterpolatedNoise(block.getBlockX() + 0.5, block.getBlockY(), block.getBlockZ()); + //double _22 = interp.getNoise(block.getBlockX() + 0.5, block.getBlockY(), block.getBlockZ() + 0.5); + + if(stairs != null) { + Palette stairPalette = stairs.get(down.getMaterial()); + if(stairPalette != null) { + BlockData stair = stairPalette.get(0, block.getBlockX(), block.getBlockZ()); + Stairs finalStair = getStair(new double[] {_01, _10, _12, _21}, (Stairs) stair, thresh); + if(finalStair != null) { + if(orig.matches(Util.WATER)) finalStair.setWaterlogged(true); + chunk.setBlock(block.getBlockX(), block.getBlockY(), block.getBlockZ(), finalStair); + return; + } + } + } + BlockData slab = slabs.getOrDefault(down.getMaterial(), Util.BLANK_PALETTE).get(0, block.getBlockX(), block.getBlockZ()); + if(slab instanceof Waterlogged) { + ((Waterlogged) slab).setWaterlogged(orig.matches(Util.WATER)); + } else if(orig.matches(Util.WATER)) return; + chunk.setBlock(block.getBlockX(), block.getBlockY(), block.getBlockZ(), slab); + } + } + + private static Stairs getStair(double[] vals, Stairs stair, double thresh) { + if(vals.length != 4) throw new IllegalArgumentException(); + Stairs stairNew = (Stairs) stair.clone(); + if(vals[0] > thresh) { + stairNew.setFacing(BlockFace.WEST); + } else if(vals[1] > thresh) { + stairNew.setFacing(BlockFace.NORTH); + } else if(vals[2] > thresh) { + stairNew.setFacing(BlockFace.SOUTH); + } else if(vals[3] > thresh) { + stairNew.setFacing(BlockFace.EAST); + } else return null; + return stairNew; + } + private void load(World w) { try { popMan.loadBlocks(w); diff --git a/src/main/java/com/dfsek/terra/generation/UserDefinedGenerator.java b/src/main/java/com/dfsek/terra/generation/UserDefinedGenerator.java index 648474c86..991e450d3 100644 --- a/src/main/java/com/dfsek/terra/generation/UserDefinedGenerator.java +++ b/src/main/java/com/dfsek/terra/generation/UserDefinedGenerator.java @@ -23,19 +23,29 @@ public class UserDefinedGenerator extends Generator { private final Variable xVar = s.getVariable("x"); private final Variable yVar = s.getVariable("y"); private final Variable zVar = s.getVariable("z"); - private final TreeMap> paletteMap; + @SuppressWarnings("unchecked") + private final Palette[] palettes = new Palette[256]; private final NoiseFunction2 n2 = new NoiseFunction2(); private final NoiseFunction3 n3 = new NoiseFunction3(); private static final Object noiseLock = new Object(); - public UserDefinedGenerator(String e, List v, TreeMap> pa) throws ParseException { + public UserDefinedGenerator(String equation, List v, TreeMap> pa) throws ParseException { Parser p = new Parser(); p.registerFunction("noise2", n2); p.registerFunction("noise3", n3); - this.paletteMap = pa; - this.noiseExp = p.parse(e, s); + for(int y = 0; y < 256; y++) { + Palette d = Util.BLANK_PALETTE; + for(Map.Entry> e : pa.entrySet()) { + if(e.getKey() >= y) { + d = e.getValue(); + break; + } + } + palettes[y] = d; + } + this.noiseExp = p.parse(equation, s); } /** * Gets the 2D noise at a pair of coordinates using the provided FastNoise instance. @@ -85,9 +95,6 @@ public class UserDefinedGenerator extends Generator { */ @Override public Palette getPalette(int y) { - for(Map.Entry> e : paletteMap.entrySet()) { - if(e.getKey() >= y ) return e.getValue(); - } - return null; + return palettes[y]; } } diff --git a/src/main/java/com/dfsek/terra/generation/Util.java b/src/main/java/com/dfsek/terra/generation/Util.java new file mode 100644 index 000000000..0942b5fdb --- /dev/null +++ b/src/main/java/com/dfsek/terra/generation/Util.java @@ -0,0 +1,15 @@ +package com.dfsek.terra.generation; + +import org.bukkit.Material; +import org.bukkit.block.data.BlockData; +import org.polydev.gaea.world.palette.Palette; +import org.polydev.gaea.world.palette.RandomPalette; + +import java.util.Random; + +public class Util { + public static final BlockData STONE = Material.STONE.createBlockData(); + public static final BlockData WATER = Material.WATER.createBlockData(); + public static final BlockData AIR = Material.AIR.createBlockData(); + public static final Palette BLANK_PALETTE = new RandomPalette(new Random(2403)).add(AIR, 1); +} diff --git a/src/main/java/com/dfsek/terra/population/CavePopulator.java b/src/main/java/com/dfsek/terra/population/CavePopulator.java index ca45946bf..fe8bbfb08 100644 --- a/src/main/java/com/dfsek/terra/population/CavePopulator.java +++ b/src/main/java/com/dfsek/terra/population/CavePopulator.java @@ -16,6 +16,7 @@ import org.polydev.gaea.world.carving.CarvingData; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Random; import java.util.Set; diff --git a/src/main/java/com/dfsek/terra/population/OrePopulator.java b/src/main/java/com/dfsek/terra/population/OrePopulator.java index 90c6bbdb5..191d44234 100644 --- a/src/main/java/com/dfsek/terra/population/OrePopulator.java +++ b/src/main/java/com/dfsek/terra/population/OrePopulator.java @@ -22,8 +22,7 @@ public class OrePopulator extends GaeaBlockPopulator { @Override public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) { try (ProfileFuture ignored = TerraProfiler.fromWorld(world).measure("OreTime")) { - Location l = chunk.getBlock(8, 0, 0).getLocation(); - Biome b = TerraBiomeGrid.fromWorld(world).getBiome(l.getBlockX(), l.getBlockZ(), GenerationPhase.POPULATE); + Biome b = TerraBiomeGrid.fromWorld(world).getBiome((chunk.getX() << 4)+8, (chunk.getZ() << 4) + 8, GenerationPhase.POPULATE); for(Map.Entry e : BiomeConfig.fromBiome((UserDefinedBiome) b).getOres().entrySet()) { int num = e.getValue().get(random); for(int i = 0; i < num; i++) { diff --git a/src/main/java/com/dfsek/terra/population/StructurePopulator.java b/src/main/java/com/dfsek/terra/population/StructurePopulator.java index 20b8bd061..4f94b1c61 100644 --- a/src/main/java/com/dfsek/terra/population/StructurePopulator.java +++ b/src/main/java/com/dfsek/terra/population/StructurePopulator.java @@ -1,13 +1,11 @@ package com.dfsek.terra.population; -import com.dfsek.terra.Terra; import com.dfsek.terra.TerraProfiler; import com.dfsek.terra.biome.TerraBiomeGrid; import com.dfsek.terra.biome.UserDefinedBiome; import com.dfsek.terra.config.genconfig.BiomeConfig; import com.dfsek.terra.config.genconfig.StructureConfig; import com.dfsek.terra.structure.GaeaStructure; -import com.dfsek.terra.structure.StructureSpawn; import com.dfsek.terra.structure.StructureSpawnRequirement; import org.bukkit.Bukkit; import org.bukkit.Chunk; @@ -16,16 +14,10 @@ import org.bukkit.World; import org.bukkit.generator.BlockPopulator; import org.jetbrains.annotations.NotNull; import org.polydev.gaea.generation.GenerationPhase; -import org.polydev.gaea.population.GaeaBlockPopulator; import org.polydev.gaea.profiler.ProfileFuture; -import java.io.File; -import java.io.IOException; -import java.util.Arrays; import java.util.Collections; -import java.util.HashSet; import java.util.Random; -import java.util.Set; public class StructurePopulator extends BlockPopulator { diff --git a/src/main/java/com/dfsek/terra/population/TreePopulator.java b/src/main/java/com/dfsek/terra/population/TreePopulator.java index 2bf12b967..420681a68 100644 --- a/src/main/java/com/dfsek/terra/population/TreePopulator.java +++ b/src/main/java/com/dfsek/terra/population/TreePopulator.java @@ -25,18 +25,18 @@ public class TreePopulator extends GaeaBlockPopulator { Location origin = chunk.getBlock(x, 0, z).getLocation(); Biome b = TerraBiomeGrid.fromWorld(world).getBiome(origin, GenerationPhase.POPULATE); if(((UserDefinedDecorator) b.getDecorator()).getTreeChance() < random.nextInt(100)) return; - int numTrees = 0; - for(int i = 0; i < 48; i++) { + int max = 50; + int att = 0; + for(int i = 0; i < b.getDecorator().getTreeDensity() && att < max; ) { + att++; int y = WorldUtil.getHighestValidSpawnAt(chunk, x, z); if(y <= 0) continue; origin = chunk.getBlock(x, y, z).getLocation().add(0, 1, 0); b = TerraBiomeGrid.fromWorld(world).getBiome(origin, GenerationPhase.POPULATE); - numTrees++; try { - b.getDecorator().getTrees().get(random).plant(origin, random, false, Terra.getInstance()); + if(b.getDecorator().getTrees().get(random).plant(origin, random, false, Terra.getInstance())) i++; } catch(NullPointerException ignore) {} - if(numTrees >= b.getDecorator().getTreeDensity()) break; - x = random.nextInt(16); // Decrease chances of chunk-crossing trees + x = random.nextInt(16); z = random.nextInt(16); } } diff --git a/src/main/java/com/dfsek/terra/structure/StructureSpawn.java b/src/main/java/com/dfsek/terra/procgen/GridSpawn.java similarity index 64% rename from src/main/java/com/dfsek/terra/structure/StructureSpawn.java rename to src/main/java/com/dfsek/terra/procgen/GridSpawn.java index 04a0bf93b..47ed76bed 100644 --- a/src/main/java/com/dfsek/terra/structure/StructureSpawn.java +++ b/src/main/java/com/dfsek/terra/procgen/GridSpawn.java @@ -1,7 +1,5 @@ -package com.dfsek.terra.structure; +package com.dfsek.terra.procgen; -import com.dfsek.terra.config.ConfigUtil; -import org.bukkit.Bukkit; import org.bukkit.util.Vector; import org.polydev.gaea.math.MathUtil; @@ -9,20 +7,28 @@ import java.util.ArrayList; import java.util.List; import java.util.Random; -public class StructureSpawn { +public class GridSpawn { private final int separation; private final int width; - public StructureSpawn(int width, int separation) { + public GridSpawn(int width, int separation) { this.separation = separation; this.width = width; } + + /** + * Get nearest spawnpoint + * @param x X coordinate + * @param z Z coordinate + * @param seed Seed for RNG + * @return Vector representing nearest spawnpoint + */ public Vector getNearestSpawn(int x, int z, long seed) { int structureChunkX = x / (width + 2*separation); int structureChunkZ = z / (width + 2*separation); List zones = new ArrayList<>(); for(int xi = structureChunkX-1; xi <= structureChunkX+1; xi++) { for(int zi = structureChunkZ-1; zi <= structureChunkZ+1; zi++) { - zones.add(getStructureChunkSpawn(xi, zi, seed)); + zones.add(getChunkSpawn(xi, zi, seed)); } } Vector shortest = zones.get(0); @@ -32,7 +38,15 @@ public class StructureSpawn { } return shortest; } - private Vector getStructureChunkSpawn(int structureChunkX, int structureChunkZ, long seed) { + + /** + * Get the X/Z coordinates of the spawnpoint in the nearest Chunk (not Minecraft chunk) + * @param structureChunkX Chunk X coordinate + * @param structureChunkZ Chunk Z coordinate + * @param seed Seed for RNG + * @return Vector representing spawnpoint + */ + private Vector getChunkSpawn(int structureChunkX, int structureChunkZ, long seed) { Random r = new Random(MathUtil.getCarverChunkSeed(structureChunkX, structureChunkZ, seed)); int offsetX = r.nextInt(width); int offsetZ = r.nextInt(width); diff --git a/src/main/java/com/dfsek/terra/procgen/voxel/DeformedSphere.java b/src/main/java/com/dfsek/terra/procgen/voxel/DeformedSphere.java new file mode 100644 index 000000000..fbdfc794b --- /dev/null +++ b/src/main/java/com/dfsek/terra/procgen/voxel/DeformedSphere.java @@ -0,0 +1,20 @@ +package com.dfsek.terra.procgen.voxel; + +import org.bukkit.block.Block; +import org.bukkit.util.Vector; +import org.polydev.gaea.math.FastNoise; + +public class DeformedSphere extends VoxelGeometry { + public DeformedSphere(Vector start, int rad, double deform, FastNoise noise) { + for(int x = -rad; x <= rad; x++) { + for(int y = -rad; y <= rad; y++) { + for(int z = -rad; z <= rad; z++) { + Vector c = new Vector(x, y, z); + if(c.length() < (rad + 0.5) * ((noise.getNoise(x, y, z)+1)*deform)) { + addVector(c.add(start)); + } + } + } + } + } +} diff --git a/src/main/java/com/dfsek/terra/procgen/voxel/Sphere.java b/src/main/java/com/dfsek/terra/procgen/voxel/Sphere.java new file mode 100644 index 000000000..d5c99fcd2 --- /dev/null +++ b/src/main/java/com/dfsek/terra/procgen/voxel/Sphere.java @@ -0,0 +1,19 @@ +package com.dfsek.terra.procgen.voxel; + +import org.bukkit.util.Vector; +import org.polydev.gaea.math.FastNoise; + +public class Sphere extends VoxelGeometry { + public Sphere(Vector start, int rad) { + for(int x = -rad; x <= rad; x++) { + for(int y = -rad; y <= rad; y++) { + for(int z = -rad; z <= rad; z++) { + Vector c = new Vector(x, y, z); + if(c.length() < rad + 0.5) { + addVector(c.add(start)); + } + } + } + } + } +} diff --git a/src/main/java/com/dfsek/terra/procgen/voxel/Tube.java b/src/main/java/com/dfsek/terra/procgen/voxel/Tube.java new file mode 100644 index 000000000..4fd131c1d --- /dev/null +++ b/src/main/java/com/dfsek/terra/procgen/voxel/Tube.java @@ -0,0 +1,15 @@ +package com.dfsek.terra.procgen.voxel; + +import org.bukkit.util.Vector; + +public class Tube extends VoxelGeometry { + public Tube(Vector start, Vector end, int radius) { + Vector step = start.clone().subtract(end).normalize(); + Vector run = start.clone(); + int steps = (int) start.distance(end); + for(int i = 0; i < steps; i++) { + merge(new Sphere(run, radius)); + run.add(step); + } + } +} diff --git a/src/main/java/com/dfsek/terra/procgen/voxel/VoxelGeometry.java b/src/main/java/com/dfsek/terra/procgen/voxel/VoxelGeometry.java new file mode 100644 index 000000000..264164084 --- /dev/null +++ b/src/main/java/com/dfsek/terra/procgen/voxel/VoxelGeometry.java @@ -0,0 +1,26 @@ +package com.dfsek.terra.procgen.voxel; + +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.List; + +public abstract class VoxelGeometry { + public List geometry = new ArrayList<>(); + + public List getGeometry() { + return geometry; + } + + protected void addVector(Vector v) { + geometry.add(v); + } + + public void merge(VoxelGeometry other) { + geometry.addAll(other.getGeometry()); + } + public static VoxelGeometry getBlank() { + return new Blank(); + } + private static class Blank extends VoxelGeometry {} +}