Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Quiver #3060

Merged
merged 3 commits into from
Dec 16, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,36 @@
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.BlockPos;
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<List<StatusEffect>> effects = sgGeneral.add(new StatusEffectListSetting.Builder()
.name("effects")
Expand All @@ -37,36 +44,89 @@ public class Quiver extends Module {
.build()
);

private final Setting<Integer> 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<Boolean> 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<Boolean> silentBow = sgGeneral.add(new BoolSetting.Builder()
.name("silent-bow")
.description("Takes a bow from your inventory to quiver.")
.defaultValue(true)
.build()
);

private final Setting<Boolean> chatInfo = sgGeneral.add(new BoolSetting.Builder()
.name("chat-info")
.description("Sends info about quiver checks in chat.")
.defaultValue(false)
.build()
);

// Safety

private final Setting<Boolean> 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<Boolean> 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<Double> 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<Integer> arrowSlots = new ArrayList<>();
private FindItemResult bow;
private boolean wasMainhand, wasHotbar;
private int timer, prevSlot;
private final BlockPos.Mutable testPos = new BlockPos.Mutable();

public Quiver() {
super(Categories.Combat, "quiver", "Shoots arrows at yourself.");
}

@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<StatusEffect> usedEffects = new ArrayList<>();

for (int i = mc.player.getInventory().size(); i > 0; i--) {
Expand All @@ -91,33 +151,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);
Expand All @@ -126,7 +187,77 @@ 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, disabling.");
toggle();
return false;
}

return true;
}

private boolean headIsOpen() {
testPos.set(mc.player.getBlockPos().add(0, 1, 0));
BlockState pos1 = mc.world.getBlockState(testPos);
if (((AbstractBlockAccessor) pos1.getBlock()).isCollidable()) return false;

testPos.add(0, 1, 0);
BlockState pos2 = mc.world.getBlockState(testPos);
return !((AbstractBlockAccessor) pos2.getBlock()).isCollidable();
}

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;

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;
}
}

return true;
}
}