diff --git a/patches/minecraft/net/minecraft/world/level/block/ChorusFlowerBlock.java.patch b/patches/minecraft/net/minecraft/world/level/block/ChorusFlowerBlock.java.patch index c1f016378b..a07221c1b5 100644 --- a/patches/minecraft/net/minecraft/world/level/block/ChorusFlowerBlock.java.patch +++ b/patches/minecraft/net/minecraft/world/level/block/ChorusFlowerBlock.java.patch @@ -1,6 +1,6 @@ --- a/net/minecraft/world/level/block/ChorusFlowerBlock.java +++ b/net/minecraft/world/level/block/ChorusFlowerBlock.java -@@ -66,7 +_,7 @@ +@@ -66,11 +_,11 @@ BlockPos blockpos = p_220982_.above(); if (p_220981_.isEmptyBlock(blockpos) && blockpos.getY() <= p_220981_.getMaxY()) { int i = p_220980_.getValue(AGE); @@ -9,6 +9,20 @@ boolean flag = false; boolean flag1 = false; BlockState blockstate = p_220981_.getBlockState(p_220982_.below()); +- if (blockstate.is(Blocks.END_STONE)) { ++ if (blockstate.is(Blocks.END_STONE) || blockstate.is(net.minecraftforge.common.Tags.Blocks.CHORUS_ADDITIONALLY_GROWS_ON)) { + flag = true; + } else if (blockstate.is(this.plant)) { + int j = 1; +@@ -78,7 +_,7 @@ + for (int k = 0; k < 4; k++) { + BlockState blockstate1 = p_220981_.getBlockState(p_220982_.below(j + 1)); + if (!blockstate1.is(this.plant)) { +- if (blockstate1.is(Blocks.END_STONE)) { ++ if (blockstate1.is(Blocks.END_STONE) || blockstate1.is(net.minecraftforge.common.Tags.Blocks.CHORUS_ADDITIONALLY_GROWS_ON)) { + flag1 = true; + } + break; @@ -122,6 +_,7 @@ } else { this.placeDeadFlower(p_220981_, p_220982_); @@ -17,3 +31,12 @@ } } } +@@ -167,7 +_,7 @@ + @Override + protected boolean canSurvive(BlockState p_51683_, LevelReader p_51684_, BlockPos p_51685_) { + BlockState blockstate = p_51684_.getBlockState(p_51685_.below()); +- if (!blockstate.is(this.plant) && !blockstate.is(Blocks.END_STONE)) { ++ if (!blockstate.is(this.plant) && !blockstate.is(Blocks.END_STONE) && !blockstate.is(net.minecraftforge.common.Tags.Blocks.CHORUS_ADDITIONALLY_GROWS_ON)) { + if (!blockstate.isAir()) { + return false; + } else { diff --git a/patches/minecraft/net/minecraft/world/level/block/ChorusPlantBlock.java.patch b/patches/minecraft/net/minecraft/world/level/block/ChorusPlantBlock.java.patch new file mode 100644 index 0000000000..1f7dea618a --- /dev/null +++ b/patches/minecraft/net/minecraft/world/level/block/ChorusPlantBlock.java.patch @@ -0,0 +1,36 @@ +--- a/net/minecraft/world/level/block/ChorusPlantBlock.java ++++ b/net/minecraft/world/level/block/ChorusPlantBlock.java +@@ -50,7 +_,7 @@ + BlockState blockstate5 = p_51711_.getBlockState(p_51712_.west()); + Block block = p_312378_.getBlock(); + return p_312378_.trySetValue( +- DOWN, Boolean.valueOf(blockstate.is(block) || blockstate.is(Blocks.CHORUS_FLOWER) || blockstate.is(Blocks.END_STONE)) ++ DOWN, Boolean.valueOf(blockstate.is(block) || blockstate.is(Blocks.CHORUS_FLOWER) || blockstate.is(Blocks.END_STONE) || blockstate.is(net.minecraftforge.common.Tags.Blocks.CHORUS_ADDITIONALLY_GROWS_ON)) + ) + .trySetValue(UP, Boolean.valueOf(blockstate1.is(block) || blockstate1.is(Blocks.CHORUS_FLOWER))) + .trySetValue(NORTH, Boolean.valueOf(blockstate2.is(block) || blockstate2.is(Blocks.CHORUS_FLOWER))) +@@ -74,7 +_,7 @@ + p_364837_.scheduleTick(p_51732_, this, 1); + return super.updateShape(p_51728_, p_369826_, p_364837_, p_51732_, p_51729_, p_51733_, p_51730_, p_368636_); + } else { +- boolean flag = p_51730_.is(this) || p_51730_.is(Blocks.CHORUS_FLOWER) || p_51729_ == Direction.DOWN && p_51730_.is(Blocks.END_STONE); ++ boolean flag = p_51730_.is(this) || p_51730_.is(Blocks.CHORUS_FLOWER) || p_51729_ == Direction.DOWN && (p_51730_.is(Blocks.END_STONE) || p_51730_.is(net.minecraftforge.common.Tags.Blocks.CHORUS_ADDITIONALLY_GROWS_ON)); + return p_51728_.setValue(PROPERTY_BY_DIRECTION.get(p_51729_), Boolean.valueOf(flag)); + } + } +@@ -100,13 +_,13 @@ + } + + BlockState blockstate2 = p_51725_.getBlockState(blockpos.below()); +- if (blockstate2.is(this) || blockstate2.is(Blocks.END_STONE)) { ++ if (blockstate2.is(this) || blockstate2.is(Blocks.END_STONE) || blockstate2.is(net.minecraftforge.common.Tags.Blocks.CHORUS_ADDITIONALLY_GROWS_ON)) { + return true; + } + } + } + +- return blockstate.is(this) || blockstate.is(Blocks.END_STONE); ++ return blockstate.is(this) || blockstate.is(Blocks.END_STONE) || blockstate.is(net.minecraftforge.common.Tags.Blocks.CHORUS_ADDITIONALLY_GROWS_ON); + } + + @Override diff --git a/src/main/generated/data/forge/tags/block/chorus_additionally_grows_on.json b/src/main/generated/data/forge/tags/block/chorus_additionally_grows_on.json new file mode 100644 index 0000000000..4451697d12 --- /dev/null +++ b/src/main/generated/data/forge/tags/block/chorus_additionally_grows_on.json @@ -0,0 +1,5 @@ +{ + "values": [ + "#forge:end_stones" + ] +} \ No newline at end of file diff --git a/src/main/java/net/minecraftforge/common/Tags.java b/src/main/java/net/minecraftforge/common/Tags.java index d2f40eaebd..a2a74767ce 100644 --- a/src/main/java/net/minecraftforge/common/Tags.java +++ b/src/main/java/net/minecraftforge/common/Tags.java @@ -55,6 +55,7 @@ public class Tags { public static final TagKey CHESTS_ENDER = forgeTag("chests/ender"); public static final TagKey CHESTS_TRAPPED = forgeTag("chests/trapped"); + public static final TagKey CHORUS_ADDITIONALLY_GROWS_ON = forgeTag("chorus_additionally_grows_on"); public static final TagKey COBBLESTONE_NORMAL = forgeTag("cobblestone/normal"); public static final TagKey COBBLESTONE_INFESTED = forgeTag("cobblestone/infested"); public static final TagKey COBBLESTONE_MOSSY = forgeTag("cobblestone/mossy"); diff --git a/src/main/java/net/minecraftforge/common/data/ForgeBlockTagsProvider.java b/src/main/java/net/minecraftforge/common/data/ForgeBlockTagsProvider.java index f3c22aaf4d..7fb5a28b89 100644 --- a/src/main/java/net/minecraftforge/common/data/ForgeBlockTagsProvider.java +++ b/src/main/java/net/minecraftforge/common/data/ForgeBlockTagsProvider.java @@ -55,6 +55,8 @@ public final class ForgeBlockTagsProvider extends BlockTagsProvider { tag(CHESTS_WOODEN) .add(Blocks.CHEST, Blocks.TRAPPED_CHEST) .addOptionalTag(forgeTagKey("chests/wooden")); + tag(CHORUS_ADDITIONALLY_GROWS_ON) + .addTag(END_STONES); tag(CLUSTERS).add(Blocks.AMETHYST_CLUSTER); tag(COBBLESTONES) .addTags(COBBLESTONE_NORMAL, COBBLESTONE_INFESTED, COBBLESTONE_MOSSY, COBBLESTONE_DEEPSLATE) diff --git a/src/main/java/net/minecraftforge/common/extensions/IForgeGameTestHelper.java b/src/main/java/net/minecraftforge/common/extensions/IForgeGameTestHelper.java index 30a30a4114..1060b72471 100644 --- a/src/main/java/net/minecraftforge/common/extensions/IForgeGameTestHelper.java +++ b/src/main/java/net/minecraftforge/common/extensions/IForgeGameTestHelper.java @@ -16,6 +16,7 @@ import net.minecraft.Util; import net.minecraft.network.chat.MutableComponent; import net.minecraft.core.Registry; import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.block.state.BlockState; import org.jetbrains.annotations.Nullable; import com.mojang.authlib.GameProfile; @@ -186,6 +187,26 @@ public interface IForgeGameTestHelper { } } + default BlockState setAndAssertBlock(int x, int y, int z, Block block) { + return this.setAndAssertBlock(x, y, z, block.defaultBlockState()); + } + + default BlockState setAndAssertBlock(int x, int y, int z, BlockState state) { + return this.setAndAssertBlock(new BlockPos(x, y, z), state); + } + + default BlockState setAndAssertBlock(BlockPos pos, Block block) { + return this.setAndAssertBlock(pos, block.defaultBlockState()); + } + + default BlockState setAndAssertBlock(BlockPos pos, BlockState state) { + this.assertTrue( + this.self().getLevel().setBlock(this.self().absolutePos(pos), state, Block.UPDATE_ALL), + () -> "Failed to set block at pos %s : %s".formatted(pos, state.getBlock()) + ); + return state; + } + default Flag flag(String name) { return new Flag<>(name); } diff --git a/src/test/generated/chorus_block_placement/data/forge/tags/block/chorus_additionally_grows_on.json b/src/test/generated/chorus_block_placement/data/forge/tags/block/chorus_additionally_grows_on.json new file mode 100644 index 0000000000..202e19cbc3 --- /dev/null +++ b/src/test/generated/chorus_block_placement/data/forge/tags/block/chorus_additionally_grows_on.json @@ -0,0 +1,5 @@ +{ + "values": [ + "chorus_block_placement:placeable_on_chorus" + ] +} \ No newline at end of file diff --git a/src/test/java/net/minecraftforge/debug/gameplay/block/ChorusBlockPlacementTest.java b/src/test/java/net/minecraftforge/debug/gameplay/block/ChorusBlockPlacementTest.java new file mode 100644 index 0000000000..537f3c7471 --- /dev/null +++ b/src/test/java/net/minecraftforge/debug/gameplay/block/ChorusBlockPlacementTest.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) Forge Development LLC and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ + +package net.minecraftforge.debug.gameplay.block; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.HolderLookup; +import net.minecraft.gametest.framework.GameTest; +import net.minecraft.gametest.framework.GameTestHelper; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.Tags; +import net.minecraftforge.common.data.BlockTagsProvider; +import net.minecraftforge.data.event.GatherDataEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import net.minecraftforge.gametest.GameTestHolder; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.ForgeRegistries; +import net.minecraftforge.registries.RegistryObject; +import net.minecraftforge.test.BaseTestMod; + +@GameTestHolder("forge." + ChorusBlockPlacementTest.MOD_ID) +@Mod(ChorusBlockPlacementTest.MOD_ID) +public class ChorusBlockPlacementTest extends BaseTestMod { + static final String MOD_ID = "chorus_block_placement"; + + private static final DeferredRegister BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MOD_ID); + private static final RegistryObject BLOCK = BLOCKS.register("placeable_on_chorus", () -> new Block(Block.Properties.of().setId(BLOCKS.key("placeable_on_chorus")))); + + public ChorusBlockPlacementTest(FMLJavaModLoadingContext context) { + super(context); + } + + @GameTest(template = "forge:empty3x3x3") + public static void custom_placeable_block(GameTestHelper helper) { + var custom = helper.setAndAssertBlock(BlockPos.ZERO, BLOCK.get()); + helper.assertTrue(custom.is(Tags.Blocks.CHORUS_ADDITIONALLY_GROWS_ON), () -> "Block %s is not placeable on chorus".formatted(custom.getBlock())); + + helper.setAndAssertBlock(BlockPos.ZERO.above(), Blocks.CHORUS_FLOWER); + helper.runAfterDelay(1, () -> { + helper.assertBlockPresent(Blocks.CHORUS_FLOWER, BlockPos.ZERO.above()); + helper.succeed(); + }); + } + + @SubscribeEvent + public void runData(GatherDataEvent event) { + event.getGenerator().addProvider(event.includeServer(), new BlockTags(event)); + } + + private static final class BlockTags extends BlockTagsProvider { + public BlockTags(GatherDataEvent event) { + super(event.getGenerator().getPackOutput(), event.getLookupProvider(), MOD_ID, event.getExistingFileHelper()); + } + + @Override + protected void addTags(HolderLookup.Provider provider) { + this.tag(Tags.Blocks.CHORUS_ADDITIONALLY_GROWS_ON).add(BLOCK.get()); + } + } +}