From e7e22d2e7d38ae3c598faeafea17ffd38a64648a Mon Sep 17 00:00:00 2001 From: noil Date: Mon, 8 Nov 2021 00:58:02 -0500 Subject: [PATCH] Added ChestFarmer (WIP) --- .../seppuku/api/util/InventoryUtil.java | 16 ++ .../rigamortis/seppuku/api/util/MathUtil.java | 16 +- .../impl/module/combat/AutoTrapModule.java | 1 + .../impl/module/combat/BurrowModule.java | 12 +- .../impl/module/combat/ChestFarmerModule.java | 239 ++++++++++++++++++ .../impl/module/combat/NoCrystalModule.java | 13 +- .../impl/module/world/AutoWitherModule.java | 12 +- .../impl/module/world/NukerModule.java | 1 - 8 files changed, 275 insertions(+), 35 deletions(-) create mode 100644 src/main/java/me/rigamortis/seppuku/impl/module/combat/ChestFarmerModule.java diff --git a/src/main/java/me/rigamortis/seppuku/api/util/InventoryUtil.java b/src/main/java/me/rigamortis/seppuku/api/util/InventoryUtil.java index ea4f753..5846587 100644 --- a/src/main/java/me/rigamortis/seppuku/api/util/InventoryUtil.java +++ b/src/main/java/me/rigamortis/seppuku/api/util/InventoryUtil.java @@ -1,6 +1,7 @@ package me.rigamortis.seppuku.api.util; import net.minecraft.block.Block; +import net.minecraft.block.BlockEnderChest; import net.minecraft.block.BlockObsidian; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityPlayerSP; @@ -74,6 +75,21 @@ public final class InventoryUtil { return -1; } + public static boolean isItemStackEnderChest(final ItemStack itemStack) { + if (itemStack.getItem() instanceof ItemBlock) + return ((ItemBlock) itemStack.getItem()).getBlock() instanceof BlockEnderChest; + + return false; + } + + public static int findEnderChestInHotbar(final EntityPlayerSP player) { + for (int index = 0; InventoryPlayer.isHotbar(index); index++) + if (isItemStackEnderChest(player.inventory.getStackInSlot(index))) + return index; + + return -1; + } + public static boolean isItemStackObsidian(final ItemStack itemStack) { if (itemStack.getItem() instanceof ItemBlock) return ((ItemBlock) itemStack.getItem()).getBlock() instanceof BlockObsidian; diff --git a/src/main/java/me/rigamortis/seppuku/api/util/MathUtil.java b/src/main/java/me/rigamortis/seppuku/api/util/MathUtil.java index d50ce0d..32c873c 100644 --- a/src/main/java/me/rigamortis/seppuku/api/util/MathUtil.java +++ b/src/main/java/me/rigamortis/seppuku/api/util/MathUtil.java @@ -1,7 +1,10 @@ package me.rigamortis.seppuku.api.util; +import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; import net.minecraft.entity.Entity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; @@ -14,6 +17,8 @@ import java.math.RoundingMode; */ public final class MathUtil { + public static final Minecraft mc = Minecraft.getMinecraft(); + public static Vec3d interpolateEntity(Entity entity, float time) { return new Vec3d(entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * time, entity.lastTickPosY + (entity.posY - entity.lastTickPosY) * time, @@ -42,8 +47,17 @@ public final class MathUtil { return new float[]{(float) MathHelper.wrapDegrees(Math.toDegrees(Math.atan2(difZ, difX)) - 90.0f), (float) MathHelper.wrapDegrees(Math.toDegrees(Math.atan2(difY, dist)))}; } + public static EnumFacing calcSide(BlockPos pos) { + for (EnumFacing side : EnumFacing.values()) { + BlockPos sideOffset = pos.offset(side); + IBlockState offsetState = mc.world.getBlockState(sideOffset); + if (!offsetState.getBlock().canCollideCheck(offsetState, false)) continue; + if (!offsetState.getMaterial().isReplaceable()) return side; + } + return null; + } + public static double[] directionSpeed(double speed) { - final Minecraft mc = Minecraft.getMinecraft(); float forward = mc.player.movementInput.moveForward; float side = mc.player.movementInput.moveStrafe; float yaw = mc.player.prevRotationYaw + (mc.player.rotationYaw - mc.player.prevRotationYaw) * mc.getRenderPartialTicks(); diff --git a/src/main/java/me/rigamortis/seppuku/impl/module/combat/AutoTrapModule.java b/src/main/java/me/rigamortis/seppuku/impl/module/combat/AutoTrapModule.java index 6d288e3..aa08fee 100644 --- a/src/main/java/me/rigamortis/seppuku/impl/module/combat/AutoTrapModule.java +++ b/src/main/java/me/rigamortis/seppuku/impl/module/combat/AutoTrapModule.java @@ -135,6 +135,7 @@ public final class AutoTrapModule extends Module { final HandSwapContext handSwapContext = new HandSwapContext( mc.player.inventory.currentItem, InventoryUtil.findObsidianInHotbar(mc.player)); + if (handSwapContext.getNewSlot() == -1) { Seppuku.INSTANCE.getRotationManager().finishTask(this.rotationTask); return; diff --git a/src/main/java/me/rigamortis/seppuku/impl/module/combat/BurrowModule.java b/src/main/java/me/rigamortis/seppuku/impl/module/combat/BurrowModule.java index 8480b6e..d482e24 100644 --- a/src/main/java/me/rigamortis/seppuku/impl/module/combat/BurrowModule.java +++ b/src/main/java/me/rigamortis/seppuku/impl/module/combat/BurrowModule.java @@ -145,16 +145,6 @@ public final class BurrowModule extends Module { } } - private EnumFacing calcSide(BlockPos pos) { - for (EnumFacing side : EnumFacing.values()) { - BlockPos sideOffset = pos.offset(side); - IBlockState offsetState = Minecraft.getMinecraft().world.getBlockState(sideOffset); - if (!offsetState.getBlock().canCollideCheck(offsetState, false)) continue; - if (!offsetState.getMaterial().isReplaceable()) return side; - } - return null; - } - private int adaptiveTpHeight() { final Minecraft mc = Minecraft.getMinecraft(); @@ -220,7 +210,7 @@ public final class BurrowModule extends Module { private boolean place(final BlockPos pos, final Minecraft mc) { final Block block = mc.world.getBlockState(pos).getBlock(); - final EnumFacing direction = this.calcSide(pos); + final EnumFacing direction = MathUtil.calcSide(pos); if (direction == null) return false; diff --git a/src/main/java/me/rigamortis/seppuku/impl/module/combat/ChestFarmerModule.java b/src/main/java/me/rigamortis/seppuku/impl/module/combat/ChestFarmerModule.java new file mode 100644 index 0000000..d400b94 --- /dev/null +++ b/src/main/java/me/rigamortis/seppuku/impl/module/combat/ChestFarmerModule.java @@ -0,0 +1,239 @@ +package me.rigamortis.seppuku.impl.module.combat; + +import me.rigamortis.seppuku.Seppuku; +import me.rigamortis.seppuku.api.event.EventStageable; +import me.rigamortis.seppuku.api.event.player.EventUpdateWalkingPlayer; +import me.rigamortis.seppuku.api.module.Module; +import me.rigamortis.seppuku.api.task.hand.HandSwapContext; +import me.rigamortis.seppuku.api.task.rotation.RotationTask; +import me.rigamortis.seppuku.api.util.EntityUtil; +import me.rigamortis.seppuku.api.util.InventoryUtil; +import me.rigamortis.seppuku.api.util.MathUtil; +import me.rigamortis.seppuku.api.util.Timer; +import me.rigamortis.seppuku.api.value.Value; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.init.Blocks; +import net.minecraft.item.ItemPickaxe; +import net.minecraft.network.play.client.CPacketAnimation; +import net.minecraft.network.play.client.CPacketEntityAction; +import net.minecraft.network.play.client.CPacketPlayerTryUseItemOnBlock; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.tileentity.TileEntityEnderChest; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import team.stiff.pomelo.impl.annotated.handler.annotation.Listener; + +/** + * @author noil + */ +public final class ChestFarmerModule extends Module { + + private final Minecraft mc = Minecraft.getMinecraft(); + + public final Value pickOnlyMode = new Value("PickaxeOnly", new String[]{"pickonly", "onlypick", "onlypicks", "onlypickaxes", "pickaxesonly", "po"}, "Only run this module while a pickaxe is being held", true); + public final Value visible = new Value("Visible", new String[]{"Visible", "v"}, "Casts a ray to the placement position, forces the placement when disabled", true); + public final Value rotate = new Value("Rotate", new String[]{"rotation", "r", "rotate"}, "Rotate to place the chest", true); + public final Value swing = new Value("Swing", new String[]{"Arm"}, "Swing the player's arm while placing the chest", true); + public final Value sneak = new Value("PlaceOnSneak", new String[]{"sneak", "s", "pos", "sneakPlace"}, "When true, ChestFarmer will only place while the player is sneaking", false); + public final Value moving = new Value("FarmWhileMoving", new String[]{"moving", "fwm"}, "When true, ChestFarmer will farm while walking and jumping", false); + public final Value range = new Value("Range", new String[]{"MaxRange", "MaximumRange"}, "Range around you to mine ender chests", 3, 1, 6, 1); + public final Value placeDelay = new Value("Delay", new String[]{"PlaceDelay", "PlaceDel"}, "The delay(ms) between chests being placed", 100.0f, 0.0f, 500.0f, 1.0f); + public final Value safeLimit = new Value("SafeLimit", new String[]{"limit", "sl", "l"}, "The amount of ender chests we will keep and not farm", 16, 0, 128, 1); + + private final Timer placeTimer = new Timer(); + private final RotationTask placeRotationTask = new RotationTask("ChestFarmerPlaceTask", 3); + private final RotationTask mineRotationTask = new RotationTask("ChestFarmerMineTask", 3); + + private BlockPos currentWorkingPos = null; + + public ChestFarmerModule() { + //String displayName, String[] alias, String desc, String key, int color, ModuleType type + super("ChestFarmer", new String[]{"chestfarmer", "autoenderchest", "autochest", "cf"}, "Automatically place and mine ender chests for obsidian", "NONE", -1, ModuleType.COMBAT); + } + + @Override + public void onToggle() { + super.onToggle(); + this.currentWorkingPos = null; + Seppuku.INSTANCE.getRotationManager().finishTask(this.placeRotationTask); + Seppuku.INSTANCE.getRotationManager().finishTask(this.mineRotationTask); + } + + @Listener + public void onWalkingUpdate(EventUpdateWalkingPlayer event) { + if (event.getStage() != EventStageable.EventStage.PRE) + return; + + if (mc.world == null || mc.player == null) + return; + + if (InventoryUtil.getBlockCount(Blocks.ENDER_CHEST) <= this.safeLimit.getValue()) { + Seppuku.INSTANCE.getNotificationManager().addNotification("", this.getDisplayName() + ": Safe limit reached, toggling off."); + this.toggle(); + return; + } + + if (this.pickOnlyMode.getValue()) { + if (!(mc.player.getHeldItemMainhand().getItem() instanceof ItemPickaxe)) { + this.currentWorkingPos = null; + if (this.placeRotationTask.isOnline()) { + Seppuku.INSTANCE.getRotationManager().finishTask(this.placeRotationTask); + } + if (this.mineRotationTask.isOnline()) { + Seppuku.INSTANCE.getRotationManager().finishTask(this.mineRotationTask); + } + return; + } + } + + final Vec3d pos = MathUtil.interpolateEntity(mc.player, mc.getRenderPartialTicks()); + final float playerSpeed = (float) MathUtil.getDistance(pos, mc.player.posX, mc.player.posY, mc.player.posZ); + + if (!this.moving.getValue()) { + if (!mc.player.onGround || playerSpeed > 0.005f) { + return; + } + } + + final BlockPos interpolatedPos = new BlockPos(pos.x, pos.y, pos.z); + final BlockPos north = interpolatedPos.north(); + final BlockPos south = interpolatedPos.south(); + final BlockPos east = interpolatedPos.east(); + final BlockPos west = interpolatedPos.west(); + + final BlockPos[] possibleBlocks = new BlockPos[]{north.down(), south.down(), east.down(), west.down(), + north, south, east, west}; + + if (this.currentWorkingPos == null) { + if (this.mineRotationTask.isOnline()) { + Seppuku.INSTANCE.getRotationManager().finishTask(this.mineRotationTask); + } + + // find a chest location (starting from under the player first and going upwards) + for (int i = 0; i < possibleBlocks.length; i++) { + final BlockPos blockPos = possibleBlocks[i]; + + if (!this.valid(blockPos)) + continue; + + this.currentWorkingPos = blockPos; + } + } else { // we have blocks to place + if (!mc.player.isHandActive()) { + final HandSwapContext handSwapContext = new HandSwapContext( + mc.player.inventory.currentItem, InventoryUtil.findEnderChestInHotbar(mc.player)); + + if (handSwapContext.getNewSlot() == -1) { + Seppuku.INSTANCE.getRotationManager().finishTask(this.placeRotationTask); + return; + } + + if (!mc.player.isSneaking() && this.sneak.getValue()) { + if (this.placeRotationTask.isOnline()) { + Seppuku.INSTANCE.getRotationManager().finishTask(this.placeRotationTask); + } + return; + } + + if (this.valid(this.currentWorkingPos)) { + Seppuku.INSTANCE.getRotationManager().startTask(this.placeRotationTask); + if (this.placeRotationTask.isOnline()) { + // swap to obsidian + handSwapContext.handleHandSwap(false, mc); + + if (this.placeDelay.getValue() <= 0.0f) { + this.place(this.currentWorkingPos); + } else if (placeTimer.passed(this.placeDelay.getValue())) { + this.place(this.currentWorkingPos); + this.placeTimer.reset(); + } + + // swap back to original + handSwapContext.handleHandSwap(true, mc); + + Seppuku.INSTANCE.getRotationManager().finishTask(this.placeRotationTask); + } + } + } + + for (TileEntity tileEntity : mc.world.loadedTileEntityList) { + if (tileEntity instanceof TileEntityEnderChest) { + if (mc.player.getDistance(tileEntity.getPos().getX(), tileEntity.getPos().getY(), tileEntity.getPos().getZ()) < this.range.getValue()) { + Seppuku.INSTANCE.getRotationManager().startTask(this.mineRotationTask); + if (this.mineRotationTask.isOnline()) { + if (this.rotate.getValue()) { + final float[] rotations = EntityUtil.getRotations(this.currentWorkingPos.getX(), this.currentWorkingPos.getY(), this.currentWorkingPos.getZ()); + Seppuku.INSTANCE.getRotationManager().setPlayerRotations(rotations[0], rotations[1]); + } + mc.playerController.onPlayerDamageBlock(this.currentWorkingPos, mc.player.getHorizontalFacing()); + if (this.swing.getValue()) { + mc.player.swingArm(EnumHand.MAIN_HAND); + } + } + } + } + } + } + } + + private boolean canBreak(BlockPos pos) { + final IBlockState blockState = Minecraft.getMinecraft().world.getBlockState(pos); + final Block block = blockState.getBlock(); + + return block.getBlockHardness(blockState, Minecraft.getMinecraft().world, pos) != -1; + } + + private boolean valid(BlockPos pos) { + // there are no entities colliding with block placement + if (!mc.world.checkNoEntityCollision(new AxisAlignedBB(pos))) + return false; + + // player is too far from distance + if (mc.player.getDistance(pos.getX(), pos.getY(), pos.getZ()) > this.range.getValue()) + return false; + + // check if the block is replaceable + final Block block = mc.world.getBlockState(pos).getBlock(); + return block.isReplaceable(mc.world, pos) && !(block == Blocks.OBSIDIAN) && !(block == Blocks.BEDROCK) && !(block == Blocks.ENDER_CHEST); + } + + private void place(BlockPos pos) { + final Block block = mc.world.getBlockState(pos).getBlock(); + + final EnumFacing direction = MathUtil.calcSide(pos); + if (direction == null) + return; + + final boolean activated = block.onBlockActivated(mc.world, pos, mc.world.getBlockState(pos), mc.player, EnumHand.MAIN_HAND, direction, 0, 0, 0); + + if (activated) + mc.player.connection.sendPacket(new CPacketEntityAction(mc.player, CPacketEntityAction.Action.START_SNEAKING)); + + final EnumFacing otherSide = direction.getOpposite(); + final BlockPos sideOffset = pos.offset(direction); + + if (this.rotate.getValue()) { + final float[] angle = MathUtil.calcAngle(mc.player.getPositionEyes(mc.getRenderPartialTicks()), new Vec3d(pos.getX() + 0.5f, pos.getY() + 0.5f, pos.getZ() + 0.5f)); + Seppuku.INSTANCE.getRotationManager().setPlayerRotations(angle[0], angle[1]); + } + + if (!this.visible.getValue()) { + mc.player.connection.sendPacket(new CPacketPlayerTryUseItemOnBlock(sideOffset, otherSide, EnumHand.MAIN_HAND, 0.5F, 0.5F, 0.5F)); + mc.player.connection.sendPacket(new CPacketAnimation(EnumHand.MAIN_HAND)); + } else { + mc.playerController.processRightClickBlock(mc.player, mc.world, sideOffset, otherSide, new Vec3d(0.5F, 0.5F, 0.5F), EnumHand.MAIN_HAND); + + if (this.swing.getValue()) { + mc.player.swingArm(EnumHand.MAIN_HAND); + } + } + + if (activated) + mc.player.connection.sendPacket(new CPacketEntityAction(mc.player, CPacketEntityAction.Action.STOP_SNEAKING)); + } +} diff --git a/src/main/java/me/rigamortis/seppuku/impl/module/combat/NoCrystalModule.java b/src/main/java/me/rigamortis/seppuku/impl/module/combat/NoCrystalModule.java index eb118aa..c8e6ce7 100644 --- a/src/main/java/me/rigamortis/seppuku/impl/module/combat/NoCrystalModule.java +++ b/src/main/java/me/rigamortis/seppuku/impl/module/combat/NoCrystalModule.java @@ -131,6 +131,7 @@ public final class NoCrystalModule extends Module { if (blocksToPlace.size() != 0) { // we have blocks to place final HandSwapContext handSwapContext = new HandSwapContext( mc.player.inventory.currentItem, InventoryUtil.findObsidianInHotbar(mc.player)); + if (handSwapContext.getNewSlot() == -1) { Seppuku.INSTANCE.getRotationManager().finishTask(this.rotationTask); return; @@ -208,7 +209,7 @@ public final class NoCrystalModule extends Module { private void place(BlockPos pos) { final Block block = mc.world.getBlockState(pos).getBlock(); - final EnumFacing direction = this.calcSide(pos); + final EnumFacing direction = MathUtil.calcSide(pos); if (direction == null) return; @@ -239,14 +240,4 @@ public final class NoCrystalModule extends Module { if (activated) mc.player.connection.sendPacket(new CPacketEntityAction(mc.player, CPacketEntityAction.Action.STOP_SNEAKING)); } - - private EnumFacing calcSide(BlockPos pos) { - for (EnumFacing side : EnumFacing.values()) { - BlockPos sideOffset = pos.offset(side); - IBlockState offsetState = mc.world.getBlockState(sideOffset); - if (!offsetState.getBlock().canCollideCheck(offsetState, false)) continue; - if (!offsetState.getMaterial().isReplaceable()) return side; - } - return null; - } } diff --git a/src/main/java/me/rigamortis/seppuku/impl/module/world/AutoWitherModule.java b/src/main/java/me/rigamortis/seppuku/impl/module/world/AutoWitherModule.java index 0fa39e3..e1e30b3 100644 --- a/src/main/java/me/rigamortis/seppuku/impl/module/world/AutoWitherModule.java +++ b/src/main/java/me/rigamortis/seppuku/impl/module/world/AutoWitherModule.java @@ -309,7 +309,7 @@ public final class AutoWitherModule extends Module { private void place(BlockPos pos) { final Block block = mc.world.getBlockState(pos).getBlock(); - final EnumFacing direction = this.calcSide(pos); + final EnumFacing direction = MathUtil.calcSide(pos); if (direction == null) return; @@ -332,14 +332,4 @@ public final class AutoWitherModule extends Module { if (activated) mc.player.connection.sendPacket(new CPacketEntityAction(mc.player, CPacketEntityAction.Action.STOP_SNEAKING)); } - - private EnumFacing calcSide(BlockPos pos) { - for (EnumFacing side : EnumFacing.values()) { - BlockPos sideOffset = pos.offset(side); - IBlockState offsetState = mc.world.getBlockState(sideOffset); - if (!offsetState.getBlock().canCollideCheck(offsetState, false)) continue; - if (!offsetState.getMaterial().isReplaceable()) return side; - } - return null; - } } diff --git a/src/main/java/me/rigamortis/seppuku/impl/module/world/NukerModule.java b/src/main/java/me/rigamortis/seppuku/impl/module/world/NukerModule.java index dec756b..647347e 100644 --- a/src/main/java/me/rigamortis/seppuku/impl/module/world/NukerModule.java +++ b/src/main/java/me/rigamortis/seppuku/impl/module/world/NukerModule.java @@ -168,7 +168,6 @@ public final class NukerModule extends Module { private boolean canBreak(BlockPos pos) { final IBlockState blockState = Minecraft.getMinecraft().world.getBlockState(pos); final Block block = blockState.getBlock(); - return block.getBlockHardness(blockState, Minecraft.getMinecraft().world, pos) != -1; }