From c528695d1ae85de6ebcef4408df63f0dbf07a805 Mon Sep 17 00:00:00 2001 From: Space Walker <48224626+SpaceWalkerRS@users.noreply.github.com> Date: Sat, 3 Sep 2022 22:49:01 +0200 Subject: [PATCH] Refactor Carpet's sticky blocks code (#1505) refactor sticky blocks code --- .../carpet/fakes/BlockBehaviourInterface.java | 20 ++ .../BlockBehaviour_customStickyMixin.java | 25 ++ .../mixins/ChainBlock_customStickyMixin.java | 46 +++ .../mixins/ChestBlock_customStickyMixin.java | 45 +++ .../mixins/HoneyBlock_customStickyMixin.java | 26 ++ .../PistonHandler_customStickyMixin.java | 313 ------------------ ...onStructureResolver_customStickyMixin.java | 94 ++++++ .../mixins/SlimeBlock_customStickyMixin.java | 26 ++ src/main/resources/carpet.mixins.json | 10 +- 9 files changed, 290 insertions(+), 315 deletions(-) create mode 100644 src/main/java/carpet/fakes/BlockBehaviourInterface.java create mode 100644 src/main/java/carpet/mixins/BlockBehaviour_customStickyMixin.java create mode 100644 src/main/java/carpet/mixins/ChainBlock_customStickyMixin.java create mode 100644 src/main/java/carpet/mixins/ChestBlock_customStickyMixin.java create mode 100644 src/main/java/carpet/mixins/HoneyBlock_customStickyMixin.java delete mode 100644 src/main/java/carpet/mixins/PistonHandler_customStickyMixin.java create mode 100644 src/main/java/carpet/mixins/PistonStructureResolver_customStickyMixin.java create mode 100644 src/main/java/carpet/mixins/SlimeBlock_customStickyMixin.java diff --git a/src/main/java/carpet/fakes/BlockBehaviourInterface.java b/src/main/java/carpet/fakes/BlockBehaviourInterface.java new file mode 100644 index 00000000..289c0743 --- /dev/null +++ b/src/main/java/carpet/fakes/BlockBehaviourInterface.java @@ -0,0 +1,20 @@ +package carpet.fakes; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; + +public interface BlockBehaviourInterface { + + /** + * @return whether this block is sticky in any way when moved by pistons + */ + public boolean isSticky(BlockState state); + + /** + * @return whether the neighboring block is pulled along if this block is moved by pistons + */ + public boolean isStickyToNeighbor(Level level, BlockPos pos, BlockState state, BlockPos neighborPos, BlockState neighborState, Direction dir, Direction moveDir); + +} diff --git a/src/main/java/carpet/mixins/BlockBehaviour_customStickyMixin.java b/src/main/java/carpet/mixins/BlockBehaviour_customStickyMixin.java new file mode 100644 index 00000000..55fc78b4 --- /dev/null +++ b/src/main/java/carpet/mixins/BlockBehaviour_customStickyMixin.java @@ -0,0 +1,25 @@ +package carpet.mixins; + +import org.spongepowered.asm.mixin.Mixin; + +import carpet.fakes.BlockBehaviourInterface; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.state.BlockState; + +@Mixin(BlockBehaviour.class) +public class BlockBehaviour_customStickyMixin implements BlockBehaviourInterface { + + @Override + public boolean isSticky(BlockState state) { + return false; + } + + @Override + public boolean isStickyToNeighbor(Level level, BlockPos pos, BlockState state, BlockPos neighborPos, BlockState neighborState, Direction dir, Direction moveDir) { + return false; + } +} diff --git a/src/main/java/carpet/mixins/ChainBlock_customStickyMixin.java b/src/main/java/carpet/mixins/ChainBlock_customStickyMixin.java new file mode 100644 index 00000000..2e2d1e01 --- /dev/null +++ b/src/main/java/carpet/mixins/ChainBlock_customStickyMixin.java @@ -0,0 +1,46 @@ +package carpet.mixins; + +import org.spongepowered.asm.mixin.Mixin; + +import carpet.CarpetSettings; +import carpet.fakes.BlockBehaviourInterface; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.ChainBlock; +import net.minecraft.world.level.block.EndRodBlock; +import net.minecraft.world.level.block.state.BlockState; + +@Mixin(ChainBlock.class) +public class ChainBlock_customStickyMixin implements BlockBehaviourInterface { + + @Override + public boolean isSticky(BlockState state) { + return CarpetSettings.doChainStone; + } + + @Override + public boolean isStickyToNeighbor(Level level, BlockPos pos, BlockState state, BlockPos neighborPos, BlockState neighborState, Direction dir, Direction moveDir) { + Axis axis = state.getValue(ChainBlock.AXIS); + + if (axis != dir.getAxis()) { + return false; + } + + if (CarpetSettings.chainStoneStickToAll) { + return true; + } + if (neighborState.is((Block)(Object)this)) { + return axis == neighborState.getValue(ChainBlock.AXIS); + } + if (neighborState.is(Blocks.END_ROD)) { + return axis == neighborState.getValue(EndRodBlock.FACING).getAxis(); + } + + return Block.canSupportCenter(level, neighborPos, dir.getOpposite()); + } +} diff --git a/src/main/java/carpet/mixins/ChestBlock_customStickyMixin.java b/src/main/java/carpet/mixins/ChestBlock_customStickyMixin.java new file mode 100644 index 00000000..23b369ae --- /dev/null +++ b/src/main/java/carpet/mixins/ChestBlock_customStickyMixin.java @@ -0,0 +1,45 @@ +package carpet.mixins; + +import org.spongepowered.asm.mixin.Mixin; + +import carpet.CarpetSettings; +import carpet.fakes.BlockBehaviourInterface; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.ChestBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.ChestType; + +@Mixin(ChestBlock.class) +public class ChestBlock_customStickyMixin implements BlockBehaviourInterface { + + @Override + public boolean isSticky(BlockState state) { + return CarpetSettings.movableBlockEntities; + } + + @Override + public boolean isStickyToNeighbor(Level level, BlockPos pos, BlockState state, BlockPos neighborPos, BlockState neighborState, Direction dir, Direction moveDir) { + if (!neighborState.is((Block)(Object)this)) { + return false; + } + + ChestType type = state.getValue(ChestBlock.TYPE); + ChestType neighborType = neighborState.getValue(ChestBlock.TYPE); + + if (type == ChestType.SINGLE || neighborType == ChestType.SINGLE) { + return false; + } + if (type != neighborType.getOpposite()) { + return false; + } + + Direction facing = state.getValue(ChestBlock.FACING); + Direction neighborFacing = state.getValue(ChestBlock.FACING); + + return facing == neighborFacing; + } +} diff --git a/src/main/java/carpet/mixins/HoneyBlock_customStickyMixin.java b/src/main/java/carpet/mixins/HoneyBlock_customStickyMixin.java new file mode 100644 index 00000000..d103e399 --- /dev/null +++ b/src/main/java/carpet/mixins/HoneyBlock_customStickyMixin.java @@ -0,0 +1,26 @@ +package carpet.mixins; + +import org.spongepowered.asm.mixin.Mixin; + +import carpet.fakes.BlockBehaviourInterface; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.HoneyBlock; +import net.minecraft.world.level.block.state.BlockState; + +@Mixin(HoneyBlock.class) +public class HoneyBlock_customStickyMixin implements BlockBehaviourInterface { + + @Override + public boolean isSticky(BlockState state) { + return true; + } + + @Override + public boolean isStickyToNeighbor(Level level, BlockPos pos, BlockState state, BlockPos neighborPos, BlockState neighborState, Direction dir, Direction moveDir) { + return !neighborState.is(Blocks.SLIME_BLOCK); + } +} diff --git a/src/main/java/carpet/mixins/PistonHandler_customStickyMixin.java b/src/main/java/carpet/mixins/PistonHandler_customStickyMixin.java deleted file mode 100644 index 3dbf3f5f..00000000 --- a/src/main/java/carpet/mixins/PistonHandler_customStickyMixin.java +++ /dev/null @@ -1,313 +0,0 @@ -package carpet.mixins; - -import carpet.CarpetSettings; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; - -import java.util.List; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.ChainBlock; -import net.minecraft.world.level.block.ChestBlock; -import net.minecraft.world.level.block.EndRodBlock; -import net.minecraft.world.level.block.piston.PistonStructureResolver; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.ChestType; - -@Mixin(PistonStructureResolver.class) -public abstract class PistonHandler_customStickyMixin -{ - /* - * The following Mixins make double chests behave sticky on the side where they are connected to its other double chest half block. - * This is achieved by Injecting calls to "stickToStickySide" where normally slimeblocks stick to all their neighboring blocks. - * redirectGetBlockState_1_A/B is neccessary to get access to the blockState_1 variable, which is used in redirectSlimeBlock. - * redirectSlimeBlock is neccessary to also enable chests to have the backward stickyness (this seems to be an edge case) - * - * Note that it is possible to separate chests the same way pistons can separate slimeblocks. - * - * These also support other custom sticky block with non-standard rules, like chains. - */ - @Shadow @Final private Level level; - @Shadow @Final private Direction pushDirection; - @Shadow protected abstract boolean addBlockLine(BlockPos blockPos_1, Direction direction_1); - @Shadow private static boolean isSticky(BlockState block_1) { return false; } - @Shadow private static boolean canStickToEachOther(BlockState block, BlockState block2) {return false;} - @Shadow protected abstract boolean addBranchingBlocks(BlockPos pos); - - // collects information about sticking block when backtracking. - private BlockPos currentPos; - private BlockState currentState; - @Redirect(method = "addBlockLine", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;getBlockState(Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/level/block/state/BlockState;", ordinal = 0)) - private BlockState redirectGetBlockState_1_A(Level world, BlockPos pos) { - return currentState = world.getBlockState(pos); - } - @Redirect(method = "addBlockLine", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;getBlockState(Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/level/block/state/BlockState;", ordinal = 1)) - private BlockState redirectGetBlockState_1_B(Level world, BlockPos pos) { - currentPos = pos; - return currentState = world.getBlockState(pos); - } - - /** - * Makes backwards stickiness work with sticky non-slimeblocks as well (chests, chains). - * @author 2No2Name, gnembon - */ - @Redirect(method = "addBlockLine", at = @At( - value = "INVOKE", - target = "Lnet/minecraft/world/level/block/piston/PistonStructureResolver;isSticky(Lnet/minecraft/world/level/block/state/BlockState;)Z", - ordinal = 0 ) - ) - private boolean redirectIsStickyBlock(BlockState blockState) - { - // applies to both MBE chests as well as sticky chains - return blockCanBePulled(blockState) || isSticky(blockState); - } - - /** - * Returns true if there is a modification making this blockState sticky on the given face. Vanilla stickyness of SLIME_BLOCK is not affected. - * @param blockState BlockState to determine the stickyness of - * @return boolean whether block is not SLIME_BLOCK and is sticky in the given direction - * @author 2No2Name - */ - private boolean blockCanBePulled(BlockState blockState) { - if (CarpetSettings.movableBlockEntities) - { - Block block = blockState.getBlock(); - if (block == Blocks.CHEST || block == Blocks.TRAPPED_CHEST) - //Make chests be sticky on the side to - return getDirectionToOtherChestHalf(blockState) == pushDirection.getOpposite(); - //example how you could make sticky pistons have a sticky side: - //if(block == Blocks.STICKY_PISTON) - // return blockState.get(FacingBlock.FACING) == motionDirection; - } - if (CarpetSettings.doChainStone && blockState.getBlock() == Blocks.CHAIN) - { - return isChainOnAxis(currentState, pushDirection); - } - - - return false; - } - - /** - * Determines if we should continue to drag blocks in a line (going opposite to the direction of a push) - * @param previous: block that is already dragged - * @param next: canidate block to decide if needs to be dragged along as well. - * @return true if we should keep dragging blocks behind - */ - @Redirect(method = "addBlockLine", at = @At( - value = "INVOKE", - target = "Lnet/minecraft/world/level/block/piston/PistonStructureResolver;canStickToEachOther(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/block/state/BlockState;)Z") - ) - private boolean isDraggingPreviousBlockBehind(BlockState previous, BlockState next) - { - if (CarpetSettings.doChainStone) - { - if (previous.getBlock() == Blocks.CHAIN && isChainOnAxis(previous, pushDirection)) - { - if ( (next.getBlock() == Blocks.CHAIN && isChainOnAxis(next, pushDirection)) - || CarpetSettings.chainStoneStickToAll - || isEndRodOnAxis(next, pushDirection.getAxis()) - || Block.canSupportCenter(level, currentPos, pushDirection)) - { - return true; - } - } - } - return canStickToEachOther(previous, next); - } - - - /** - * Handles blocks besides the slimeblock that are sticky. Currently only supports blocks that are sticky on one side. - * This runs in U style structures with something in the middle on retraction. - * @author 2No2Name - */ - @Inject(method = "addBlockLine", locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true, at = @At( - value = "INVOKE", - target = "Ljava/util/List;get(I)Ljava/lang/Object;", - shift = At.Shift.AFTER - )) - private void stickToStickySide(BlockPos blockPos_1, Direction direction_1, CallbackInfoReturnable cir, BlockState blockState_1, int int_1, int int_2, int int_4, BlockPos blockPos_3, int int_5, int int_6) - { - if (CarpetSettings.movableBlockEntities) - { - if (!stickToStickySide(blockPos_3)) - { - cir.setReturnValue(false); - } - } - } - @Shadow @Final private List toPush; - @Inject(method = "resolve", at = @At(value = "INVOKE", target = "Ljava/util/List;get(I)Ljava/lang/Object;", shift = At.Shift.AFTER), locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true) - /** - * Handles blocks besides the slimeblock that are sticky. - * Supports blocks that are sticky on one side, (double chests now, 2no2name) - * as well as other special sticky blocks (chains, gnembon). - * @author 2No2Name, gnembon - */ - private void stickToStickySide(CallbackInfoReturnable cir, int int_1){ - if (CarpetSettings.movableBlockEntities) - { - if (!stickToStickySide(this.toPush.get(int_1))) - { - cir.setReturnValue(false); - } - } - - if (CarpetSettings.doChainStone) - { - BlockPos pos = this.toPush.get(int_1); - BlockState chainState = level.getBlockState(pos); - // chain is sideways - if (chainState.getBlock() == Blocks.CHAIN && !isChainOnAxis(chainState, pushDirection) - && !this.addBranchingBlocks(pos)) - { - cir.setReturnValue(false); - } - } - } - - /** - * Handles blocks besides the slimeblock that are sticky. Currently only supports blocks that are sticky on one side. - * Currently the only additional sticky block is the double chest, which sticks to its other chest half. - * @param blockPos_1 location of a block that moves and needs to stick other blocks to it - * @author 2No2Name - */ - private boolean stickToStickySide(BlockPos blockPos_1) - { - BlockState blockState_1 = this.level.getBlockState(blockPos_1); - Block block = blockState_1.getBlock(); - Direction stickyDirection = null; - if(block == Blocks.CHEST || block == Blocks.TRAPPED_CHEST) { - stickyDirection = getDirectionToOtherChestHalf(blockState_1); - } - - //example how you could make sticky pistons have a sticky side: - //else if(block == Blocks.STICKY_PISTON){ - // stickyDirection = blockState_1.get(FacingBlock.FACING); - //} - - return stickyDirection == null || this.addBlockLine(blockPos_1.relative(stickyDirection), stickyDirection); //offset - } - - - /** - * This never seems to run - * @author gnembon - */ - @Inject(method = "addBlockLine", locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true, at= @At( - value = "INVOKE", - target = "Lnet/minecraft/world/level/block/piston/PistonStructureResolver;isSticky(Lnet/minecraft/world/level/block/state/BlockState;)Z", - ordinal = 1, - shift = At.Shift.BEFORE - ) - ) - private void redirectIsStickyBlock(BlockPos pos, Direction dir, CallbackInfoReturnable cir, - BlockState blockState, int i, int j, int l, BlockPos blockPos2, int m, int n, BlockPos blockPos3) - { - if (CarpetSettings.doChainStone) - { - BlockState chainState = level.getBlockState(blockPos3); - if (chainState.getBlock() == Blocks.CHAIN && !isChainOnAxis(chainState, pushDirection) && !addBranchingBlocks(blockPos3)) - { - cir.setReturnValue(false); - } - } - } - - - /** - * Custom movement of blocks stuck to the sides of blocks other than slimeblocks like chains - */ - @Inject(method = "addBranchingBlocks", locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true, at = @At( - value = "INVOKE", - target = "Lnet/minecraft/world/level/block/piston/PistonStructureResolver;canStickToEachOther(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/block/state/BlockState;)Z", - shift = At.Shift.BEFORE - )) - private void otherSideStickyCases(BlockPos pos, CallbackInfoReturnable cir, - BlockState blockState, Direction var3[], int var4, int var5, Direction direction, BlockPos blockPos, BlockState blockState2) - { - if (CarpetSettings.doChainStone) - { - if (blockState.getBlock() == Blocks.CHAIN && isChainOnAxis(blockState, direction) && !blockState2.isAir()) - { - Block otherBlock = blockState2.getBlock(); - if ((otherBlock == Blocks.CHAIN && (blockState.getValue(ChainBlock.AXIS) == blockState2.getValue(ChainBlock.AXIS))) - || CarpetSettings.chainStoneStickToAll - || isEndRodOnAxis(blockState2, blockState.getValue(ChainBlock.AXIS)) - || otherBlock == Blocks.HONEY_BLOCK - || Block.canSupportCenter(level, blockPos, direction.getOpposite())) - { - if (!addBlockLine(blockPos, direction)) - { - cir.setReturnValue(false); - } - } - } - } - } - - /** - * chains may cause moving adjacent blocks, meaning isAdjacentBlockStuck check is irreliable. - * since initial block may not be sticky. - * in vanilla canMoveAdjacent is always called on block2 being sticky. - * @param block - * @param block2 - * @return - */ - @Redirect(method = "addBranchingBlocks", at = @At( - value = "INVOKE", - target = "Lnet/minecraft/world/level/block/piston/PistonStructureResolver;canStickToEachOther(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/block/state/BlockState;)Z") - ) - private boolean isStuckSlimeStone(BlockState block, BlockState block2) - { - return isSticky(block2) && canStickToEachOther(block, block2); - } - - - //if more helpers like this start existing, move this to Chest class - /** - * @param blockState blockState of one double chest half block - * @return Direction towards the other block of the double chest, null if the blockState is not a double chest - * @author 2No2Name - */ - private Direction getDirectionToOtherChestHalf(BlockState blockState) - { - ChestType chestType; - try{ - chestType = blockState.getValue(ChestBlock.TYPE); - }catch(IllegalArgumentException e){return null;} - if(chestType == ChestType.SINGLE) - return null; - return ChestBlock.getConnectedDirection(blockState); - } - - - private boolean isChainOnAxis(BlockState state, Direction stickDirection) - { - Direction.Axis axis; - try { - axis = state.getValue(ChainBlock.AXIS); - }catch(IllegalArgumentException e){return false;} - return stickDirection.getAxis() == axis; - } - - private boolean isEndRodOnAxis(BlockState state, Direction.Axis stickAxis) - { - if (state.getBlock() != Blocks.END_ROD) return false; - Direction facing; - try { - facing = state.getValue(EndRodBlock.FACING); - }catch(IllegalArgumentException e){return false;} - return stickAxis == facing.getAxis(); - } -} diff --git a/src/main/java/carpet/mixins/PistonStructureResolver_customStickyMixin.java b/src/main/java/carpet/mixins/PistonStructureResolver_customStickyMixin.java new file mode 100644 index 00000000..13abaec9 --- /dev/null +++ b/src/main/java/carpet/mixins/PistonStructureResolver_customStickyMixin.java @@ -0,0 +1,94 @@ +package carpet.mixins; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +import carpet.fakes.BlockBehaviourInterface; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.piston.PistonStructureResolver; +import net.minecraft.world.level.block.state.BlockState; + +@Mixin(PistonStructureResolver.class) +public class PistonStructureResolver_customStickyMixin { + + @Shadow @Final private Level level; + @Shadow @Final private Direction pushDirection; + + @Inject( + method = "isSticky", + cancellable = true, + at = @At( + value = "HEAD" + ) + ) + private static void isSticky(BlockState state, CallbackInfoReturnable cir) { + cir.setReturnValue(((BlockBehaviourInterface)state.getBlock()).isSticky(state)); + } + + // fields that are needed because @Redirects cannot capture locals + private BlockPos pos_addBlockLine; + private BlockPos behindPos_addBlockLine; + + @Inject( + method = "addBlockLine", + locals = LocalCapture.CAPTURE_FAILHARD, + at = @At( + value = "INVOKE", + ordinal = 1, + target = "Lnet/minecraft/world/level/Level;getBlockState(Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/level/block/state/BlockState;" + ) + ) + private void captureBlockLinePositions(BlockPos pos, Direction fromDir, CallbackInfoReturnable cir, BlockState state, int dst, BlockPos behindPos) { + pos_addBlockLine = behindPos.relative(pushDirection); + behindPos_addBlockLine = behindPos; + } + + @Redirect( + method = "addBlockLine", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/level/block/piston/PistonStructureResolver;canStickToEachOther(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/block/state/BlockState;)Z" + ) + ) + private boolean onAddBlockLineCanStickToEachOther(BlockState state, BlockState behindState) { + return ((BlockBehaviourInterface)state.getBlock()).isStickyToNeighbor(level, pos_addBlockLine, state, behindPos_addBlockLine, behindState, pushDirection.getOpposite(), pushDirection); + } + + // fields that are needed because @Redirects cannot capture locals + private Direction dir_addBranchingBlocks; + private BlockPos neighborPos_addBranchingBlocks; + + @Inject( + method = "addBranchingBlocks", + locals = LocalCapture.CAPTURE_FAILHARD, + at = @At( + value = "INVOKE", + ordinal = 1, + target = "Lnet/minecraft/world/level/Level;getBlockState(Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/level/block/state/BlockState;" + ) + ) + private void captureNeighborPositions(BlockPos pos, CallbackInfoReturnable cir, BlockState state, Direction[] dirs, int i, int j, Direction dir, BlockPos neighborPos) { + dir_addBranchingBlocks = dir; + neighborPos_addBranchingBlocks = neighborPos; + } + + @Redirect( + method = "addBranchingBlocks", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/level/block/piston/PistonStructureResolver;canStickToEachOther(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/block/state/BlockState;)Z" + ) + ) + private boolean onAddBranchingBlocksCanStickToEachOther(BlockState neighborState, BlockState state, BlockPos pos) { + return ((BlockBehaviourInterface)state.getBlock()).isStickyToNeighbor(level, pos, state, neighborPos_addBranchingBlocks, neighborState, dir_addBranchingBlocks, pushDirection); + } +} diff --git a/src/main/java/carpet/mixins/SlimeBlock_customStickyMixin.java b/src/main/java/carpet/mixins/SlimeBlock_customStickyMixin.java new file mode 100644 index 00000000..38b35089 --- /dev/null +++ b/src/main/java/carpet/mixins/SlimeBlock_customStickyMixin.java @@ -0,0 +1,26 @@ +package carpet.mixins; + +import org.spongepowered.asm.mixin.Mixin; + +import carpet.fakes.BlockBehaviourInterface; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.SlimeBlock; +import net.minecraft.world.level.block.state.BlockState; + +@Mixin(SlimeBlock.class) +public class SlimeBlock_customStickyMixin implements BlockBehaviourInterface { + + @Override + public boolean isSticky(BlockState state) { + return true; + } + + @Override + public boolean isStickyToNeighbor(Level level, BlockPos pos, BlockState state, BlockPos neighborPos, BlockState neighborState, Direction dir, Direction moveDir) { + return !neighborState.is(Blocks.HONEY_BLOCK); + } +} diff --git a/src/main/resources/carpet.mixins.json b/src/main/resources/carpet.mixins.json index 04a31c1e..502c2e1b 100644 --- a/src/main/resources/carpet.mixins.json +++ b/src/main/resources/carpet.mixins.json @@ -170,7 +170,6 @@ "PistonMovingBlockEntity_movableBEMixin", "Level_movableBEMixin", "LevelChunk_movableBEMixin", - "PistonHandler_customStickyMixin", "Player_creativeNoClipMixin", "PistonMovingBlockEntity_playerHandlingMixin", "BlockItem_creativeNoClipMixin", @@ -180,7 +179,14 @@ "LivingEntity_creativeFlyMixin", "ChunkMap_creativePlayersLoadChunksMixin", "SculkSensorBlock_rangeMixin", - "CollectingNeighborUpdaterAccessor" + "CollectingNeighborUpdaterAccessor", + + "BlockBehaviour_customStickyMixin", + "ChainBlock_customStickyMixin", + "ChestBlock_customStickyMixin", + "HoneyBlock_customStickyMixin", + "PistonStructureResolver_customStickyMixin", + "SlimeBlock_customStickyMixin" ], "client": [ "Timer_tickSpeedMixin",