Custom tree generation
Custom tree generation is a tricky one, so here I am to help explain it. Your first thought may be to look into how vanilla does trees, but a quick look in there most likely would be very confusing without any comments or nicely named variables, so this tutorial will hopefully help to remedy that.WorldGenTaigaTree
or whatever the tree class is called with what our tree will be.
Speaking of our tree, let's make that class:
public class WorldGenCustomTree extends WorldGenAbstractTree {
/**
* Constructor
*/
public WorldGenCustomTree(boolean notify) {
super(notify);
}
/**
* Tree generation code
*/
public boolean generate(World worldIn, Random rand, BlockPos base) {
// ???
}
}
Here you can see our custom tree extends WorldGenAbstractTree
. This just means the game knows that our tree is a tree, and also makes sure we implement the correct methods that the game
will use whilst generating our tree (such as the generate
method). Next you will notice the generate
method itself, so what do we do with it? The answer
to that question is rather simple, yet complicated to actually achieve. This will simply contain code that given the world, and the base of the tree, will try to loop through a random
amount (utilizing the rand
variable) to generate a trunk, and likewise for the leaves atop this trunk.
// Block to use for the trunk
public static final IBlockState TRUNK = BlockInit.LOG.getDefaultState();
public boolean generate(World worldIn, Random rand, BlockPos base) {
// Trunk height is random number between 3 and 7 (4 + 3);
int trunkHeight = rand.nextInt(4) + 3;
// Not actual generation, just checking if there is enough space for the tree to generate
// Loop through how many blocks high the trunk will be
for (int i = 0; i < trunkHeight; i++) {
// If the block at this location is not air, then stop generation of the tree and tell the game generation failed
if (!(worldIn.getBlockState(new BlockPos(base.getX(), base.getY() + i + 1, base.getZ())).equals(Blocks.AIR.getDefaultState()))) {
return false;
}
}
// Actually generate trunk
for (int i = 0; i < trunkHeight; i++) {
// Set the block to our trunk block
world.setBlockState(new BlockPos(base.getX(), base.getY() + i + 1, base.getZ()), TRUNK);
}
}
So what does this code mean? Well, this is what happens:- Create a random number for the height of the trunk.
- Check if all the blocks from the base of the tree to the height of the trunk are empty, and if not, cancel the generation of the tree. We gotta have somewhere for the tree to actually grow!
- Loop through these spaces, generating the logs as we go.
Unfortunately this is a little complicated, and you will have to apply a similar approach to generating leaves, but I will not go over that here, as depending on the type of tree you're making, this can change
drastically. You could even be generating a tree that doesn't even exist yet in real life, so I cannot go over this. If you need more help generating leaves, or understanding this code, I
advise you take some courses on loops in Java. This isn't a bad thing, you just need to make sure you remember that our modding community is here to help you on modding-related issues, rather than general
Java support. If you still feel you need help, please feel welcome to stop by our Discord server and ask for some assistance in the #help-support-NUMBER
channels.
- Squishling