diff --git a/src/main/java/carpet/CarpetSettings.java b/src/main/java/carpet/CarpetSettings.java index 203d6ec4..ce47c63e 100644 --- a/src/main/java/carpet/CarpetSettings.java +++ b/src/main/java/carpet/CarpetSettings.java @@ -80,7 +80,6 @@ public class CarpetSettings rule("portalSuffocationFix", "fix", "Nether portals correctly place entities going through") .extraInfo("Entities shouldn't suffocate in obsidian").wip(), rule("superSecretSetting", "experimental","Gbhs sgnf sadsgras fhskdpri!"), - rule("invisibilityFix", "fix", "Guardians honor players' invisibility effect").wip(), rule("portalCreativeDelay", "creative", "Portals won't let a creative player go through instantly") .extraInfo("Holding obsidian in either hand won't let you through at all"), rule("ctrlQCraftingFix", "fix survival", "Dropping entire stacks works also from on the crafting UI result slot"), @@ -105,7 +104,7 @@ public class CarpetSettings .defaultTrue().wip(), rule("flippinCactus", "creative survival", "Players can flip and rotate blocks when holding cactus") .extraInfo("Doesn't cause block updates when rotated/flipped", - "Applies to pistons, observers, droppers, repeaters, stairs, glazed terracotta etc...").wip(), + "Applies to pistons, observers, droppers, repeaters, stairs, glazed terracotta etc..."), rule("hopperCounters", "commands creative survival","hoppers pointing to wool will count items passing through them") .extraInfo("Enables /counter command, and actions while placing red and green carpets on wool blocks", "Use /counter reset to reset the counter, and /counter to query", @@ -162,7 +161,7 @@ public class CarpetSettings ((MinecraftServer_motdInterface)CarpetServer.minecraft_server).checkMOTD()), rule("rotatorBlock", "experimental", "Cactus in dispensers rotates blocks.") .extraInfo("Cactus in a dispenser gives the dispenser the ability to rotate the blocks " + - "that are in front of it anti-clockwise if possible.").wip(), + "that are in front of it anti-clockwise if possible."), rule("viewDistance", "creative", "Changes the view distance of the server.") .extraInfo("Set to 0 to not override the value in server settings.") .choices("0", "0 12 16 32 64").setNotStrict() @@ -724,8 +723,12 @@ public class CarpetSettings public CarpetSettingEntry wip() { return validate( (s, n) -> { - if (s != null) - Messenger.m(s, "r Work in progress - limited or no functionality available for "+n); + if (s != null) + try + { + Messenger.m(s, "r Work in progress - limited or no functionality available for "+n); + } + catch (NullPointerException ignored) { } }); } } diff --git a/src/main/java/carpet/helpers/BlockRotator.java b/src/main/java/carpet/helpers/BlockRotator.java index b3cc2b32..68b71b5e 100644 --- a/src/main/java/carpet/helpers/BlockRotator.java +++ b/src/main/java/carpet/helpers/BlockRotator.java @@ -21,6 +21,7 @@ import net.minecraft.block.RepeaterBlock; import net.minecraft.block.SlabBlock; import net.minecraft.block.StairsBlock; import net.minecraft.block.TrapdoorBlock; +import net.minecraft.block.dispenser.FallibleItemDispenserBehavior; import net.minecraft.block.enums.BlockHalf; import net.minecraft.block.enums.ComparatorMode; import net.minecraft.block.enums.SlabType; @@ -31,6 +32,7 @@ import net.minecraft.item.ItemPlacementContext; import net.minecraft.item.ItemStack; import net.minecraft.util.BlockRotation; import net.minecraft.util.Hand; +import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPointer; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; @@ -40,13 +42,16 @@ import net.minecraft.world.World; public class BlockRotator { - public static boolean flipBlockWithCactus(World worldIn, BlockPos pos, BlockState state, PlayerEntity playerIn, Hand hand, Direction facing, float hitX, float hitY, float hitZ) + public static boolean flipBlockWithCactus(BlockState state, World world, PlayerEntity player, Hand hand, BlockHitResult hit) { - if (!playerIn.abilities.allowModifyWorld || !CarpetSettings.getBool("flippinCactus") || !player_holds_cactus_mainhand(playerIn)) + if (!player.abilities.allowModifyWorld || !CarpetSettings.getBool("flippinCactus") || !player_holds_cactus_mainhand(player)) { return false; } - return flip_block(worldIn, pos, state, playerIn, hand, facing, hitX, hitY, hitZ); + CarpetSettings.impendingFillSkipUpdates = true; + boolean retval = flip_block(state, world, player, hand, hit); + CarpetSettings.impendingFillSkipUpdates = false; + return retval; } public static BlockState alternativeBlockPlacement(Block block, ItemPlacementContext context)//World worldIn, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer) @@ -185,66 +190,69 @@ public class BlockRotator - public static boolean flip_block(World worldIn, BlockPos pos, BlockState state, PlayerEntity playerIn, Hand hand, Direction facing, float hitX, float hitY, float hitZ) + public static boolean flip_block(BlockState state, World world, PlayerEntity player, Hand hand, BlockHitResult hit) { Block block = state.getBlock(); + BlockPos pos = hit.getBlockPos(); + Vec3d hitVec = hit.getPos().subtract(pos.getX(), pos.getY(), pos.getZ()); + Direction facing = hit.getSide(); if ( (block instanceof GlazedTerracottaBlock) || (block instanceof AbstractRedstoneGateBlock) || (block instanceof RailBlock) || (block instanceof TrapdoorBlock) || (block instanceof LeverBlock) || (block instanceof FenceGateBlock)) { - worldIn.setBlockState(pos, block.rotate(state, BlockRotation.CLOCKWISE_90), 2 | 1024); + world.setBlockState(pos, state.rotate(BlockRotation.CLOCKWISE_90), 2 | 1024); } else if ((block instanceof ObserverBlock) || (block instanceof EndRodBlock)) { - worldIn.setBlockState(pos, state.with(FacingBlock.FACING, (Direction) state.get(FacingBlock.FACING).getOpposite()), 2 | 1024); + world.setBlockState(pos, state.with(FacingBlock.FACING, (Direction) state.get(FacingBlock.FACING).getOpposite()), 2 | 1024); } else if (block instanceof DispenserBlock) { - worldIn.setBlockState(pos, state.with(DispenserBlock.FACING, state.get(DispenserBlock.FACING).getOpposite()), 2 | 1024); + world.setBlockState(pos, state.with(DispenserBlock.FACING, state.get(DispenserBlock.FACING).getOpposite()), 2 | 1024); } else if (block instanceof PistonBlock) { if (!(state.get(PistonBlock.EXTENDED))) - worldIn.setBlockState(pos, state.with(FacingBlock.FACING, state.get(FacingBlock.FACING).getOpposite()), 2 | 1024); + world.setBlockState(pos, state.with(FacingBlock.FACING, state.get(FacingBlock.FACING).getOpposite()), 2 | 1024); } else if (block instanceof SlabBlock) { if (((SlabBlock) block).hasSidedTransparency(state)) { - worldIn.setBlockState(pos, state.with(SlabBlock.TYPE, state.get(SlabBlock.TYPE) == SlabType.TOP ? SlabType.BOTTOM : SlabType.TOP), 2 | 1024); + world.setBlockState(pos, state.with(SlabBlock.TYPE, state.get(SlabBlock.TYPE) == SlabType.TOP ? SlabType.BOTTOM : SlabType.TOP), 2 | 1024); } } else if (block instanceof HopperBlock) { if ((Direction)state.get(HopperBlock.FACING) != Direction.DOWN) { - worldIn.setBlockState(pos, state.with(HopperBlock.FACING, state.get(HopperBlock.FACING).rotateYClockwise()), 2 | 1024); + world.setBlockState(pos, state.with(HopperBlock.FACING, state.get(HopperBlock.FACING).rotateYClockwise()), 2 | 1024); } } else if (block instanceof StairsBlock) { //LOG.error(String.format("hit with facing: %s, at side %.1fX, X %.1fY, Y %.1fZ",facing, hitX, hitY, hitZ)); - if ((facing == Direction.UP && hitY == 1.0f) || (facing == Direction.DOWN && hitY == 0.0f)) + if ((facing == Direction.UP && hitVec.y == 1.0f) || (facing == Direction.DOWN && hitVec.y == 0.0f)) { - worldIn.setBlockState(pos, state.with(StairsBlock.HALF, state.get(StairsBlock.HALF) == BlockHalf.TOP ? BlockHalf.BOTTOM : BlockHalf.TOP ), 2 | 1024); + world.setBlockState(pos, state.with(StairsBlock.HALF, state.get(StairsBlock.HALF) == BlockHalf.TOP ? BlockHalf.BOTTOM : BlockHalf.TOP ), 2 | 1024); } else { boolean turn_right; if (facing == Direction.NORTH) { - turn_right = (hitX <= 0.5); + turn_right = (hitVec.x <= 0.5); } else if (facing == Direction.SOUTH) { - turn_right = !(hitX <= 0.5); + turn_right = !(hitVec.x <= 0.5); } else if (facing == Direction.EAST) { - turn_right = (hitZ <= 0.5); + turn_right = (hitVec.z <= 0.5); } else if (facing == Direction.WEST) { - turn_right = !(hitZ <= 0.5); + turn_right = !(hitVec.z <= 0.5); } else { @@ -252,11 +260,11 @@ public class BlockRotator } if (turn_right) { - worldIn.setBlockState(pos, block.rotate(state, BlockRotation.COUNTERCLOCKWISE_90), 2 | 1024); + world.setBlockState(pos, state.rotate(BlockRotation.COUNTERCLOCKWISE_90), 2 | 1024); } else { - worldIn.setBlockState(pos, block.rotate(state, BlockRotation.CLOCKWISE_90), 2 | 1024); + world.setBlockState(pos, state.rotate(BlockRotation.CLOCKWISE_90), 2 | 1024); } } } @@ -264,7 +272,7 @@ public class BlockRotator { return false; } - worldIn.scheduleBlockRender(pos); + world.scheduleBlockRender(pos); return true; } private static boolean player_holds_cactus_mainhand(PlayerEntity playerIn) @@ -279,10 +287,26 @@ public class BlockRotator && (entity instanceof PlayerEntity)) { PlayerEntity player = (PlayerEntity)entity; - return (!player.getMainHandStack().isEmpty() - && player.getMainHandStack().getItem() instanceof BlockItem && - ((BlockItem) (player.getMainHandStack().getItem())).getBlock() == Blocks.CACTUS); + return (!player.getOffHandStack().isEmpty() + && player.getOffHandStack().getItem() instanceof BlockItem && + ((BlockItem) (player.getOffHandStack().getItem())).getBlock() == Blocks.CACTUS); } return false; } + + public static class CactusDispenserBehaviour extends FallibleItemDispenserBehavior + { + @Override + protected ItemStack dispenseSilently(BlockPointer source, ItemStack stack) + { + if (CarpetSettings.getBool("rotatorBlock")) + { + return BlockRotator.dispenserRotate(source, stack); + } + else + { + return super.dispenseSilently(source, stack); + } + } + } } diff --git a/src/main/java/carpet/mixins/DirectionMixin.java b/src/main/java/carpet/mixins/DirectionMixin.java index 76bd9a3e..adfeeda3 100644 --- a/src/main/java/carpet/mixins/DirectionMixin.java +++ b/src/main/java/carpet/mixins/DirectionMixin.java @@ -2,6 +2,7 @@ package carpet.mixins; import carpet.CarpetSettings; import carpet.fakes.EntityInterface; +import carpet.helpers.BlockRotator; import net.minecraft.entity.Entity; import net.minecraft.util.math.Direction; import org.spongepowered.asm.mixin.Mixin; @@ -12,15 +13,31 @@ import org.spongepowered.asm.mixin.injection.Redirect; public abstract class DirectionMixin { @Redirect(method = "getEntityFacingOrder", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;getYaw(F)F")) - private static float ifGetYaw(Entity entity, float float_1) + private static float getYaw(Entity entity, float float_1) { + float yaw; if (!CarpetSettings.getBool("placementRotationFix")) { - return entity.getYaw(1.0F); + yaw = entity.getYaw(float_1); } else { - return ((EntityInterface) entity).getMainYaw(1.0F); + yaw = ((EntityInterface) entity).getMainYaw(float_1); } + if (BlockRotator.flippinEligibility(entity)) + { + yaw += 180f; + } + return yaw; + } + @Redirect(method = "getEntityFacingOrder", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;getPitch(F)F")) + private static float getPitch(Entity entity, float float_1) + { + float pitch = entity.getPitch(float_1); + if (BlockRotator.flippinEligibility(entity)) + { + pitch = -pitch; + } + return pitch; } } diff --git a/src/main/java/carpet/mixins/DispenserBehaviour_cactusMixin.java b/src/main/java/carpet/mixins/DispenserBehaviour_cactusMixin.java new file mode 100644 index 00000000..d2695686 --- /dev/null +++ b/src/main/java/carpet/mixins/DispenserBehaviour_cactusMixin.java @@ -0,0 +1,21 @@ +package carpet.mixins; + +import carpet.helpers.BlockRotator; +import net.minecraft.block.Blocks; +import net.minecraft.block.DispenserBlock; +import net.minecraft.block.dispenser.DispenserBehavior; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(DispenserBehavior.class) +public interface DispenserBehaviour_cactusMixin +{ + @SuppressWarnings("PublicStaticMixinMember") + @Inject(method = "registerDefaults", at = @At("HEAD")) + static void addBlockRotator(CallbackInfo ci) + { + DispenserBlock.registerBehavior(Blocks.CACTUS.asItem(), new BlockRotator.CactusDispenserBehaviour()); + } +} diff --git a/src/main/java/carpet/mixins/HopperBlock_cactusMixin.java b/src/main/java/carpet/mixins/HopperBlock_cactusMixin.java new file mode 100644 index 00000000..5eed6fd6 --- /dev/null +++ b/src/main/java/carpet/mixins/HopperBlock_cactusMixin.java @@ -0,0 +1,26 @@ +package carpet.mixins; + +import carpet.helpers.BlockRotator; +import net.minecraft.block.HopperBlock; +import net.minecraft.item.ItemPlacementContext; +import net.minecraft.util.math.Direction; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(HopperBlock.class) +public class HopperBlock_cactusMixin +{ + @Redirect(method = "getPlacementState", at = @At( + value = "INVOKE", + target = "Lnet/minecraft/item/ItemPlacementContext;getSide()Lnet/minecraft/util/math/Direction;" + )) + private Direction getOppositeOpposite(ItemPlacementContext context) + { + if (BlockRotator.flippinEligibility(context.getPlayer())) + { + return context.getSide().getOpposite(); + } + return context.getSide(); + } +} diff --git a/src/main/java/carpet/mixins/ItemUsageContext_cactusMixin.java b/src/main/java/carpet/mixins/ItemUsageContext_cactusMixin.java new file mode 100644 index 00000000..5f9d86b1 --- /dev/null +++ b/src/main/java/carpet/mixins/ItemUsageContext_cactusMixin.java @@ -0,0 +1,27 @@ +package carpet.mixins; + +import carpet.helpers.BlockRotator; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemUsageContext; +import net.minecraft.util.math.Direction; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(ItemUsageContext.class) +public class ItemUsageContext_cactusMixin +{ + @Redirect(method = "getPlayerFacing", at = @At( + value = "INVOKE", + target = "Lnet/minecraft/entity/player/PlayerEntity;getHorizontalFacing()Lnet/minecraft/util/math/Direction;" + )) + private Direction getPlayerFacing(PlayerEntity playerEntity) + { + Direction dir = playerEntity.getHorizontalFacing(); + if (BlockRotator.flippinEligibility(playerEntity)) + { + dir = dir.getOpposite(); + } + return dir; + } +} diff --git a/src/main/java/carpet/mixins/ServerPlayerInteractionManager_cactusMixin.java b/src/main/java/carpet/mixins/ServerPlayerInteractionManager_cactusMixin.java new file mode 100644 index 00000000..3a405cf2 --- /dev/null +++ b/src/main/java/carpet/mixins/ServerPlayerInteractionManager_cactusMixin.java @@ -0,0 +1,30 @@ +package carpet.mixins; + +import carpet.helpers.BlockRotator; +import net.minecraft.block.BlockState; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.server.network.ServerPlayerInteractionManager; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.world.World; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(ServerPlayerInteractionManager.class) +public class ServerPlayerInteractionManager_cactusMixin +{ + + @Redirect(method = "interactBlock", at = @At( + value = "INVOKE", + target = "Lnet/minecraft/block/BlockState;activate(Lnet/minecraft/world/World;Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/util/Hand;Lnet/minecraft/util/hit/BlockHitResult;)Z" + )) + private boolean activateWithOptionalCactus(BlockState blockState, World world_1, PlayerEntity playerEntity_1, Hand hand_1, BlockHitResult blockHitResult_1) + { + Boolean flipped = BlockRotator.flipBlockWithCactus(blockState, world_1, playerEntity_1, hand_1, blockHitResult_1); + if (flipped) + return true; + + return blockState.activate(world_1, playerEntity_1, hand_1, blockHitResult_1); + } +} diff --git a/src/main/resources/carpet.mixins.json b/src/main/resources/carpet.mixins.json index c4fd48f5..5fc17beb 100644 --- a/src/main/resources/carpet.mixins.json +++ b/src/main/resources/carpet.mixins.json @@ -53,12 +53,17 @@ "PlayerEntity_parrotMixin", "SaplingBlockMixin", "EntityMixin", - "DirectionMixin", "GuardianEntityMixin", "ServerChunkManagerMixin", "SpawnHelperMixin", + "DirectionMixin", + "ServerPlayerInteractionManager_cactusMixin", + "HopperBlock_cactusMixin", + "ItemUsageContext_cactusMixin", + "DispenserBehaviour_cactusMixin", + "HopperBlockEntityMixin", "ContainerMixin", "ClientConnectionMixin",