The always up-to-date definitive guide to terrain generation: part two - Making a flat landscape

Discussion in 'Resources' started by jtjj222, Aug 17, 2012.

Thread Status:
Not open for further replies.
  1. Offline


    The first part of this series: part one - prerequisites and setup

    At the end of the last tutorial, we left off with the basic framework for a terrain generator. Now is the fun part: Actually making some terrain! Open up Just for extra redundancy, I will post the entire class file so far here. Note that I added the method getDefaultPopulators, which allows us to tell bukkit what block populators we are going to use. More on this in the next section.

    The generateBlockSections method is where we are going to focusing on today. Inside it, we need to:
    Create an array to represent the blocks in the chunk. We will call this array, for simplicity, chunk.
    1. byte[][] chunk = new byte[world.getMaxHeight() / 16][];

    Remember that the array that generateBlockSections returns is actually an array of block sections, and each of them are 16 blocks tall, so the max height / 16 is the number of block sections in each chunk.
    Next, we need to loop through all of the blocks in the chunk that need to be set to stone:
    2. for (int x=0; x<16; x++) { //loop through all of the blocks in the chunk that are lower than maxHeight
    3. for (int z=0; z<16; z++) {
    4. int maxHeight = 64; //how thick we want out flat terrain to be
    5. for (int y=0;y<maxHeight;y++) {
    7. }
    8. }
    9. }

    And inside the deepest loop, set them to stone using the setBlock method earlier.
    1. setBlock(x,y,z,chunk,Material.STONE); //set the current block to stone

    setBlock takes care of all the nitty-gritty math involved in figuring out the offsets.
    Lastly, we need to return "chunk":
    1. return chunk;

    And we are done! Now let's test it out. You can test it out with a multi-world plugin like multiverse, but I personaly like to create a test server on my desktop, drop my plugin into the plugins folder, and add the following to my bukkit.yml:
              generator: BasicTerrain
    note that the default name for the default world is world, unless you have changed it.
    Then, I delete the default world, start the server, and pray it works! Whatever method you use, go ahead and build, then run the plugin.

    It Works! Here is the working eclipse project. (note that you will need to re-link bukkit.jar to it)

    Stay tuned for the next part which covers Block populators!

    Sorry, I forgot to mention the getDefaultPopulators method in this tutorial. It goes in your chunk generator and is needed for when we do block populators:
    2. /**
    3. * Returns a list of all of the block populators (that do "little" features)
    4. * to be called after the chunk generator
    5. */
    6. @Override
    7. public List<BlockPopulator> getDefaultPopulators(World world) {
    8. ArrayList<BlockPopulator> pops = new ArrayList<BlockPopulator>();
    9. //Add Block populators here
    10. return pops;
    11. }

    Sorry 'bout that!
    (Placeholder for error correction and links to future parts)
    Part 3:
    Part 4:
    Part 5:

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
    Last edited by a moderator: May 27, 2016
    TakaGo, TheButlah and chasechocolate like this.
  2. Offline


    Did you post the source code (as a piece) anywhere. Good Tutorials. Keep up the good work!!!!

    EDIT: Never mind!!!
  3. all I have to say to you good sir is THANK YOU SO VERY MUCH!!!!!!!!!!!
  4. Offline


    Following exactly and I get:
    12:51:20 AM [SEVERE] Could not set generator for default world 'world': Plugin 'BasicTerrain v1.0' lacks a default world generator
        generator: BasicTerrain
    1. package me.ultimate.BasicTerrain;
    3. import java.util.ArrayList;
    4. import java.util.List;
    5. import java.util.Random;
    7. import org.bukkit.Material;
    8. import org.bukkit.World;
    9. import org.bukkit.generator.BlockPopulator;
    10. import org.bukkit.generator.ChunkGenerator;
    11. import;
    13. public class BasicTerrain extends JavaPlugin {
    15. public ChunkGenerator getDefaultChunkGenerator(String worldName, String GenId) {
    16. return new me.ultimate.BasicTerrain.BasicTerrain.BasicChunkGenerator();
    17. }
    19. public class BasicChunkGenerator extends ChunkGenerator {
    21. void setBlock(int x, int y, int z, byte[][] chunk, Material material) {
    22. if (chunk[y >> 4] == null)
    23. chunk[y >> 4] = new byte[16 * 16 * 16];
    24. if (!(y <= 256 && y >= 0 && x <= 16 && x >= 0 && z <= 16 && z >= 0))
    25. return;
    26. try {
    27. chunk[y >> 4][((y & 0xF) << 8) | (z << 4) | x] = (byte) material.getId();
    28. } catch (Exception e) {
    29. // do nothing
    30. }
    31. }
    33. @Override
    34. public byte[][] generateBlockSections(World world, Random rand, int ChunkX, int ChunkZ, BiomeGrid biome) {
    35. return null;
    36. }
    38. @Override
    39. public List<BlockPopulator> getDefaultPopulators(World world) {
    40. ArrayList<BlockPopulator> pops = new ArrayList<BlockPopulator>();
    41. return pops;
    42. }
    43. }
    45. }

    name: BasicTerrain
    version: 1.0
    main: me.ultimate.BasicTerrain.BasicTerrain
    load: startup
  5. Offline


    Sorry man, I had made a mistake in the last tutorial.

    Change getDefaultChunkGenerator to getDefaultWorldGenerator in your plugin.
    Ultimate_n00b likes this.
  6. Offline


    I know that this post is around a year old now, but I'd really like jtjj222 to go over how the setBlock method packs the data into the array. I personally know how it's done, but I feel that because this is supposed to be a tutorial on world generation, you should explain this to the many people who don't know how that works.
Thread Status:
Not open for further replies.

Share This Page