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.
First of all you will probably want to have a biome already made, and know how to add vanilla trees to that biome (look in some other vanilla biome classes for details).  How we will implement our tree generation in the biome is basically the same, just replace WorldGenTaigaTree or whatever the tree class is called with what our tree will be.  Speaking of our tree, let's make that class:
// imports

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.
Well that's all well and good, but let's go into more detail about how exactly we achieve that in code.  Let's look at the following example for generating the trunk of a tree:
// 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.

Thank you for following my custom tree generation guide/tutorial, I hope you found this useful! :)
- Squishling