Let's start with a basic example by extending SaplingBlock.First create a class that extends SaplingBlock.
<code>public class ExampleSapling extends SaplingBlock{}</code>
After that you can insert the constructor. It must call super with the Parameters :
{| class="wikitable" border=1
!Name !! Type !!Description
|-
| <code>treeIn</code> || <code>net.minecraft.block.trees.Tree</code> || <code>The Tree your Sapling is related to</code>
|-
| <code>properties</code> || <code>net.minecraft.block.AbstractBlock.Properties</code> || <code>The Block Properties of the Sapling</code>
|-
|}
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 <code>isValidGround</code> and make your own additions to the vanilla provided Blocks. I recommend making a
<code>private static final List<Block> validBlocks = ImmutableList.of(Blocks block...)</code> to add Blocks to the List of possible Blocks.
If you have that, your function could look like :
<syntaxhighlight lang="java">
protected boolean isValidGround(@Nonnull BlockState state,@Nonnull IBlockReader worldIn,@Nonnull BlockPos pos) {
return validBlocks.stream().anyMatch(state::isIn) || super.isValidGround(state, worldIn, pos);
}
</syntaxhighlight>
Now onto making the Tree for your Sapling.
Start by making a <code>class</code> that extends <code>Tree</code> :
<code>public class ExampleTree extends Tree </code>
This <code>class</code> will only contain one <code>function</code> which is :
<code>protected ConfiguredFeature<BaseTreeFeatureConfig, ?> getTreeFeature(Random randomIn, boolean largeHive)</code>
As you can see, this function requires to return a ConfiguredFeature<BaseTreeFeatureConfig, ?>. This will be the Tree that is Placed in the World.
The <code>ConfiguredFeature<BaseTreeFeatureConfig, ?></code> will look sth like this :
<syntaxhighlight lang="java">
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());
</syntaxhighlight>
After we have our ExampleTree we need to register it. This is done via 2 functions :
<syntaxhighlight lang="java">
public static void registerTrees() {
register("example_tree", EXAMPLETREE);
}
</syntaxhighlight>
and also the function <code>register</code> :
<syntaxhighlight lang="java">
public void register(String key, ConfiguredFeature<FC, ?> configuredFeature){
Registry.register(WorldGenRegistries.CONFIGURED_FEATURE, key, configuredFeature);
}
</syntaxhighlight >
If you have everything setup, call registerTrees() in FMLCommonSetupEvent.<br>
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 :
<syntaxhighlight lang="java">
public ExampleSapling() {
super(new ExampleTree(), AbstractBlock.Properties.create(Material.PLANTS).doesNotBlockMovement().tickRandomly().zeroHardnessAndResistance().sound(SoundType.PLANT));
}
</syntaxhighlight >
Also in your ExampleTree class, instead of null, the function now should return your TreeFeature : <br>
<syntaxhighlight lang="java">
protected ConfiguredFeature<BaseTreeFeatureConfig, ?> getTreeFeature(@Nonnull Random randomIn, boolean largeHive) {
return EXAMPLETREEFEATURE;
}
</syntaxhighlight >
Now register the Sapling like any other Block and it should be able to be placed and grow with the correct Tree.