| | | | | | |

How to Make a World Generation Algorithm in Bukkit/Spigot

This article is going to be a bit different than most Info Toast articles, as it’s aimed more towards people who know how to code and are familiar with everything that comes with coding. That being said, you probably should have several years of Java coding under your belt before you attempt this. The Spigot API is not the best for world generation, and so you will have to recreate everything that Minecraft has from scratch. That being said, this article shows you how to make a world generation algorithm in Bukkit. In addition, if you need any help, the Info Toast discord is here for you: https://discord.gg/rftS5NA.

Making you own World Generation algorithm in Bukkit
A photo of my world generation algoritm

Step 1 of making a world generation algorithm in Bukkit: Planning

The first mistake that I made when creating my world generation algorithm in Bukkit was that I made code that didn’t scale well as the algorithm got more advanced. While I was able to get basic noise in, it didn’t scale so I was able to make different biomes. You must plan everything out before you start coding the world generator, otherwise you will run into a problem when it’s starting to get good and have to start from scratch. Here are some important questions you must ask yourself before coding.

  • What biomes do I plan to have and what features of each biome will there be?
  • How to determine biomes?
  • How will I set up trees? Fractal algorithm? Use structure block files?
  • How are caves going to work?
  • How am I going to use noise?
Yet another photo of my worldgen

Step 1.5: Determining the Order

Asking questions like this will help you figure out how to right code that scales properly for what you want to do. The next thing you will want to do is determine the order in which stuff happens. Mine looks like this and you may want to consider doing this too:

  1. FastNoise creates noise map
  2. Rivers are added to noise map
  3. The type of biome is determined from the noise map – flat, mountainous, ocean, deep ocean, river
  4. The biome is determined from the type of biome based on a noise grid of temperature and humidity
  5. The world generator places surface blocks determined by the biome handler class
  6. The generator places a line of stone all the way down followed by bedrock
  7. The world generator places small items on top of the surface from a randomly generated Material in the biome handler class
  8. The worldgen runs a method in the biome handler class that allows the terrain to be transformed before the server runs BlockPopulators
  9. The BlockPopulators then populate large items such as trees based on a method in the biome handler class.
  10. Worldgen makes caves
Making a world generation algorithm in Bukkit
Jungles in my worldgen

Step 2 of making a world generation algorithm in Bukkit: Building the foundations

The next thing you will want to do to make a world generation algorithm in Bukkit is build the basic foundations for how the world generator will work. Make a normal plugin base: https://www.spigotmc.org/wiki/creating-a-blank-spigot-plugin-in-intellij-idea/. We will be using IntelliJ IDEA for this tutorial. Next, make a new class called CustomChunkGenerator. Then, add this line of code to your plugin class:

@Override
public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) {
  return new CustomChunkGenerator();
}

CustomChunkGenerator extends ChunkGenerator. You need to create a new method called with the signature:

