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. |