# 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.

Not open for further replies.
1. Offline

### jtjj222

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 BasicChunkGenerator.java. 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.
Code:java
`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:
Code:java
` for (int x=0; x<16; x++) { //loop through all of the blocks in the chunk that are lower than maxHeightfor (int z=0; z<16; z++) {int maxHeight = 64; //how thick we want out flat terrain to befor (int y=0;y<maxHeight;y++) {                 }        }}`

And inside the deepest loop, set them to stone using the setBlock method earlier.
Code:java
`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":
Code:java
`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:
Code:
```worlds:
world:
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)
https://dl.dropbox.com/u/12637402/gentut/setup/BasicTerrain.zip

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:
Code:java
` /*** Returns a list of all of the block populators (that do "little" features)* to be called after the chunk generator*/@Overridepublic List<BlockPopulator> getDefaultPopulators(World world) {ArrayList<BlockPopulator> pops = new ArrayList<BlockPopulator>();//Add Block populators herereturn pops;} `

Sorry 'bout that!
(Placeholder for error correction and links to future parts)

EDIT by Moderator: merged posts, please use the edit button instead of double posting.

Last edited by a moderator: May 27, 2016
#1
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!!!

#2
3. Offline

### computerdude5000

all I have to say to you good sir is THANK YOU SO VERY MUCH!!!!!!!!!!!

4. Offline

### Ultimate_n00b

Following exactly and I get:
Code:
`12:51:20 AM [SEVERE] Could not set generator for default world 'world': Plugin 'BasicTerrain v1.0' lacks a default world generator`
Code:
```worlds:
world:
generator: BasicTerrain```
Code:java
`package me.ultimate.BasicTerrain; import java.util.ArrayList;import java.util.List;import java.util.Random; import org.bukkit.Material;import org.bukkit.World;import org.bukkit.generator.BlockPopulator;import org.bukkit.generator.ChunkGenerator;import org.bukkit.plugin.java.JavaPlugin; public class BasicTerrain extends JavaPlugin {    public ChunkGenerator getDefaultChunkGenerator(String worldName, String GenId) {      return new me.ultimate.BasicTerrain.BasicTerrain.BasicChunkGenerator();   }    public class BasicChunkGenerator extends ChunkGenerator {       void setBlock(int x, int y, int z, byte[][] chunk, Material material) {         if (chunk[y >> 4] == null)            chunk[y >> 4] = new byte[16 * 16 * 16];         if (!(y <= 256 && y >= 0 && x <= 16 && x >= 0 && z <= 16 && z >= 0))            return;         try {            chunk[y >> 4][((y & 0xF) << 8) | (z << 4) | x] = (byte) material.getId();         } catch (Exception e) {            // do nothing         }      }       @Override      public byte[][] generateBlockSections(World world, Random rand, int ChunkX, int ChunkZ, BiomeGrid biome) {         return null;      }       @Override      public List<BlockPopulator> getDefaultPopulators(World world) {         ArrayList<BlockPopulator> pops = new ArrayList<BlockPopulator>();         return pops;      }   } } `

Code:
```name: BasicTerrain
version: 1.0
main: me.ultimate.BasicTerrain.BasicTerrain

#4
5. Offline

### jtjj222

Ultimate_n00b

Change getDefaultChunkGenerator to getDefaultWorldGenerator in your plugin.

#5
Ultimate_n00b likes this.
6. Offline

### TheButlah

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.

#6