From 4e2d656e9df70666ff4c96f37cd2d15c8acab45f Mon Sep 17 00:00:00 2001 From: thedarkcolour <30441001+thedarkcolour@users.noreply.github.com> Date: Sat, 3 Sep 2022 12:07:09 -0700 Subject: [PATCH] [1.19.x] Add IForgeBlock#onTreeGrow to replace IForgeBlock#onPlantGrow from 1.16 (#8999) --- .../trunkplacers/TrunkPlacer.java.patch | 11 +++ .../common/extensions/IForgeBlock.java | 26 ++++++ .../common/extensions/IForgeBlockState.java | 25 +++++ .../debug/block/OnTreeGrowBlockTest.java | 86 ++++++++++++++++++ src/test/resources/META-INF/mods.toml | 2 + .../blockstates/test_dirt.json | 5 + .../blockstates/test_grass_block.json | 5 + .../models/block/test_dirt.json | 6 ++ .../models/block/test_grass_block.json | 11 +++ .../models/item/test_dirt.json | 3 + .../models/item/test_grass_block.json | 3 + .../textures/blocks/test_dirt.png | Bin 0 -> 477 bytes .../textures/blocks/test_grass_block_side.png | Bin 0 -> 707 bytes .../blocks/test_grass_block_side_overlay.png | Bin 0 -> 294 bytes .../textures/blocks/test_grass_block_top.png | 0 .../tags/blocks/dirt.json | 7 ++ 16 files changed, 190 insertions(+) create mode 100644 patches/minecraft/net/minecraft/world/level/levelgen/feature/trunkplacers/TrunkPlacer.java.patch create mode 100644 src/test/java/net/minecraftforge/debug/block/OnTreeGrowBlockTest.java create mode 100644 src/test/resources/assets/on_tree_grow_block_test/blockstates/test_dirt.json create mode 100644 src/test/resources/assets/on_tree_grow_block_test/blockstates/test_grass_block.json create mode 100644 src/test/resources/assets/on_tree_grow_block_test/models/block/test_dirt.json create mode 100644 src/test/resources/assets/on_tree_grow_block_test/models/block/test_grass_block.json create mode 100644 src/test/resources/assets/on_tree_grow_block_test/models/item/test_dirt.json create mode 100644 src/test/resources/assets/on_tree_grow_block_test/models/item/test_grass_block.json create mode 100644 src/test/resources/assets/on_tree_grow_block_test/textures/blocks/test_dirt.png create mode 100644 src/test/resources/assets/on_tree_grow_block_test/textures/blocks/test_grass_block_side.png create mode 100644 src/test/resources/assets/on_tree_grow_block_test/textures/blocks/test_grass_block_side_overlay.png create mode 100644 src/test/resources/assets/on_tree_grow_block_test/textures/blocks/test_grass_block_top.png create mode 100644 src/test/resources/data/on_tree_grow_block_test/tags/blocks/dirt.json diff --git a/patches/minecraft/net/minecraft/world/level/levelgen/feature/trunkplacers/TrunkPlacer.java.patch b/patches/minecraft/net/minecraft/world/level/levelgen/feature/trunkplacers/TrunkPlacer.java.patch new file mode 100644 index 0000000000..7004dcaac7 --- /dev/null +++ b/patches/minecraft/net/minecraft/world/level/levelgen/feature/trunkplacers/TrunkPlacer.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/level/levelgen/feature/trunkplacers/TrunkPlacer.java ++++ b/net/minecraft/world/level/levelgen/feature/trunkplacers/TrunkPlacer.java +@@ -58,7 +_,7 @@ + } + + protected static void m_226169_(LevelSimulatedReader p_226170_, BiConsumer p_226171_, RandomSource p_226172_, BlockPos p_226173_, TreeConfiguration p_226174_) { +- if (p_226174_.f_161215_ || !m_70295_(p_226170_, p_226173_)) { ++ if (!(((net.minecraft.world.level.LevelReader) p_226170_).m_8055_(p_226173_).onTreeGrow((net.minecraft.world.level.LevelReader) p_226170_, p_226171_, p_226172_, p_226173_, p_226174_)) && (p_226174_.f_161215_ || !m_70295_(p_226170_, p_226173_))) { + p_226171_.accept(p_226173_, p_226174_.f_161212_.m_213972_(p_226172_, p_226173_)); + } + diff --git a/src/main/java/net/minecraftforge/common/extensions/IForgeBlock.java b/src/main/java/net/minecraftforge/common/extensions/IForgeBlock.java index 1a6a3d49fa..4dab3c4bd2 100644 --- a/src/main/java/net/minecraftforge/common/extensions/IForgeBlock.java +++ b/src/main/java/net/minecraftforge/common/extensions/IForgeBlock.java @@ -6,6 +6,7 @@ package net.minecraftforge.common.extensions; import java.util.Optional; +import java.util.function.BiConsumer; import net.minecraft.client.Camera; import net.minecraft.util.RandomSource; @@ -24,6 +25,7 @@ import net.minecraft.world.item.*; import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.block.*; import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.levelgen.feature.configurations.TreeConfiguration; import net.minecraft.world.level.material.FluidState; import net.minecraft.world.level.material.MaterialColor; import net.minecraft.world.level.pathfinder.BlockPathTypes; @@ -326,6 +328,30 @@ public interface IForgeBlock */ boolean canSustainPlant(BlockState state, BlockGetter level, BlockPos pos, Direction facing, IPlantable plantable); + /** + * Called when a tree grows on top of this block and tries to set it to dirt by the trunk placer. + * An override that returns true is responsible for using the place function to + * set blocks in the world properly during generation. A modded grass block might override this method + * to ensure it turns into the corresponding modded dirt instead of regular dirt when a tree grows on it. + * For modded grass blocks, returning true from this method is NOT a substitute for adding your block + * to the #minecraft:dirt tag, rather for changing the behaviour to something other than setting to dirt. + * + * NOTE: This happens DURING world generation, the generation may be incomplete when this is called. + * Use the placeFunction when modifying the level. + * + * @param state The current state + * @param level The current level + * @param placeFunction Function to set blocks in the level for the tree, use this instead of the level directly + * @param randomSource The random source + * @param pos Position of the block to be set to dirt + * @param config Configuration of the trunk placer. Consider azalea trees, which should place rooted dirt instead of regular dirt. + * @return True to ignore vanilla behaviour + */ + default boolean onTreeGrow(BlockState state, LevelReader level, BiConsumer placeFunction, RandomSource randomSource, BlockPos pos, TreeConfiguration config) + { + return false; + } + /** * Checks if this soil is fertile, typically this means that growth rates * of plants on this soil will be slightly sped up. diff --git a/src/main/java/net/minecraftforge/common/extensions/IForgeBlockState.java b/src/main/java/net/minecraftforge/common/extensions/IForgeBlockState.java index fe55e30aeb..9b796c4f50 100644 --- a/src/main/java/net/minecraftforge/common/extensions/IForgeBlockState.java +++ b/src/main/java/net/minecraftforge/common/extensions/IForgeBlockState.java @@ -6,6 +6,7 @@ package net.minecraftforge.common.extensions; import java.util.Optional; +import java.util.function.BiConsumer; import net.minecraft.client.Camera; import net.minecraft.util.RandomSource; @@ -18,6 +19,7 @@ import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.projectile.FishingHook; import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.level.levelgen.feature.configurations.TreeConfiguration; import net.minecraft.world.level.material.FluidState; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.pathfinder.BlockPathTypes; @@ -275,6 +277,29 @@ public interface IForgeBlockState return self().getBlock().canSustainPlant(self(), level, pos, facing, plantable); } + /** + * Called when a tree grows on top of this block and tries to set it to dirt by the trunk placer. + * An override that returns true is responsible for using the place function to + * set blocks in the world properly during generation. A modded grass block might override this method + * to ensure it turns into the corresponding modded dirt instead of regular dirt when a tree grows on it. + * For modded grass blocks, returning true from this method is NOT a substitute for adding your block + * to the #minecraft:dirt tag, rather for changing the behaviour to something other than setting to dirt. + * + * NOTE: This happens DURING world generation, the generation may be incomplete when this is called. + * Use the placeFunction when modifying the level. + * + * @param level The current level + * @param placeFunction Function to set blocks in the level for the tree, use this instead of the level directly + * @param randomSource The random source + * @param pos Position of the block to be set to dirt + * @param config Configuration of the trunk placer. Consider azalea trees, which should place rooted dirt instead of regular dirt. + * @return True to ignore vanilla behaviour + */ + default boolean onTreeGrow(LevelReader level, BiConsumer placeFunction, RandomSource randomSource, BlockPos pos, TreeConfiguration config) + { + return self().getBlock().onTreeGrow(self(), level, placeFunction, randomSource, pos, config); + } + /** * Checks if this soil is fertile, typically this means that growth rates * of plants on this soil will be slightly sped up. diff --git a/src/test/java/net/minecraftforge/debug/block/OnTreeGrowBlockTest.java b/src/test/java/net/minecraftforge/debug/block/OnTreeGrowBlockTest.java new file mode 100644 index 0000000000..97fc320d07 --- /dev/null +++ b/src/test/java/net/minecraftforge/debug/block/OnTreeGrowBlockTest.java @@ -0,0 +1,86 @@ +package net.minecraftforge.debug.block; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.SaplingBlock; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.configurations.TreeConfiguration; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.material.MaterialColor; +import net.minecraftforge.common.IPlantable; +import net.minecraftforge.common.extensions.IForgeBlockState; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.ForgeRegistries; +import net.minecraftforge.registries.RegistryObject; + +import java.util.function.BiConsumer; + +/** + * A test case used to ensure that {@link IForgeBlockState#onTreeGrow(LevelReader, BiConsumer, RandomSource, BlockPos, TreeConfiguration)} + * works properly, using a custom grass block that should revert to its custom dirt form after a tree grows on + * top of it instead of turning to dirt. + */ +@Mod(OnTreeGrowBlockTest.ID) +public class OnTreeGrowBlockTest +{ + public static final boolean ENABLED = true; + + static final String ID = "on_tree_grow_block_test"; + + public static final DeferredRegister BLOCKS = DeferredRegister.create(ForgeRegistries.Keys.BLOCKS, ID); + public static final DeferredRegister ITEMS = DeferredRegister.create(ForgeRegistries.Keys.ITEMS, ID); + + public static final RegistryObject TEST_GRASS_BLOCK = BLOCKS.register("test_grass_block", () -> new Block(BlockBehaviour.Properties.of(Material.GRASS, MaterialColor.COLOR_LIGHT_BLUE).destroyTime(1.5f)) + { + @Override + public boolean canSustainPlant(BlockState state, BlockGetter world, BlockPos pos, Direction facing, IPlantable plantable) + { + return plantable instanceof SaplingBlock; + } + + @Override + public boolean onTreeGrow(BlockState state, LevelReader level, BiConsumer placeFunction, RandomSource randomSource, BlockPos pos, TreeConfiguration config) + { + // Respect vanilla behavior for trees that want custom dirt blocks + if (config.forceDirt) + { + return false; + } + else + { + placeFunction.accept(pos, TEST_DIRT.get().defaultBlockState()); + return true; + } + } + }); + public static final RegistryObject TEST_DIRT = BLOCKS.register("test_dirt", () -> new Block(BlockBehaviour.Properties.of(Material.GRASS, MaterialColor.COLOR_LIGHT_BLUE).destroyTime(1.5f)) + { + @Override + public boolean canSustainPlant(BlockState state, BlockGetter world, BlockPos pos, Direction facing, IPlantable plantable) + { + return plantable instanceof SaplingBlock; + } + }); + public static final RegistryObject TEST_GRASS_BLOCK_ITEM = ITEMS.register("test_grass_block", () -> new BlockItem(TEST_GRASS_BLOCK.get(), new Item.Properties())); + public static final RegistryObject TEST_DIRT_ITEM = ITEMS.register("test_dirt", () -> new BlockItem(TEST_DIRT.get(), new Item.Properties())); + + public OnTreeGrowBlockTest() + { + if (ENABLED) + { + IEventBus modBus = FMLJavaModLoadingContext.get().getModEventBus(); + BLOCKS.register(modBus); + ITEMS.register(modBus); + } + } +} diff --git a/src/test/resources/META-INF/mods.toml b/src/test/resources/META-INF/mods.toml index 8bb3a9b314..00f559698f 100644 --- a/src/test/resources/META-INF/mods.toml +++ b/src/test/resources/META-INF/mods.toml @@ -22,6 +22,8 @@ license="LGPL v2.1" +[[mods]] +modId="on_tree_grow_block_test" [[mods]] modId="containertypetest" [[mods]] diff --git a/src/test/resources/assets/on_tree_grow_block_test/blockstates/test_dirt.json b/src/test/resources/assets/on_tree_grow_block_test/blockstates/test_dirt.json new file mode 100644 index 0000000000..2094227ae8 --- /dev/null +++ b/src/test/resources/assets/on_tree_grow_block_test/blockstates/test_dirt.json @@ -0,0 +1,5 @@ +{ + "variants": { + "": { "model": "on_tree_grow_block_test:block/test_dirt"} + } +} \ No newline at end of file diff --git a/src/test/resources/assets/on_tree_grow_block_test/blockstates/test_grass_block.json b/src/test/resources/assets/on_tree_grow_block_test/blockstates/test_grass_block.json new file mode 100644 index 0000000000..3ee19ad9e2 --- /dev/null +++ b/src/test/resources/assets/on_tree_grow_block_test/blockstates/test_grass_block.json @@ -0,0 +1,5 @@ +{ + "variants": { + "": { "model": "on_tree_grow_block_test:block/test_grass_block"} + } +} \ No newline at end of file diff --git a/src/test/resources/assets/on_tree_grow_block_test/models/block/test_dirt.json b/src/test/resources/assets/on_tree_grow_block_test/models/block/test_dirt.json new file mode 100644 index 0000000000..832a25fb37 --- /dev/null +++ b/src/test/resources/assets/on_tree_grow_block_test/models/block/test_dirt.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "on_tree_grow_block_test:blocks/test_dirt" + } +} \ No newline at end of file diff --git a/src/test/resources/assets/on_tree_grow_block_test/models/block/test_grass_block.json b/src/test/resources/assets/on_tree_grow_block_test/models/block/test_grass_block.json new file mode 100644 index 0000000000..166ded41ea --- /dev/null +++ b/src/test/resources/assets/on_tree_grow_block_test/models/block/test_grass_block.json @@ -0,0 +1,11 @@ +{ + "parent": "minecraft:block/grass_block", + "textures": { + "particle": "on_tree_grow_block_test:blocks/test_dirt", + "bottom": "on_tree_grow_block_test:blocks/test_dirt", + "top": "on_tree_grow_block_test:blocks/test_grass_block_top", + "side": "on_tree_grow_block_test:blocks/test_grass_block_side", + "overlay": "on_tree_grow_block_test:blocks/test_grass_block_side_overlay" + }, + "render_type": "cutout_mipped" +} \ No newline at end of file diff --git a/src/test/resources/assets/on_tree_grow_block_test/models/item/test_dirt.json b/src/test/resources/assets/on_tree_grow_block_test/models/item/test_dirt.json new file mode 100644 index 0000000000..d3fcfccb89 --- /dev/null +++ b/src/test/resources/assets/on_tree_grow_block_test/models/item/test_dirt.json @@ -0,0 +1,3 @@ +{ + "parent": "on_tree_grow_block_test:block/test_dirt" +} \ No newline at end of file diff --git a/src/test/resources/assets/on_tree_grow_block_test/models/item/test_grass_block.json b/src/test/resources/assets/on_tree_grow_block_test/models/item/test_grass_block.json new file mode 100644 index 0000000000..31e5d38959 --- /dev/null +++ b/src/test/resources/assets/on_tree_grow_block_test/models/item/test_grass_block.json @@ -0,0 +1,3 @@ +{ + "parent": "on_tree_grow_block_test:block/test_grass_block" +} \ No newline at end of file diff --git a/src/test/resources/assets/on_tree_grow_block_test/textures/blocks/test_dirt.png b/src/test/resources/assets/on_tree_grow_block_test/textures/blocks/test_dirt.png new file mode 100644 index 0000000000000000000000000000000000000000..34f4a5e0a361aad320ab9b51aa8fdfe59ba38644 GIT binary patch literal 477 zcmV<30V4j1P)Px#1ZP1_K>z@;j|==^1poj5lTb`lMZRS*xM44rRWX@SFRfKEr(ie6YBaZ8G|zB1 z$ZRx@RWYJYEzfc{wOTZgQ7@KSG{9mvvtBKhM<|X;E1zIDh*2-TU^l2*G^ScKvRgBr zS~QSLE2&d2lT|UGRWZ6_FQ-v2uU9dzU^lT~H?CVNi%u=1P%XG#F~Darv|2HxRW7?= zGL=p(fk-KvS~Q+jF@sJmJa3d600009a7bBm000id000id0mpBsWB>pF(@8`@R47vw z&IfkGAP_~-Z&3!25Tit96ijTZxTI(QtBbRMckTmrjnc-F^MTMd9aQX-fnhzQ`1EWY z#(kDa;!Dxxpi1o_={1Jqm`~+A|2JrPT%4tKTPGgEULZMNxUq3M_8fvypmfM~O;WCz zHd_sDYBuA{M6=vUZf~IXj}FA_Pj}}O8PGuB$j(~Ky|95hvLbP-rV6R;C#H?WJL*;& zDPkh@=UMx(bAJ6|(cc;BG28j@gFLj03W6qHDl8RF>bI1vpc=%aYvuY-`o;VKWu6c| Tl=!Ao00000NkvXXu0mjf5Yxe- literal 0 HcmV?d00001 diff --git a/src/test/resources/assets/on_tree_grow_block_test/textures/blocks/test_grass_block_side.png b/src/test/resources/assets/on_tree_grow_block_test/textures/blocks/test_grass_block_side.png new file mode 100644 index 0000000000000000000000000000000000000000..e371500112c4460301b4c46c163f6df04acb82e9 GIT binary patch literal 707 zcmV;!0zCbRP)Px#1ZP1_K>z@;j|==^1poj6M^H>uMO|_&lDIpMxjJEbFLI1CWO*%ek2ZXlF^Qr$ zfSNR7bSrd}m*tyM9iPA!#AEv8yDr%^ACRWZ0>FPmC4o>eigU^kXkF@sJm3d$@q00009a7bBm z000id000id0mpBsWB>pG1xZ9fR47vo&DlbNKokJbYa(gdW}DfDmSp>)ZI(F|;Lvrb z7+V+`0W&M@|DWspzyXMj#Fd0Ps;X*2Nv6gior#Z6sOibn)O0dCGn;|A`Gs6Imr)iK z$S*Cgq+xYUD-_o^3bB%&-z;x!!_MwrY5$;ncywH;o}8XlKs&#vRrSlOO8vT8EH((- z+};_c)ui^lfi06c@Sr_5o?MRT(l*lP7r@syPax<1ds|9^4qyib54bc<;f9nuAnTkU zl~#mIP}co`UJI!&(X-3|1JOeWKi$ahe@Wk}aTNS%G}l0G|-ol$4bD^XJc-H!mwItE#H1rlzL3xw)^euf4rJEiJ9GvU2LwsfC4w zv9YleCr)f>X(=cu0BVhokI%`;DK0LqtE&TYRcCCs22$cBL4Lviu>yu?4$tC%N;nHV zB8wRq_zr_G