*WARNING* I'm from Germany, so my English won't be perfect. You are allowed to ask, if you don't understand something In this tutorial I want to explain you the very basics of world generation. I assume, you know the basics to create a bukkit plugin. There are already tutorials for World Generation, but they're using the old API. Table of contents: How to build a chunk Coding of the plugin class Coding of the generator class Get it working How to build a chunk You know, the normal Minecraft chunk has a size of 16x16x256. To save memory, the chunk itself is split into 16 16x16x16 parts. The idea behind this is, that chunks in which is no block (or air) will be delivered with NULL. The complete chunk is represented by this array: Code:JAVA byte[][] result = new byte[world.getMaxHeight() / 16][]; Before you can set blocks, you have to initialize the chunk part in which the block is: Code:JAVA result[partY] = new byte[4096]; partY is the position of the part in the chunk from bottom to top. As you can see, each part consists of 12 bits. The first 4 Bits are the y value, the 4 in the middle the z value and the last 4 the x value. For example, we want to set a stone block at the position P(12|8|5): To set the block, you have to do: Code:JAVA result[2140] = (byte)Material.STONE.getId(); Coding of the plugin class This is very simple. You only have to add one function too your main class: Code:JAVA import org.bukkit.generator.ChunkGenerator;import org.bukkit.plugin.java.JavaPlugin; public class YourWorldGeneratorPlugin extends JavaPlugin{public ChunkGenerator getDefaultWorldGenerator(String worldName, String id){return new YourGenerator();}} For more infos about getDefaultWorldGenerator(String worldName, String id) look here. Coding of the generator class We will code a very simple flat terrain generator. Take a look into the docu: click! You can see, to generate a very simple world, you need a class that extends Code:JAVA org.bukkit.generator.ChunkGenerator and has the function Code:JAVA byte[][] generateBlockSections(World world, Random random, int x, int z, BiomeGrid biomes) Your basic class structure will look like this: Code:JAVA import java.util.Random; import org.bukkit.World;import org.bukkit.generator.ChunkGenerator; public class YourGenerator extends ChunkGenerator {public byte[][] generateBlockSections(World world, Random random, int chunkX, int chunkZ, BiomeGrid biomeGrid){byte[][] result = new byte[world.getMaxHeight() / 16][]; //world height / chunk part height (=16, look above)return result;}} This is your very first generator! Congratulation for doing nothing! But now let us add some blocks. To make it easier, we add an simple method, to set a block in the chunk: Code:JAVA void setBlock(byte[][] result, int x, int y, int z, byte blkid) {if (result[y >> 4] == null) //is this chunkpart already initialised?{result[y >> 4] = new byte[4096]; //initialise the chunk part}result[y >> 4][((y & 0xF) << 8) | (z << 4) | x] = blkid; //set the block (look above, how this is done)} Now it's very easy: First we generate a layer of bedrock at y=0: Code:JAVA for(x = 0; x < 16; x++){for(z = 0; z < 16; z++){setBlock(result, x, 0, z, (byte)Material.BEDROCK.getId());}} Then you generate two layers of dirt: Code:JAVA for(x = 0; x < 16; x++){for(y = 1; y <= 2; y++){for (z = 0; z < 16; z++){setBlock(result, x, y, z, (byte)Material.DIRT.getId());}}} And at last you create a layer of grass: Code:JAVA for(x = 0; x < 16; x++){for(z = 0; z < 16; z++){setBlock(result, x, 3, z, (byte)Material.GRASS.getId());}} There is an advanced version of this code attached. Get it working Now we have a generator written. But there are a few things to do: First you have to make an entry in your plugin.yml Code: load: STARTUP If you don't add this line, bukkit will generate the world and THEN load your plugin! Now you're ready to export it as .jar (I expect, you know how to build a plugin) and copy it into your plugin folder. Now open your bukkit.yml and add this lines of code: Code: worlds: YourWorldNameHere: generator: YourWorldGeneratorPlugin You have only to modify your level name in server.properties and you're ready to start bukkit. End This is the end of my tutorial. If you have any questions and/or suggestions, write an answer. Here is the download link: BukkitFlatWorld.zip If you find any mistakes, please report them to me. I used bukkit-1.2.5-R3.0, and I don't promise, that it works flawless with newer versions. Mator
I'm reposting a question from the PlotMe developer zachbora: Do you think you could explain how to make a generator that supports block values?
I'll try it. But first, I will finish this tutorial here (maybe today , i hadn't much time in the last few days) and then i will look at that problem.
you can use the "ChunkMaker" class of the plugin "MultiWorld" to make those chunks whit cuboids and other stuff, whtout to code mutch by your own
Could you explain how to make biomes generate? I want to be able to specify that a specific biome generates at the spawn, but everything else has an ocean biome? An example of this would be a survival island generator, where the island is unique to every seed by using biomes instead of specific blocks and block locations.
Hm... Thats an intersting question. There are two possibilities: You handle it with the populator (The easy way), or the complex way: You create a delayed task. But i have to research this. Atm I'm working at another project. When I finished this, I will maybe make a tutorial about this.
@MatorKaleen: Your code is too difficult. Instead of the byte[][] you should use a byte[] with size 65536 (16 * 16 * 256) called blocks and add a method: Code: private int convert(int x, int y, int z) { return (x * 16 + z) * 256 + y; } To create a block simply do now: Code: blocks[convert(x, y, z)] = (byte) Material.STONE.getId(); Finally just return blocks.
@sd5 The way, you describe, is 1. Deprecated (look here) 2. Much more memory intensive: a byte[65536] is larger than a byte[16][], because you needn't to initialise every 16 arrays in the second dimension (it's hard to explain in english for me, sry) Maybe this is more difficult as your one, but I think, this is the more effecient way. Mator
Very interesting. Wish I had known about this before I did my plot generator. I will change the code and see if it works. It's too bad that chunk gen still doesn't support block data.
Looks good! Just one tip, use the getMaxHeight(); method instead of specifying the height. Code:Java public byte[][] generateBlockSections(World world, Random random, int chunkX, int chunkZ, BiomeGrid biomeGrid) { byte[][] result = new byte[world.getMaxHeight() / 16][]; return result;}
Thanks for the tip, I will update the download the next few days Here's a little new screenshot, what I'm doing atm: Mediafire
Cool, do you know how to make light update on generated chunks because I generated glowstone and no light is given off until the block is updated.