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