Saplings

From Forge Community Wiki

Let's start with a basic example by extending SaplingBlock.First create a class that extends SaplingBlock.

public class ExampleSapling extends SaplingBlock{}

After that you can insert the constructor. It must call super with the Parameters :

Name Type Description
treeIn net.minecraft.block.trees.Tree The Tree your Sapling is related to
properties net.minecraft.block.AbstractBlock.Properties The Block Properties of the Sapling


That means we need to make a Tree for ourselves, but more on that in a bit. If you want to have the Sapling be placeable on your own Mods Block, you need to override isValidGround and make your own additions to the vanilla provided Blocks. I recommend making a private static final List<Block> validBlocks = ImmutableList.of(Blocks block...) to add Blocks to the List of possible Blocks. If you have that, your function could look like :

protected boolean isValidGround(@Nonnull BlockState state,@Nonnull IBlockReader worldIn,@Nonnull BlockPos pos) {
return validBlocks.stream().anyMatch(state::isIn) || super.isValidGround(state, worldIn, pos);
}

Now onto making the Tree for your Sapling.

Start by making a class that extends Tree :

public class ExampleTree extends Tree This class will only contain one function which is : protected ConfiguredFeature<BaseTreeFeatureConfig, ?> getTreeFeature(Random randomIn, boolean largeHive) As you can see, this function requires to return a ConfiguredFeature<BaseTreeFeatureConfig, ?>. This will be the Tree that is Placed in the World. The ConfiguredFeature<BaseTreeFeatureConfig, ?> will look sth like this :

public static final ConfiguredFeature<BaseTreeFeatureConfig, ?> EXAMPLETREEFEATURE = 
 Feature.TREE.withConfiguration(
            new BaseTreeFeatureConfig.Builder(
                    new SimpleBlockStateProvider(BlockInit.EXAMPLE_WOOD.get().getDefaultState()),
                    new SimpleBlockStateProvider(BlockInit.EXAMPLE_LEAVES.get().getDefaultState()),
                    new BlobFoliagePlacer(FeatureSpread.func_242252_a(2), FeatureSpread.func_242252_a(0), 3),
                    new StraightTrunkPlacer(4, 2, 0),
                    new TwoLayerFeature(1, 0, 1)
            ).setIgnoreVines().build());

After we have our ExampleTree we need to register it. This is done via 2 functions :

public static void registerTrees() {
        register("example_tree", EXAMPLETREE);
    }

and also the function register :

public void register(String key, ConfiguredFeature<FC, ?> configuredFeature){
Registry.register(WorldGenRegistries.CONFIGURED_FEATURE, key, configuredFeature);
}

If you have everything setup, call registerTrees() in FMLCommonSetupEvent.
Back to the Sapling. Your constructor can now be completed by putting the Tree we just registered as the first super parameter and the Properties as the second parameter :

public ExampleSapling() {
        super(new ExampleTree(), AbstractBlock.Properties.create(Material.PLANTS).doesNotBlockMovement().tickRandomly().zeroHardnessAndResistance().sound(SoundType.PLANT));
    }

Also in your ExampleTree class, instead of null, the function now should return your TreeFeature :

protected ConfiguredFeature<BaseTreeFeatureConfig, ?> getTreeFeature(@Nonnull Random randomIn, boolean largeHive) {
        return EXAMPLETREEFEATURE;
    }

Now register the Sapling like any other Block and it should be able to be placed and grow with the correct Tree.