Solved New world with ChunkGenerator and caves(1.14) [EDIT: Version's bug]

Discussion in 'Spigot Plugin Development' started by Hugi21, Jun 29, 2019.

  1. Hello everyone !

    I wanted to create a world using ChunkGenerator to have a world with more ores, higher mountains, big caves and other things like that. But, there are no much tutorials on ChunkGenerator.

    Finally, I found this one TUTORIAL

    I've just literraly copy and paste the code, to see if it works and how it looks. But each time I tried to generate a custom world the server crash. I don't think it's a pure java error, I think it's a problem of power. But like the tutorial is old and the javadocs doesn't explain in details how ChunkGenerator works, I refer to you to be... enlightened on the topic !

    I give you the code :

    (Spigot 1.14)

    Code (Text):
    public class CustomChunk extends ChunkGenerator {
        public static int currentheight;
        @Override
        public ChunkData generateChunkData(World world, Random random, int chunkX, int chunkZ, BiomeGrid biome) {
            // TODO Chunk generation code here.
            ChunkData chunk = createChunkData(world);
            SimplexOctaveGenerator generator = new SimplexOctaveGenerator(new Random(world.getSeed()), 18);
            generator.setScale(0.005D);
            for (int X = 0; X < 16; X++)
                for (int Z = 0; Z < 16; Z++) {
                    currentheight = (int) ((generator.noise(chunkX*16+X, chunkZ*16+Z, 0.5D, 0.5D, true)+1)*19D+60D);
                    chunk.setBlock(X, currentheight, Z, Material.GRASS);
                    chunk.setBlock(X, currentheight-1, Z, Material.DIRT);
                    for (int i = currentheight-2; i > 0; i--)
                        chunk.setBlock(X, i, Z, Material.STONE);
                    chunk.setBlock(X, 0, Z, Material.BEDROCK);
                }
        return chunk;}

        @Override
        public List<BlockPopulator> getDefaultPopulators(World world) {
            List<BlockPopulator> bp = new ArrayList<>();
            bp.add(new TreePopulator());
            bp.add(new LakesPopulator());
            bp.add(new GoldPopulator());
            bp.add(new DiamondPopulator());
            return bp;
        }
    }
     

    I'm not very sure how to add more than one BlockPopulator, as you see I made a list and add the Populator in a second time. Tell me if there is a better way to do that.

    Code (Text):
    public class commands implements CommandExecutor {
        private static brouillon plugin ;
        @Override
        public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
            if (sender instanceof Player) {
                Player p = (Player) sender;
                if (label.equalsIgnoreCase("brouillon")) {
                    if (args[0].equalsIgnoreCase("create")) {
                        if (args[1] != "") {
                            WorldCreator nw = new WorldCreator(args[1]);
                            nw.generator(new CustomChunk());
                            Bukkit.getLogger().log(Level.INFO, "Generator is : " + nw.generator().toString());
                            Bukkit.getLogger().log(Level.INFO, "World name is : " + nw.name());
                            nw.createWorld();

    return true;
                        }
                    } else if(args[0].equalsIgnoreCase("tp")){
                        if(Bukkit.getWorld(args[1]) != null){
                            p.teleport(Bukkit.getWorld(args[1]).getSpawnLocation());
    return true;
                        }
                    }
                }
            }
            return false;
        }


    }

    Code (Text):
    public class TreePopulator extends BlockPopulator {
        @Override
        public void populate(World world, Random random, Chunk chunk) {
            if(random.nextBoolean()){
                int amount = random.nextInt(4)+1;  // Amount of trees
                for (int i = 1; i < amount; i++) {
                    int X = random.nextInt(15);
                    int Z = random.nextInt(15);
                    int Y = 1;
                    for (int j = world.getMaxHeight()-1; chunk.getBlock(X, j, Z).getType() == Material.AIR; j--);
                    world.generateTree(chunk.getBlock(X, Y, Z).getLocation(), TreeType.TREE);
                }
            }
        }
    }
     


    All the ores populators are based on this one
    Code (Text):
    public class GoldPopulator extends BlockPopulator {
        @Override
        public void populate(World world, Random random, Chunk chunk) {
            int X, Y, Z;
            boolean isStone;
            for (int i = 1; i < 15; i++) {
                if (random.nextInt(100) < 60) {
                    X = random.nextInt(15);
                    Z = random.nextInt(15);
                    Y = random.nextInt(40)+20;
                    if (chunk.getBlock(X, Y, Z).getType() == Material.STONE) {
                        isStone = true;
                        while (isStone) {
                            chunk.getBlock(X, Y, Z).setType(Material.COAL_ORE);
                            if (random.nextInt(100) < 40)  {
                                switch (random.nextInt(5)) {
                                    case 0: X++; break;
                                    case 1: Y++; break;
                                    case 2: Z++; break;
                                    case 3: X--; break;
                                    case 4: Y--; break;
                                    case 5: Z--; break;
                                }
                                isStone = (chunk.getBlock(X, Y, Z).getType() == Material.STONE) && (chunk.getBlock(X, Y, Z).getType() != Material.COAL_ORE);
                            } else isStone = false;
                        }
                    }
                }
            }
        }
    }

    And finally...
    Code (Text):
    public class LakesPopulator extends BlockPopulator {
        @Override
        public void populate(World world, Random random, Chunk chunk) {
            if (random.nextInt(100) < 5) {
                Block block;
                int chunkX = chunk.getX();
                int chunkZ = chunk.getZ();
                int X = chunkX * 16 + random.nextInt(15)-8;
                int Z = chunkZ * 16 + random.nextInt(15)-8;
                int Y;
                for (Y = world.getMaxHeight()-1; chunk.getBlock(X, Y, Z).getType() == Material.AIR; Y--);
                Y -= 7;
                block = world.getBlockAt(Z+8, Y, Z+8);
                if (random.nextInt(100) < 90) block.setType(Material.WATER); else block.setType(Material.LAVA);
                boolean[] aboolean = new boolean[2048];
                boolean flag;
                int i = random.nextInt(4)+4;

                int j, j1, k1;

                for (j = 0; j < i; ++j) {

                    double d0 = random.nextDouble() * 6.0D + 3.0D;
                    double d1 = random.nextDouble() * 4.0D + 2.0D;
                    double d2 = random.nextDouble() * 6.0D + 3.0D;
                    double d3 = random.nextDouble() * (16.0D - d0 - 2.0D) + 1.0D + d0 / 2.0D;
                    double d4 = random.nextDouble() * (8.0D - d1 - 4.0D) + 2.0D + d1 / 2.0D;
                    double d5 = random.nextDouble() * (16.0D - d2 - 2.0D) + 1.0D + d2 / 2.0D;

                    for (int k = 1; k < 15; ++k) {
                        for (int l = 1; l < 15; ++l) {
                            for (int i1 = 1; i1 < 7; ++i1) {
                                double d6 = ((double) k - d3) / (d0 / 2.0D);
                                double d7 = ((double) i1 - d4) / (d1 / 2.0D);
                                double d8 = ((double) l - d5) / (d2 / 2.0D);
                                double d9 = d6 * d6 + d7 * d7 + d8 * d8;

                                if (d9 < 1.0D) {
                                    aboolean[(k * 16 + l) * 8 + i1] = true;
                                }
                            }
                        }
                    }
                }

                for (j = 0; j < 16; ++j) {
                    for (k1 = 0; k1 < 16; ++k1) {
                        for (j1 = 0; j1 < 8; ++j1) {
                            if (aboolean[(j * 16 + k1) * 8 + j1]) {
                                world.getBlockAt(X + j, Y + j1, Z + k1).setType(j1>4 ? Material.AIR : ((Block) block).getType());
                            }
                        }
                    }
                }

                for (j = 0; j < 16; ++j) {
                    for (k1 = 0; k1 < 16; ++k1) {
                        for (j1 = 4; j1 < 8; ++j1) {
                            if (aboolean[(j * 16 + k1) * 8 + j1]) {
                                int X1 = X+j;
                                int Y1 = Y+j1-1;
                                int Z1 = Z+k1;
                                if (world.getBlockAt(X1, Y1, Z1).getType() == Material.DIRT) {
                                    world.getBlockAt(X1, Y1, Z1).setType(Material.GRASS);
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    Also, as the thread's title explains, I'm looking for a way to generate BIG caves... So if you know a project where I can see something, tell me please :) .

    And here is the error log file. (Sorry this is too long to be in the thread)

    Thanks in advance !

    Regards.

    Hugo

    (Sorry if there is some english mistakes, this is not my native language)
     

    Attached Files:


  2. Hi! i'm also writing a generator right now, you could use 3d noise for caves.