public ChunkData generateChunkData(World world, Random random, int chunkX, int chunkZ, BiomeGrid biome) {

This is a rough sketch of what the contents of that method is going to be:

public ChunkData generateChunkData(World world, Random random, int chunkX, int chunkZ, BiomeGrid biome) {
  ChunkData chunk = createChunkData(world);
  SimplexOctaveGenerator generator = new SimplexOctaveGenerator(new Random(world.getSeed()), 8);
  generator.setScale(0.010D);
  // List of biomes that need to be transformed
  for (int x = 0; x < 16; x++) {
    for (int z = 0; z < 16; z++) {
      int rawX = chunkX * 16 + x;
      int rawZ = chunkZ * 16 + z;
      // Code that gets the block height based on the heightmap
      // Code that calculates the and sets the biome
      // Code that generates the actual blocks -- grass to bedrock
      // Code that transforms the area based on what's set in the biome handler
    }
  }
  return chunk;
}

NOTE: You must transform blocks synchronously with a lock variable otherwise it will create an error on Paper and other servers that thread plugins.

Ice Flats Biome

Step 3 of making a world generation algorithm in Bukkit: Setting up Biomes

Biomes are an extremely important part of this worldgen. Object-orientation for biomes is extremely important. You don’t want to shove all that into one class. Start by making an interface for each of your biome handlers. I included the following methods, but you can do something different.

  • boolean isOcean — pretty self-explanitory
  • Biome getBiome — What biome this should look like for vanilla clients
  • Material[] getSurface — A list of blocks on the surface (e.g. {GRASS_BLOCK, DIRT, DIRT}).
  • Material populateGrass — Not just grass, but gets a random material to put on top of the surface of the world, (e.g. DEAD_BUSH, GRASS, COBBLESTONE_SLAB)
  • void populateLargeItems — Spawns stuff like trees
  • void transformTerrain — Transforms the terrain before BlockPopulators

Now here’s the fun part. Before you start doing all the other stuff, all you need to do is make a ton of biomes. Make sure you keep in mind the temperature and humidity of each of these biomes.

Making a world generation algorithm in Bukkit
Birch and Rocky Mountains

Step 3.5: Where do the biomes go?

Now you need to actually place those biomes down. I’m not going to tell you how to do this, instead I’m going to refer you to some code that you should probably read. Check out https://github.com/Hex27/TerraformGenerator. I learned a lot of stuff about worldgen from this person’s code. You will be able to see and adapt this part to your code. However, I will tell you the very basis of what’s about to go on here, because this is the most complex part.

  • Noise algorithm creates heightmap
  • Heightmap adds rivers
  • Anything below level 61 has water on top and is an ocean biome.
  • If it’s below another level it’s deep ocean.
  • Above a certain level is a mountain biome
  • Anything in the middle is a flat biome
  • Anything that the heightmap has listed as a river is a river biome
  • Noise is based on what type of biome it is above, with erosion noise to make it a little less blocky.
  • For oceans, deep oceans, flat biomes, or mountainous biomes, use a temperature and humidity noise map to look through an array of options. Just access the proper biome by doing, for example: mountainous[temperature][moisture]. That’s your biome.
  • Populate the chunk depending on what biome it is.
  • Make your final modifications.
A pic of my worldgen in early development before I had to rewrite it to include biomes

Step 4 of making a world generation algorithm in Bukkit: The Trouble with the Trees

Trees seem to be a problem with a lot of modern Bukkit worldgen algorithms. Some of the more common ones such as TerraformGenerator use a fractal algorithm to generate trees, which looks good on paper but is a hassle for people to play survival with. That is why I recommend using pre-built trees. In fact, there is a datapack that you can use that has a ton of these trees. It’s called EasyTrees. You can download it here: https://www.planetminecraft.com/data-pack/easy-trees-4562308/. The way this datapack spawns trees is a bit weird. Basically, the player places an armor stand, which turns into an area effect cloud, which lasts a little while and then the datapack places a tree there.

The reason you don’t want to automate placing the armor stands is because while this doesn’t cause much of a problem when a player places one tree, it can become extremely laggy the longer it lasts. This is why I recommend spawning the area effect cloud, and then using the NBT API found here: https://www.spigotmc.org/resources/nbt-api.7939/ to spawn an area effect cloud that the datapack will immediately place a tree at. (I typically let the area effect cloud last for 10 ms to not interfere with other stuff the worldgen might be doing first but also not cause a lot of lag.)

Making a world generation algorithm in Bukkit
Desert in my worldgen

I am going to allow people to download the Standalone for my Lorax engine (that’s my nickname) that basically does all of that for you. I’d rather not have people steal my code, and I’d rather you distribute the Lorax engine jar with your worldgen algorithm if you use it, but I’m not going to obfuscate the jar and I’m not going to take legal action if anyone copies and pastes the decompiled code.

Step 5: Caves and Structures

Caves and Structures are often not biome dependent. This means instead of using the Biome classes, you most likely want to make completely new BlockPopulators for caves, ores, and non-biome-dependent structures. This is heavily up to the developer how to structure stuff like this, so I’m not going to show you how to do anything other than just tell you it needs to be in its own BlockPopulator.

An image of my caves (+ CaveBiomes datapack)

Step 6: Conclusion

Making a world generation algorithm in Bukkit is no small task. There’s a reason there are very few general purpose world generation algorithms on the market right now. Especially after 1.13 and OpenTerrainGenerator dropped out of the race this is even more true. There is also poor documentation which is why I made this article. If you’ve managed to do it, give yourself a tremendous pat on the back. I would also love to hear from you. Please comment below and advertise your world generator if you manage to make one, not because I want to be controlling, but because I’m nosy. I hope this article succeeds at bringing custom Spigot world generators back. If you need any help along the way, please join the Info Toast discord: https://discord.gg/rftS5NA. I would love for more intelligent coders to join our community.

Discord Server

Search Site

Frank

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *