From cd67762beeb680034d2b57c4584c5eafb4e4bead Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rikka0=5F0=E5=B0=8F=E5=85=AD=E8=8A=B1?= <929513338@qq.com> Date: Tue, 28 Sep 2021 05:26:17 +1000 Subject: [PATCH] [1.17.x] implements canConnectRedstone(), Redstone dust now defers to the blockstate for determining connectivity (#8014) --- .../level/block/RedStoneWireBlock.java.patch | 27 ++++++ .../common/extensions/IForgeBlock.java | 50 ++++++++++ .../common/extensions/IForgeBlockState.java | 15 +++ .../block/RedstoneSidedConnectivityTest.java | 97 +++++++++++++++++++ src/test/resources/META-INF/mods.toml | 2 + .../test_east_redstone_connect.json | 7 ++ .../lang/en_us.json | 3 + .../block/test_east_redstone_connect.json | 12 +++ .../item/test_east_redstone_connect.json | 3 + 9 files changed, 216 insertions(+) create mode 100644 patches/minecraft/net/minecraft/world/level/block/RedStoneWireBlock.java.patch create mode 100644 src/test/java/net/minecraftforge/debug/block/RedstoneSidedConnectivityTest.java create mode 100644 src/test/resources/assets/redstone_sided_connectivity_test/blockstates/test_east_redstone_connect.json create mode 100644 src/test/resources/assets/redstone_sided_connectivity_test/lang/en_us.json create mode 100644 src/test/resources/assets/redstone_sided_connectivity_test/models/block/test_east_redstone_connect.json create mode 100644 src/test/resources/assets/redstone_sided_connectivity_test/models/item/test_east_redstone_connect.json diff --git a/patches/minecraft/net/minecraft/world/level/block/RedStoneWireBlock.java.patch b/patches/minecraft/net/minecraft/world/level/block/RedStoneWireBlock.java.patch new file mode 100644 index 0000000000..0a7730ab2b --- /dev/null +++ b/patches/minecraft/net/minecraft/world/level/block/RedStoneWireBlock.java.patch @@ -0,0 +1,27 @@ +--- a/net/minecraft/world/level/block/RedStoneWireBlock.java ++++ b/net/minecraft/world/level/block/RedStoneWireBlock.java +@@ -199,7 +_,7 @@ + BlockState blockstate = p_55523_.m_8055_(blockpos); + if (p_55526_) { + boolean flag = this.m_55612_(p_55523_, blockpos, blockstate); +- if (flag && m_55640_(p_55523_.m_8055_(blockpos.m_7494_()))) { ++ if (flag && p_55523_.m_8055_(blockpos.m_7494_()).canRedstoneConnectTo(p_55523_, blockpos.m_7494_(), null)) { + if (blockstate.m_60783_(p_55523_, blockpos, p_55525_.m_122424_())) { + return RedstoneSide.UP; + } +@@ -208,7 +_,14 @@ + } + } + +- return !m_55594_(blockstate, p_55525_) && (blockstate.m_60796_(p_55523_, blockpos) || !m_55640_(p_55523_.m_8055_(blockpos.m_7495_()))) ? RedstoneSide.NONE : RedstoneSide.SIDE; ++ if (blockstate.canRedstoneConnectTo(p_55523_, blockpos, p_55525_)) { ++ return RedstoneSide.SIDE; ++ } else if (blockstate.m_60796_(p_55523_, blockpos)) { ++ return RedstoneSide.NONE; ++ } else { ++ BlockPos blockPosBelow = blockpos.m_7495_(); ++ return p_55523_.m_8055_(blockPosBelow).canRedstoneConnectTo(p_55523_, blockPosBelow, null) ? RedstoneSide.SIDE : RedstoneSide.NONE; ++ } + } + + public boolean m_7898_(BlockState p_55585_, LevelReader p_55586_, BlockPos p_55587_) { diff --git a/src/main/java/net/minecraftforge/common/extensions/IForgeBlock.java b/src/main/java/net/minecraftforge/common/extensions/IForgeBlock.java index decfd3b26e..51e61be00a 100644 --- a/src/main/java/net/minecraftforge/common/extensions/IForgeBlock.java +++ b/src/main/java/net/minecraftforge/common/extensions/IForgeBlock.java @@ -719,4 +719,54 @@ public interface IForgeBlock { return state.is(Blocks.SCAFFOLDING); } + + /** + * Whether redstone dust should visually connect to this block on a given side + *

+ * The default implementation is identical to + * {@link RedStoneWireBlock#shouldConnectTo(BlockState, Direction)} + * + *

+ * {@link RedStoneWireBlock} updates its visual connection when + * {@link BlockState#updateShape(Direction, BlockState, LevelAccessor, BlockPos, BlockPos)} + * is called, this callback is used during the evaluation of its new shape. + * + * @param state The current state + * @param world The world + * @param pos The block position in world + * @param direction The coming direction of the redstone dust connection (with respect to the block at pos) + * @return True if redstone dust should visually connect on the side passed + *

+ * If the return value is evaluated based on world and pos (e.g. from BlockEntity), then the implementation of + * this block should notify its neighbors to update their shapes when necessary. Consider using + * {@link BlockState#updateNeighbourShapes(LevelAccessor, BlockPos, int, int)} or + * {@link BlockState#updateShape(Direction, BlockState, LevelAccessor, BlockPos, BlockPos)}. + *

+ * Example: + *

+ * 1. {@code yourBlockState.updateNeighbourShapes(world, yourBlockPos, UPDATE_ALL);} + *

+ * 2. {@code neighborState.updateShape(fromDirection, stateOfYourBlock, world, neighborBlockPos, yourBlockPos)}, + * where {@code fromDirection} is defined from the neighbor block's point of view. + */ + default boolean canConnectRedstone(BlockState state, BlockGetter world, BlockPos pos, @Nullable Direction direction) + { + if (state.is(Blocks.REDSTONE_WIRE)) + { + return true; + } + else if (state.is(Blocks.REPEATER)) + { + Direction facing = state.getValue(RepeaterBlock.FACING); + return facing == direction || facing.getOpposite() == direction; + } + else if (state.is(Blocks.OBSERVER)) + { + return direction == state.getValue(ObserverBlock.FACING); + } + else + { + return state.isSignalSource() && direction != null; + } + } } diff --git a/src/main/java/net/minecraftforge/common/extensions/IForgeBlockState.java b/src/main/java/net/minecraftforge/common/extensions/IForgeBlockState.java index eba46a9749..8a7f7eb1f7 100644 --- a/src/main/java/net/minecraftforge/common/extensions/IForgeBlockState.java +++ b/src/main/java/net/minecraftforge/common/extensions/IForgeBlockState.java @@ -641,4 +641,19 @@ public interface IForgeBlockState { return self().getBlock().isScaffolding(self(), entity.level, entity.blockPosition(), entity); } + + /** + * Whether redstone dust should visually connect to this block on a side. + *

+ * Modded redstone wire blocks should call this function to determine visual connections. + * + * @param world The world + * @param pos The block position in world + * @param direction The coming direction of the redstone dust connection (with respect to the block at pos) + * @return True if redstone dust should visually connect on the side passed + */ + default boolean canRedstoneConnectTo(BlockGetter world, BlockPos pos, @Nullable Direction direction) + { + return self().getBlock().canConnectRedstone(self(), world, pos, direction); + } } diff --git a/src/test/java/net/minecraftforge/debug/block/RedstoneSidedConnectivityTest.java b/src/test/java/net/minecraftforge/debug/block/RedstoneSidedConnectivityTest.java new file mode 100644 index 0000000000..3349c8fdd7 --- /dev/null +++ b/src/test/java/net/minecraftforge/debug/block/RedstoneSidedConnectivityTest.java @@ -0,0 +1,97 @@ +/* + * Minecraft Forge + * Copyright (c) 2016-2021. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.debug.block; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.CreativeModeTab; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.FurnaceBlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Material; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import net.minecraftforge.fmllegacy.RegistryObject; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.ForgeRegistries; + +import javax.annotation.Nullable; + +@Mod(RedstoneSidedConnectivityTest.MODID) +public class RedstoneSidedConnectivityTest +{ + public static final boolean ENABLE = true; + static final String MODID = "redstone_sided_connectivity_test"; + static final String BLOCK_ID = "test_east_redstone_connect"; + + private static final DeferredRegister BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID); + private static final DeferredRegister ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, MODID); + + private static final RegistryObject TEST_REDSTONE_BLOCK = BLOCKS.register(BLOCK_ID, EastRedstoneBlock::new); + private static final RegistryObject TEST_REDSTONE_BLOCKITEM = ITEMS.register(BLOCK_ID, () -> new BlockItem(TEST_REDSTONE_BLOCK.get(), new Item.Properties().tab(CreativeModeTab.TAB_BUILDING_BLOCKS))); + + public RedstoneSidedConnectivityTest() + { + if (!ENABLE) + return; + + IEventBus modBus = FMLJavaModLoadingContext.get().getModEventBus(); + BLOCKS.register(modBus); + ITEMS.register(modBus); + } + + private static class EastRedstoneBlock extends Block + { + //This block visually connect to redstone dust only on the east side + //if a furnace block is placed on top of it + + public EastRedstoneBlock() + { + super(Properties.of(Material.METAL)); + } + + @Override + public boolean canConnectRedstone(BlockState state, BlockGetter world, BlockPos pos, @Nullable Direction direction) + { + //The passed direction is relative to the redstone dust + //This block connects on the east side relative to this block, which is west for the dust + return direction == Direction.WEST && + world.getBlockEntity(pos.relative(Direction.UP)) instanceof FurnaceBlockEntity; + } + + @SuppressWarnings("deprecation") + @Override + public void neighborChanged(BlockState state, Level world, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) + { + if (pos.relative(Direction.UP).equals(fromPos)) + { + //Notify neighbors if the redstone connection may change + state.updateNeighbourShapes(world, pos, UPDATE_ALL); + } + + super.neighborChanged(state, world, pos, block, fromPos, isMoving); + } + } +} diff --git a/src/test/resources/META-INF/mods.toml b/src/test/resources/META-INF/mods.toml index 6b32680359..66202a1bc4 100644 --- a/src/test/resources/META-INF/mods.toml +++ b/src/test/resources/META-INF/mods.toml @@ -148,6 +148,8 @@ license="LGPL v2.1" modId="tag_based_tool_types" [[mods]] modId="check_spawn_event_test" +[[mods]] + modId="redstone_sided_connectivity_test" [[mods]] modId="permissions_changed_event_test" [[mods]] diff --git a/src/test/resources/assets/redstone_sided_connectivity_test/blockstates/test_east_redstone_connect.json b/src/test/resources/assets/redstone_sided_connectivity_test/blockstates/test_east_redstone_connect.json new file mode 100644 index 0000000000..7bc00382d9 --- /dev/null +++ b/src/test/resources/assets/redstone_sided_connectivity_test/blockstates/test_east_redstone_connect.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "redstone_sided_connectivity_test:block/test_east_redstone_connect" + } + } +} diff --git a/src/test/resources/assets/redstone_sided_connectivity_test/lang/en_us.json b/src/test/resources/assets/redstone_sided_connectivity_test/lang/en_us.json new file mode 100644 index 0000000000..e94fcfe098 --- /dev/null +++ b/src/test/resources/assets/redstone_sided_connectivity_test/lang/en_us.json @@ -0,0 +1,3 @@ +{ + "block.redstone_sided_connectivity_test.test_east_redstone_connect": "Redstone Connector on East Only If Furnace on Top" +} diff --git a/src/test/resources/assets/redstone_sided_connectivity_test/models/block/test_east_redstone_connect.json b/src/test/resources/assets/redstone_sided_connectivity_test/models/block/test_east_redstone_connect.json new file mode 100644 index 0000000000..21ae5082cc --- /dev/null +++ b/src/test/resources/assets/redstone_sided_connectivity_test/models/block/test_east_redstone_connect.json @@ -0,0 +1,12 @@ +{ + "parent": "minecraft:block/cube", + "textures": { + "up": "minecraft:block/observer_front", + "down": "minecraft:block/furnace_side", + "north": "minecraft:block/furnace_side", + "east": "minecraft:block/observer_back", + "south": "minecraft:block/furnace_side", + "west": "minecraft:block/furnace_side", + "particle": "minecraft:block/observer_front" + } +} diff --git a/src/test/resources/assets/redstone_sided_connectivity_test/models/item/test_east_redstone_connect.json b/src/test/resources/assets/redstone_sided_connectivity_test/models/item/test_east_redstone_connect.json new file mode 100644 index 0000000000..12994bdadf --- /dev/null +++ b/src/test/resources/assets/redstone_sided_connectivity_test/models/item/test_east_redstone_connect.json @@ -0,0 +1,3 @@ +{ + "parent": "redstone_sided_connectivity_test:block/test_east_redstone_connect" +}