From d906f6092c9d335d4b82d634356604f8169059aa Mon Sep 17 00:00:00 2001 From: RickyTheRacc Date: Wed, 14 Dec 2022 20:51:47 -0600 Subject: [PATCH 1/3] Improve Quiver Added numerous safety checks, pulling a bow from your inventory, and a cooldown between shooting arrows to prevent NCP flagging you for self velocity (configurable) --- .../systems/modules/combat/Quiver.java | 179 +++++++++++++++--- 1 file changed, 153 insertions(+), 26 deletions(-) diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/combat/Quiver.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/combat/Quiver.java index babab71dfe..72d3c41153 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/combat/Quiver.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/combat/Quiver.java @@ -6,29 +6,35 @@ package meteordevelopment.meteorclient.systems.modules.combat; import meteordevelopment.meteorclient.events.world.TickEvent; -import meteordevelopment.meteorclient.settings.BoolSetting; -import meteordevelopment.meteorclient.settings.Setting; -import meteordevelopment.meteorclient.settings.SettingGroup; -import meteordevelopment.meteorclient.settings.StatusEffectListSetting; +import meteordevelopment.meteorclient.mixin.AbstractBlockAccessor; +import meteordevelopment.meteorclient.settings.*; import meteordevelopment.meteorclient.systems.modules.Categories; import meteordevelopment.meteorclient.systems.modules.Module; +import meteordevelopment.meteorclient.utils.entity.EntityUtils; import meteordevelopment.meteorclient.utils.player.FindItemResult; import meteordevelopment.meteorclient.utils.player.InvUtils; import meteordevelopment.orbit.EventHandler; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; import net.minecraft.entity.effect.StatusEffect; import net.minecraft.entity.effect.StatusEffectInstance; import net.minecraft.entity.effect.StatusEffects; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.BowItem; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; import net.minecraft.potion.PotionUtil; +import net.minecraft.util.math.Direction; import java.util.ArrayList; import java.util.List; public class Quiver extends Module { private final SettingGroup sgGeneral = settings.getDefaultGroup(); + private final SettingGroup sgSafety = settings.createGroup("Safety"); + private final Setting> effects = sgGeneral.add(new StatusEffectListSetting.Builder() .name("effects") @@ -37,14 +43,65 @@ public class Quiver extends Module { .build() ); + private final Setting cooldown = sgGeneral.add(new IntSetting.Builder() + .name("cooldown") + .description("How many ticks between shooting effects (19 minimum for NCP).") + .defaultValue(10) + .range(0,40) + .sliderRange(0,40) + .build() + ); + private final Setting checkEffects = sgGeneral.add(new BoolSetting.Builder() - .name("check-existing-effects") + .name("check-effects") .description("Won't shoot you with effects you already have.") .defaultValue(true) .build() ); + private final Setting silentBow = sgGeneral.add(new BoolSetting.Builder() + .name("silent-bow") + .description("Takes a bow from your inventory to quiver.") + .defaultValue(true) + .build() + ); + + private final Setting chatInfo = sgGeneral.add(new BoolSetting.Builder() + .name("chat-info") + .description("Sends info about quiver checks in chat.") + .defaultValue(false) + .build() + ); + + // Safety + + private final Setting onlyInHoles = sgSafety.add(new BoolSetting.Builder() + .name("only-in-holes") + .description("Only quiver when you're in a hole.") + .defaultValue(true) + .build() + ); + + private final Setting onlyOnGround = sgSafety.add(new BoolSetting.Builder() + .name("only-on-ground") + .description("Only quiver when you're on the ground.") + .defaultValue(true) + .build() + ); + + private final Setting minHealth = sgSafety.add(new DoubleSetting.Builder() + .name("min-health") + .description("How much health you must have to quiver.") + .defaultValue(10) + .range(0,36) + .sliderRange(0,36) + .build() + ); + private final List arrowSlots = new ArrayList<>(); + private FindItemResult bow; + private boolean wasMainhand, wasHotbar; + private int timer, prevSlot; public Quiver() { super(Categories.Combat, "quiver", "Shoots arrows at yourself."); @@ -52,21 +109,22 @@ public Quiver() { @Override public void onActivate() { - - FindItemResult bow = InvUtils.findInHotbar(Items.BOW); - - if (!bow.isHotbar()) { - error("No bow found... disabling."); - toggle(); - } + bow = InvUtils.find(Items.BOW); + if (!shouldQuiver()) return; mc.options.useKey.setPressed(false); mc.interactionManager.stopUsingItem(mc.player); - InvUtils.swap(bow.slot(), true); + prevSlot = bow.slot(); + wasHotbar = bow.isHotbar(); + timer = 0; - arrowSlots.clear(); + if (!bow.isMainHand()) { + if (wasHotbar) InvUtils.swap(bow.slot(), true); + else InvUtils.move().from(mc.player.getInventory().selectedSlot).to(prevSlot); + } else wasMainhand = true; + arrowSlots.clear(); List usedEffects = new ArrayList<>(); for (int i = mc.player.getInventory().size(); i > 0; i--) { @@ -91,33 +149,34 @@ public void onActivate() { } } - private boolean hasEffect(StatusEffect effect) { - for (StatusEffectInstance statusEffect : mc.player.getStatusEffects()) { - if (statusEffect.getEffectType() == effect) return true; - } - - return false; - } - @Override public void onDeactivate() { - InvUtils.swapBack(); + if (!wasMainhand) { + if (wasHotbar) InvUtils.swapBack(); + else InvUtils.move().from(mc.player.getInventory().selectedSlot).to(prevSlot); + } } @EventHandler private void onTick(TickEvent.Pre event) { - if (arrowSlots.isEmpty() || !InvUtils.testInMainHand(Items.BOW)) { + bow = InvUtils.find(Items.BOW); + if (!shouldQuiver()) return; + if (arrowSlots.isEmpty()) { toggle(); return; } + if (timer > 0) { + timer--; + return; + } + boolean charging = mc.options.useKey.isPressed(); if (!charging) { InvUtils.move().from(arrowSlots.get(0)).to(9); mc.options.useKey.setPressed(true); - } - else { + } else { if (BowItem.getPullProgress(mc.player.getItemUseTime()) >= 0.12) { int targetSlot = arrowSlots.get(0); arrowSlots.remove(0); @@ -126,7 +185,75 @@ private void onTick(TickEvent.Pre event) { mc.options.useKey.setPressed(false); mc.interactionManager.stopUsingItem(mc.player); if (targetSlot != 9) InvUtils.move().from(9).to(targetSlot); + + timer = cooldown.get(); } } } + + private boolean shouldQuiver() { + if (!bow.found() || !bow.isHotbar() && !silentBow.get()) { + if (chatInfo.get()) error("Couldn't find a usable bow, disabling."); + toggle(); + return false; + } + + if (!headIsOpen()) { + if (chatInfo.get()) error("Not enough space to quiver, disabling."); + toggle(); + return false; + } + + if (EntityUtils.getTotalHealth(mc.player) < minHealth.get()) { + if (chatInfo.get()) error("Not enough health to quiver, disabling."); + toggle(); + return false; + } + + if (onlyOnGround.get() && !mc.player.isOnGround()) { + if (chatInfo.get()) error("You are not on the ground, disabling."); + toggle(); + return false; + } + + if (onlyInHoles.get() && !isSurrounded(mc.player)) { + if (chatInfo.get()) error("You are not in a hole!"); + toggle(); + return false; + } + + return true; + } + + private boolean headIsOpen() { + BlockState pos1 = mc.world.getBlockState(mc.player.getBlockPos().up(2)); + BlockState pos2 = mc.world.getBlockState(mc.player.getBlockPos().up(3)); + + boolean air1 = !((AbstractBlockAccessor) pos1.getBlock()).isCollidable(); + boolean air2 = !((AbstractBlockAccessor) pos2.getBlock()).isCollidable(); + + return air1 && air2; + } + + private boolean hasEffect(StatusEffect effect) { + for (StatusEffectInstance statusEffect : mc.player.getStatusEffects()) { + if (statusEffect.getEffectType() == effect) return true; + } + + return false; + } + + private boolean isSurrounded(PlayerEntity target) { + for (Direction dir : Direction.values()) { + if (dir == Direction.UP || dir == Direction.DOWN) continue; + + Block block = mc.world.getBlockState(target.getBlockPos().offset(dir)).getBlock(); + if (block != Blocks.OBSIDIAN && block != Blocks.BEDROCK && block != Blocks.RESPAWN_ANCHOR + && block != Blocks.CRYING_OBSIDIAN && block != Blocks.NETHERITE_BLOCK) { + return false; + } + } + + return true; + } } From f8002b6a265f9e9a6c3ecbb4f829c311a74409c4 Mon Sep 17 00:00:00 2001 From: RickyTheRacc Date: Wed, 14 Dec 2022 22:26:29 -0600 Subject: [PATCH 2/3] Optimize Checks Memory is the enemy --- .../systems/modules/combat/Quiver.java | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/combat/Quiver.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/combat/Quiver.java index 72d3c41153..7718f54c00 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/combat/Quiver.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/combat/Quiver.java @@ -13,6 +13,7 @@ import meteordevelopment.meteorclient.utils.entity.EntityUtils; import meteordevelopment.meteorclient.utils.player.FindItemResult; import meteordevelopment.meteorclient.utils.player.InvUtils; +import meteordevelopment.meteorclient.utils.world.Dir; import meteordevelopment.orbit.EventHandler; import net.minecraft.block.Block; import net.minecraft.block.BlockState; @@ -26,6 +27,7 @@ import net.minecraft.item.Items; import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; import net.minecraft.potion.PotionUtil; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import java.util.ArrayList; @@ -102,6 +104,7 @@ public class Quiver extends Module { private FindItemResult bow; private boolean wasMainhand, wasHotbar; private int timer, prevSlot; + private BlockPos.Mutable testPos = new BlockPos.Mutable(); public Quiver() { super(Categories.Combat, "quiver", "Shoots arrows at yourself."); @@ -226,13 +229,13 @@ private boolean shouldQuiver() { } private boolean headIsOpen() { - BlockState pos1 = mc.world.getBlockState(mc.player.getBlockPos().up(2)); - BlockState pos2 = mc.world.getBlockState(mc.player.getBlockPos().up(3)); + testPos.set(mc.player.getBlockPos().add(0, 1, 0)); + BlockState pos1 = mc.world.getBlockState(testPos); + if (((AbstractBlockAccessor) pos1.getBlock()).isCollidable()) return false; - boolean air1 = !((AbstractBlockAccessor) pos1.getBlock()).isCollidable(); - boolean air2 = !((AbstractBlockAccessor) pos2.getBlock()).isCollidable(); - - return air1 && air2; + testPos.add(0, 1, 0); + BlockState pos2 = mc.world.getBlockState(testPos); + return !((AbstractBlockAccessor) pos2.getBlock()).isCollidable(); } private boolean hasEffect(StatusEffect effect) { @@ -247,7 +250,9 @@ private boolean isSurrounded(PlayerEntity target) { for (Direction dir : Direction.values()) { if (dir == Direction.UP || dir == Direction.DOWN) continue; - Block block = mc.world.getBlockState(target.getBlockPos().offset(dir)).getBlock(); + testPos.set(target.getBlockPos()).offset(dir); + Block block = mc.world.getBlockState(testPos).getBlock(); + if (block != Blocks.OBSIDIAN && block != Blocks.BEDROCK && block != Blocks.RESPAWN_ANCHOR && block != Blocks.CRYING_OBSIDIAN && block != Blocks.NETHERITE_BLOCK) { return false; From 7e2a106a661ebfcd42447b702281c30ec222d321 Mon Sep 17 00:00:00 2001 From: RickyTheRacc Date: Thu, 15 Dec 2022 10:14:13 -0600 Subject: [PATCH 3/3] Small Cleanup --- .../meteorclient/systems/modules/combat/Quiver.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/combat/Quiver.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/combat/Quiver.java index 7718f54c00..c0efef35bd 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/combat/Quiver.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/combat/Quiver.java @@ -13,7 +13,6 @@ import meteordevelopment.meteorclient.utils.entity.EntityUtils; import meteordevelopment.meteorclient.utils.player.FindItemResult; import meteordevelopment.meteorclient.utils.player.InvUtils; -import meteordevelopment.meteorclient.utils.world.Dir; import meteordevelopment.orbit.EventHandler; import net.minecraft.block.Block; import net.minecraft.block.BlockState; @@ -104,7 +103,7 @@ public class Quiver extends Module { private FindItemResult bow; private boolean wasMainhand, wasHotbar; private int timer, prevSlot; - private BlockPos.Mutable testPos = new BlockPos.Mutable(); + private final BlockPos.Mutable testPos = new BlockPos.Mutable(); public Quiver() { super(Categories.Combat, "quiver", "Shoots arrows at yourself."); @@ -220,7 +219,7 @@ private boolean shouldQuiver() { } if (onlyInHoles.get() && !isSurrounded(mc.player)) { - if (chatInfo.get()) error("You are not in a hole!"); + if (chatInfo.get()) error("You are not in a hole, disabling."); toggle(); return false; }