Changes

3,990 bytes added ,  14:48, 11 March 2021
Created page with "<div class="header"> <h1>Saplings</h1> <p>How to create Saplings in Forge 1.16.4</p> </div> Let's start with a basic example by extending SaplingBlock.First create a class..."
<div class="header">
<h1>Saplings</h1>
<p>How to create Saplings in Forge 1.16.4</p>
</div>
Let's start with a basic example by extending SaplingBlock.First create a class that extends SaplingBlock.<br>
<code>public class ExampleSapling extends SaplingBlock{}</code> <br>
After that you can insert the constructor. It must call super with the Parameters : <br>
{| 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>
|-
|}<br>
That means we need to make a Tree for ourselves, but more on that in a bit.<br>
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 <br><code>private static final List<Block> validBlocks = ImmutableList.of(Blocks block...)</code> to add Blocks to the List of possible Blocks.<br>
If you have that, your function could look like : <br>
<code>
protected boolean isValidGround(@Nonnull BlockState state,@Nonnull IBlockReader worldIn,@Nonnull BlockPos pos) {
return validBlocks.stream().anyMatch(state::isIn) || super.isValidGround(state, worldIn, pos);
}
</code><br>
Now onto making the Tree for your Sapling.<br>
Start by making a <code>class</code> that extends <code>Tree</code> : <br>
<code>public class ExampleTree extends Tree </code> <br>
This <code>class</code> will only contain one <code>function</code> which is : <br>
<code>protected ConfiguredFeature<BaseTreeFeatureConfig, ?> getTreeFeature(Random randomIn, boolean largeHive)</code><br>
As you can see, this function requires to return a ConfiguredFeature<BaseTreeFeatureConfig, ?>. This will be the Tree that is Placed in the World. <br>
The <code>ConfiguredFeature<BaseTreeFeatureConfig, ?><code> will look sth like this : <br>
public static final ConfiguredFeature<BaseTreeFeatureConfig, ?> EXAMPLETREEFEATURE = <br>
Feature.TREE.withConfiguration(<br>
new BaseTreeFeatureConfig.Builder(<br>
new SimpleBlockStateProvider(BlockInit.EXAMPLE_WOOD.get().getDefaultState()),<br>
new SimpleBlockStateProvider(BlockInit.EXAMPLE_LEAVES.get().getDefaultState()),<br>
new BlobFoliagePlacer(FeatureSpread.func_242252_a(2), FeatureSpread.func_242252_a(0), 3),<br>
new StraightTrunkPlacer(4, 2, 0),<br>
new TwoLayerFeature(1, 0, 1)<br>
).setIgnoreVines().build());<br>
After we have our ExampleTree we need to register it. This is done via 2 functions : <br>
<code>public static void registerTrees() {
register("example_tree", EXAMPLETREE);
}
<code><br>
and also the function <code>register</code> :
<code>
register(String key, ConfiguredFeature<FC, ?> configuredFeature){
Registry.register(WorldGenRegistries.CONFIGURED_FEATURE, key, configuredFeature);
}
</code><br>
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 :
<code>
public ExampleSapling() {
super(new ExampleTree(), AbstractBlock.Properties.create(Material.PLANTS).doesNotBlockMovement().tickRandomly().zeroHardnessAndResistance().sound(SoundType.PLANT));
}
</code><br>
Also in your ExampleTree class, instead of null, the function now should return your TreeFeature : <br>
<code>
protected ConfiguredFeature<BaseTreeFeatureConfig, ?> getTreeFeature(@Nonnull Random randomIn, boolean largeHive) {
return EXAMPLETREEFEATURE;
}
</code><br>
Now register the Sapling like any other Block and it should be able to be placed and grow with the correct Tree.
1

edit