Difference between revisions of "Saplings"

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

Latest revision as of 17:59, 11 March 2021

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.