diff --git a/Client/src/main/java/com/baseband/client/Setup.java b/Client/src/main/java/com/baseband/client/Setup.java index a1abd42..8c6d87e 100644 --- a/Client/src/main/java/com/baseband/client/Setup.java +++ b/Client/src/main/java/com/baseband/client/Setup.java @@ -52,6 +52,7 @@ public class Setup { new NoSlowDown(), new Ping(), new Say(), + new Scaffold(), new SeedOverlay(), new Set(), new Selection(), diff --git a/Client/src/main/java/com/baseband/client/event/CancellableEvent.java b/Client/src/main/java/com/baseband/client/event/CancellableEvent.java new file mode 100644 index 0000000..5a81ab5 --- /dev/null +++ b/Client/src/main/java/com/baseband/client/event/CancellableEvent.java @@ -0,0 +1,13 @@ +package com.baseband.client.event; + +public class CancellableEvent extends Event { + boolean cancelled = false; + + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } + + public boolean isCancelled() { + return cancelled; + } +} diff --git a/Client/src/main/java/com/baseband/client/event/Event.java b/Client/src/main/java/com/baseband/client/event/Event.java index 05aa76e..d2e5a2f 100644 --- a/Client/src/main/java/com/baseband/client/event/Event.java +++ b/Client/src/main/java/com/baseband/client/event/Event.java @@ -1,13 +1,5 @@ package com.baseband.client.event; public class Event { - boolean cancelled = false; - public void setCancelled(boolean cancelled) { - this.cancelled = cancelled; - } - - public boolean isCancelled() { - return cancelled; - } } diff --git a/Client/src/main/java/com/baseband/client/event/events/BaritoneEvent.java b/Client/src/main/java/com/baseband/client/event/events/BaritoneEvent.java index aa5ab56..8df1931 100644 --- a/Client/src/main/java/com/baseband/client/event/events/BaritoneEvent.java +++ b/Client/src/main/java/com/baseband/client/event/events/BaritoneEvent.java @@ -1,8 +1,8 @@ package com.baseband.client.event.events; -import com.baseband.client.event.Event; +import com.baseband.client.event.CancellableEvent; -public class BaritoneEvent extends Event { +public class BaritoneEvent extends CancellableEvent { String reason; public void setReason(String reason) { diff --git a/Client/src/main/java/com/baseband/client/event/events/MotionUpdateEvent.java b/Client/src/main/java/com/baseband/client/event/events/MotionUpdateEvent.java new file mode 100644 index 0000000..f65f94c --- /dev/null +++ b/Client/src/main/java/com/baseband/client/event/events/MotionUpdateEvent.java @@ -0,0 +1,8 @@ +package com.baseband.client.event.events; + +import com.baseband.client.event.Event; + +public class MotionUpdateEvent extends Event { + public static class Pre extends MotionUpdateEvent {} + public static class Post extends MotionUpdateEvent {} +} diff --git a/Client/src/main/java/com/baseband/client/event/events/MoveEvent.java b/Client/src/main/java/com/baseband/client/event/events/MoveEvent.java index 63ad079..327ab48 100644 --- a/Client/src/main/java/com/baseband/client/event/events/MoveEvent.java +++ b/Client/src/main/java/com/baseband/client/event/events/MoveEvent.java @@ -1,9 +1,9 @@ package com.baseband.client.event.events; -import com.baseband.client.event.Event; +import com.baseband.client.event.CancellableEvent; import net.minecraft.entity.MoverType; -public class MoveEvent extends Event { +public class MoveEvent extends CancellableEvent { public final MoverType type; public double x; public double y; diff --git a/Client/src/main/java/com/baseband/client/event/events/PacketEvent.java b/Client/src/main/java/com/baseband/client/event/events/PacketEvent.java index 798af0f..0af01ae 100644 --- a/Client/src/main/java/com/baseband/client/event/events/PacketEvent.java +++ b/Client/src/main/java/com/baseband/client/event/events/PacketEvent.java @@ -1,9 +1,9 @@ package com.baseband.client.event.events; -import com.baseband.client.event.Event; +import com.baseband.client.event.CancellableEvent; import net.minecraft.network.Packet; -public abstract class PacketEvent extends Event { +public abstract class PacketEvent extends CancellableEvent { private final Packet packet; diff --git a/Client/src/main/java/com/baseband/client/mixins/MixinEntityPlayerSP.java b/Client/src/main/java/com/baseband/client/mixins/MixinEntityPlayerSP.java index dfbba05..0bc80de 100644 --- a/Client/src/main/java/com/baseband/client/mixins/MixinEntityPlayerSP.java +++ b/Client/src/main/java/com/baseband/client/mixins/MixinEntityPlayerSP.java @@ -1,5 +1,6 @@ package com.baseband.client.mixins; +import com.baseband.client.event.events.MotionUpdateEvent; import com.baseband.client.event.events.MoveEvent; import com.baseband.client.BaseBand; import com.mojang.authlib.GameProfile; @@ -52,6 +53,17 @@ public class MixinEntityPlayerSP extends AbstractClientPlayer { } */ + @Inject(method = {"onUpdateWalkingPlayer"}, at = {@At(value = "HEAD")}) + private void preMotion(CallbackInfo info) { + BaseBand.eventManager.publish(new MotionUpdateEvent.Pre()); + } + + + @Inject(method = {"onUpdateWalkingPlayer"}, at = {@At(value = "RETURN")}) + private void postMotion(CallbackInfo info) { + BaseBand.eventManager.publish(new MotionUpdateEvent.Post()); + } + diff --git a/Client/src/main/java/com/baseband/client/module/world/Scaffold.java b/Client/src/main/java/com/baseband/client/module/world/Scaffold.java new file mode 100644 index 0000000..d52514c --- /dev/null +++ b/Client/src/main/java/com/baseband/client/module/world/Scaffold.java @@ -0,0 +1,144 @@ +package com.baseband.client.module.world; + +import com.baseband.client.event.events.MotionUpdateEvent; +import com.baseband.client.module.Feature; +import com.baseband.client.module.category.World; +import com.baseband.client.util.interact.BlockUtils; +import com.baseband.client.util.misc.Timer; +import net.minecraft.block.Block; +import net.minecraft.block.BlockLiquid; +import net.minecraft.block.material.Material; +import net.minecraft.init.Blocks; +import net.minecraft.item.ItemAir; +import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.network.play.client.CPacketHeldItemChange; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; + +@World +public class Scaffold extends Feature { + @Override + public String toString() { + return "Scaffold"; + } + + Timer timer = new Timer(); + + + public void preMotion(MotionUpdateEvent.Pre event) { + timer.reset(); + + BlockPos playerBlock = new BlockPos( + mc.player.getRidingEntity() != null ? mc.player.getRidingEntity().posX + : mc.player.posX, + mc.player.getRidingEntity() != null ? mc.player.getRidingEntity().posY + : mc.player.posY, + mc.player.getRidingEntity() != null ? mc.player.getRidingEntity().posZ + : mc.player.posZ); + + if (mc.world.isAirBlock(playerBlock.add(0, -1, 0)) + || mc.world.getBlockState(playerBlock.add(0, -1, 0)).getBlock() == Blocks.SNOW_LAYER + || mc.world.getBlockState(playerBlock.add(0, -1, 0)).getBlock() == Blocks.TALLGRASS + || mc.world.getBlockState(playerBlock.add(0, -1, 0)).getBlock() instanceof BlockLiquid) { + if (isValidBlock(playerBlock.add(0, -2, 0))) { + place(playerBlock.add(0, -1, 0), EnumFacing.UP); + } else if (isValidBlock(playerBlock.add(-1, -1, 0))) { + place(playerBlock.add(0, -1, 0), EnumFacing.EAST); + } else if (isValidBlock(playerBlock.add(1, -1, 0))) { + place(playerBlock.add(0, -1, 0), EnumFacing.WEST); + } else if (isValidBlock(playerBlock.add(0, -1, -1))) { + place(playerBlock.add(0, -1, 0), EnumFacing.SOUTH); + } else if (isValidBlock(playerBlock.add(0, -1, 1))) { + place(playerBlock.add(0, -1, 0), EnumFacing.NORTH); + } else if (isValidBlock(playerBlock.add(1, -1, 1))) { + if (isValidBlock(playerBlock.add(0, -1, 1))) { + place(playerBlock.add(0, -1, 1), EnumFacing.NORTH); + } + place(playerBlock.add(1, -1, 1), EnumFacing.EAST); + } else if (isValidBlock(playerBlock.add(-1, -1, 1))) { + if (isValidBlock(playerBlock.add(-1, -1, 0))) { + place(playerBlock.add(0, -1, 1), EnumFacing.WEST); + } + place(playerBlock.add(-1, -1, 1), EnumFacing.SOUTH); + } else if (isValidBlock(playerBlock.add(1, -1, 1))) { + if (isValidBlock(playerBlock.add(0, -1, 1))) { + place(playerBlock.add(0, -1, 1), EnumFacing.SOUTH); + } + place(playerBlock.add(1, -1, 1), EnumFacing.WEST); + } else if (isValidBlock(playerBlock.add(1, -1, 1))) { + if (isValidBlock(playerBlock.add(0, -1, 1))) { + place(playerBlock.add(0, -1, 1), EnumFacing.EAST); + } + place(playerBlock.add(1, -1, 1), EnumFacing.NORTH); + } + } + } + + + @SuppressWarnings("deprecation") + private boolean isValidBlock(BlockPos pos) { + Block b = mc.world.getBlockState(pos).getBlock(); + return !(b instanceof BlockLiquid) && b.getMaterial(null) != Material.AIR; + } + + public void place(BlockPos pos, EnumFacing face) { + if (face == EnumFacing.UP) { + pos = pos.add(0, -1, 0); + } else if (face == EnumFacing.NORTH) { + pos = pos.add(0, 0, 1); + } else if (face == EnumFacing.SOUTH) { + pos = pos.add(0, 0, -1); + } else if (face == EnumFacing.EAST) { + pos = pos.add(-1, 0, 0); + } else if (face == EnumFacing.WEST) { + pos = pos.add(1, 0, 0); + } + final int oldSlot = mc.player.inventory.currentItem; + int newSlot = -1; + for (int i = 0; i < 9; ++i) { + final ItemStack stack = mc.player.inventory.getStackInSlot(i); + if (!isNull(stack) && stack.getItem() instanceof ItemBlock + && Block.getBlockFromItem(stack.getItem()).getDefaultState().isFullBlock()) { + newSlot = i; + break; + } + } + if (newSlot == -1) { + return; + } + + if (!(mc.player.getHeldItemMainhand().getItem() instanceof ItemBlock)) { + mc.player.connection.sendPacket(new CPacketHeldItemChange(newSlot)); + mc.player.inventory.currentItem = newSlot; + mc.playerController.updateController(); + } + if (mc.gameSettings.keyBindJump.isKeyDown()) { + mc.player.motionX *= 0.3; + mc.player.motionZ *= 0.3; + mc.player.jump(); + if (timer.passed(1500) && mc.gameSettings.keyBindJump.isKeyDown()) { + mc.player.motionY = -0.28; + timer.reset(); + } + if (!mc.gameSettings.keyBindJump.isKeyDown()) { + timer.reset(); + } + } + + //TODO: waiter waiter, more rotations please + BlockUtils.faceBlockPosPacketInstant(pos); + + mc.playerController.processRightClickBlock(mc.player, mc.world, pos, face, new Vec3d(0.5, 0.5, 0.5), EnumHand.MAIN_HAND); + mc.player.swingArm(EnumHand.MAIN_HAND); + mc.player.connection.sendPacket(new CPacketHeldItemChange(oldSlot)); + mc.player.inventory.currentItem = oldSlot; + mc.playerController.updateController(); + } + + public static boolean isNull(ItemStack stack) { + return stack == null || stack.getItem() instanceof ItemAir; + } +} diff --git a/Client/src/main/java/com/baseband/client/util/interact/BlockUtils.java b/Client/src/main/java/com/baseband/client/util/interact/BlockUtils.java new file mode 100644 index 0000000..4454c06 --- /dev/null +++ b/Client/src/main/java/com/baseband/client/util/interact/BlockUtils.java @@ -0,0 +1,138 @@ +package com.baseband.client.util.interact; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockDeadBush; +import net.minecraft.block.BlockTallGrass; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.init.Blocks; +import net.minecraft.network.play.client.CPacketEntityAction; +import net.minecraft.network.play.client.CPacketPlayer; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; + +import java.util.ArrayList; +import java.util.Arrays; + + +public class BlockUtils { + + private static final Minecraft mc = Minecraft.getMinecraft(); + + // Sneak! + public static ArrayList blackList = new ArrayList(Arrays.asList( + Blocks.ENDER_CHEST, + Blocks.CHEST, + Blocks.TRAPPED_CHEST, + Blocks.CRAFTING_TABLE, + Blocks.ANVIL, + Blocks.BREWING_STAND, + Blocks.HOPPER, + Blocks.DROPPER, + Blocks.DISPENSER, + Blocks.TRAPDOOR, + Blocks.ENCHANTING_TABLE + )); + public static ArrayList shulkerList = new ArrayList(Arrays.asList( + Blocks.WHITE_SHULKER_BOX, + Blocks.ORANGE_SHULKER_BOX, + Blocks.MAGENTA_SHULKER_BOX, + Blocks.LIGHT_BLUE_SHULKER_BOX, + Blocks.YELLOW_SHULKER_BOX, + Blocks.LIME_SHULKER_BOX, + Blocks.PINK_SHULKER_BOX, + Blocks.GRAY_SHULKER_BOX, + Blocks.SILVER_SHULKER_BOX, + Blocks.CYAN_SHULKER_BOX, + Blocks.PURPLE_SHULKER_BOX, + Blocks.BLUE_SHULKER_BOX, + Blocks.BROWN_SHULKER_BOX, + Blocks.GREEN_SHULKER_BOX, + Blocks.RED_SHULKER_BOX, + Blocks.BLACK_SHULKER_BOX + )); + + // Magic i don't want to explain, gets a placeable size of a neighbor block and places + // the block on it, uses getPlaceableSide + public static void placeBlock(BlockPos pos, boolean rotate) { + EnumFacing side = getPlaceableSide(pos); + if (side == null) { + //ChatUtils.print("Couldn't place a block"); + return; + } + BlockPos neighbour = pos.offset(side); + EnumFacing opposite = side.getOpposite(); + Vec3d hitVec = new Vec3d(neighbour).add(0.5, 0.5, 0.5).add(new Vec3d(opposite.getDirectionVec()).scale(0.5)); + Block neighbourBlock = mc.world.getBlockState(neighbour).getBlock(); + if ((BlockUtils.blackList.contains(neighbourBlock) || BlockUtils.shulkerList.contains(neighbourBlock))) { + mc.player.connection.sendPacket(new CPacketEntityAction(mc.player, CPacketEntityAction.Action.START_SNEAKING)); + } + if (rotate) BlockUtils.faceVectorPacketInstant(hitVec); + mc.playerController.processRightClickBlock(mc.player, mc.world, neighbour, opposite, hitVec, EnumHand.MAIN_HAND); + mc.player.swingArm(EnumHand.MAIN_HAND); + if ((BlockUtils.blackList.contains(neighbourBlock) || BlockUtils.shulkerList.contains(neighbourBlock))) { + mc.player.connection.sendPacket(new CPacketEntityAction(mc.player, CPacketEntityAction.Action.STOP_SNEAKING)); + } + } + + public static void lookAt(Vec3d pos) { + faceVectorPacketInstant(pos); + } + + // Gets a block next to a block position + public static EnumFacing getPlaceableSide(BlockPos pos) { + for (EnumFacing side : EnumFacing.values()) { + BlockPos neighbour = pos.offset(side); + if (!mc.world.getBlockState(neighbour).getBlock().canCollideCheck(mc.world.getBlockState(neighbour), false)) { + continue; + } + IBlockState blockState = mc.world.getBlockState(neighbour); + if (!blockState.getMaterial().isReplaceable() && !(blockState.getBlock() instanceof BlockTallGrass) && !(blockState.getBlock() instanceof BlockDeadBush)) { + return side; + } + } + return null; // :( + } + + public static Vec3d eyesPos() { + return new Vec3d(mc.player.posX, mc.player.posY + mc.player.getEyeHeight(), mc.player.posZ); + } + + // Skidded magic. + public static float[] getLegitRotations(Vec3d vec) { + Vec3d eyesPos = eyesPos(); + double diffX = vec.x - eyesPos.x; + double diffY = vec.y - eyesPos.y; + double diffZ = vec.z - eyesPos.z; + double diffXZ = Math.sqrt(diffX * diffX + diffZ * diffZ); + double yaw = Math.toDegrees(Math.atan2(diffZ, diffX)) - 90f; + double pitch = (-Math.toDegrees(Math.atan2(diffY, diffXZ))); + return new float[]{(float) (MathHelper.wrapDegrees(yaw)), (float) (MathHelper.wrapDegrees(pitch))}; + } + + + public static void faceBlockPosPacketInstant(BlockPos pos) { + EnumFacing side = BlockUtils.getPlaceableSide(pos); + if (side == null) { + return; + } + BlockPos neighbour = pos.offset(side); + EnumFacing opposite = side.getOpposite(); + Vec3d hitVec = new Vec3d(neighbour).add(0.5, 0.5, 0.5).add(new Vec3d(opposite.getDirectionVec()).scale(0.5)); + BlockUtils.faceVectorPacketInstant(hitVec); + } + + // Makes it more legit-looking + public static void faceVectorPacketInstant(Vec3d vec) { + float[] rotations = getLegitRotations(vec); + mc.player.connection.sendPacket( + new CPacketPlayer.Rotation( + //mc.player.posX, mc.player.posY, mc.player.posZ, + rotations[0], rotations[1], mc.player.onGround + ) + ); + } +} diff --git a/Client/src/main/java/com/baseband/client/util/misc/Timer.java b/Client/src/main/java/com/baseband/client/util/misc/Timer.java new file mode 100644 index 0000000..2f01677 --- /dev/null +++ b/Client/src/main/java/com/baseband/client/util/misc/Timer.java @@ -0,0 +1,13 @@ +package com.baseband.client.util.misc; + +public class Timer { + private long currentMS = 0L; + + public boolean passed(long time) { + return (System.currentTimeMillis() - currentMS) >= time; + } + + public void reset() { + currentMS = System.currentTimeMillis(); + } +}