/* * Copyright (C) 2014 - 2020 | Alexander01998 | All rights reserved. * * This source code is subject to the terms of the GNU General Public * License, version 3. If a copy of the GPL was not distributed with this * file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt */ package net.wurstclient.hacks; import java.util.Comparator; import com.mojang.datafixers.util.Pair; import net.minecraft.block.Block; import net.minecraft.block.BlockWithEntity; import net.minecraft.block.CraftingTableBlock; import net.minecraft.entity.Entity; import net.minecraft.entity.effect.StatusEffect; import net.minecraft.entity.effect.StatusEffectInstance; import net.minecraft.entity.effect.StatusEffects; import net.minecraft.entity.passive.TameableEntity; import net.minecraft.entity.passive.VillagerEntity; import net.minecraft.item.FoodComponent; import net.minecraft.item.FoodComponents; import net.minecraft.item.Item; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.hit.EntityHitResult; import net.minecraft.util.hit.HitResult; import net.minecraft.util.math.BlockPos; import net.wurstclient.Category; import net.wurstclient.SearchTags; import net.wurstclient.events.UpdateListener; import net.wurstclient.hack.Hack; import net.wurstclient.settings.CheckboxSetting; import net.wurstclient.settings.EnumSetting; @SearchTags({"auto eat", "AutoFood", "auto food", "AutoFeeder", "auto feeder", "AutoFeeding", "auto feeding", "AutoSoup", "auto soup"}) public final class AutoEatHack extends Hack implements UpdateListener { private final CheckboxSetting eatWhileWalking = new CheckboxSetting( "Eat while walking", "Slows you down, not recommended.", false); private final EnumSetting<FoodPriority> foodPriority = new EnumSetting<>("Prefer food with", FoodPriority.values(), FoodPriority.HIGH_SATURATION); private final CheckboxSetting allowHunger = new CheckboxSetting("Allow hunger effect", "Rotten flesh applies a harmless 'hunger' effect.\n" + "It is safe to eat and useful as emergency food.", true); private final CheckboxSetting allowPoison = new CheckboxSetting("Allow poison effect", "Poisoned food applies damage over time.\n" + "Not recommended.", false); private final CheckboxSetting allowChorus = new CheckboxSetting("Allow chorus fruit", "Eating chorus fruit teleports you to a random location.\n" + "Not recommended.", false); private int oldSlot = -1; public AutoEatHack() { super("AutoEat", "Automatically eats food when necessary."); setCategory(Category.ITEMS); addSetting(eatWhileWalking); addSetting(foodPriority); addSetting(allowHunger); addSetting(allowPoison); addSetting(allowChorus); } @Override public void onEnable() { EVENTS.add(UpdateListener.class, this); } @Override public void onDisable() { EVENTS.remove(UpdateListener.class, this); stopIfEating(); } @Override public void onUpdate() { if(!shouldEat()) { stopIfEating(); return; } int bestSlot = getBestSlot(); if(bestSlot == -1) { stopIfEating(); return; } // save old slot if(!isEating()) oldSlot = MC.player.inventory.selectedSlot; // set slot MC.player.inventory.selectedSlot = bestSlot; // eat food MC.options.keyUse.setPressed(true); IMC.getInteractionManager().rightClickItem(); } private int getBestSlot() { int bestSlot = -1; FoodComponent bestFood = null; Comparator<FoodComponent> comparator = foodPriority.getSelected().comparator; for(int i = 0; i < 9; i++) { // filter out non-food items Item item = MC.player.inventory.getStack(i).getItem(); if(!item.isFood()) continue; FoodComponent food = item.getFoodComponent(); if(!isAllowedFood(food)) continue; // compare to previously found food if(bestFood == null || comparator.compare(food, bestFood) > 0) { bestFood = food; bestSlot = i; } } return bestSlot; } private boolean isAllowedFood(FoodComponent food) { if(!allowChorus.isChecked() && food == FoodComponents.CHORUS_FRUIT) return false; for(Pair<StatusEffectInstance, Float> pair : food.getStatusEffects()) { StatusEffect effect = pair.getFirst().getEffectType(); if(!allowHunger.isChecked() && effect == StatusEffects.HUNGER) return false; if(!allowPoison.isChecked() && effect == StatusEffects.POISON) return false; } return true; } private boolean shouldEat() { if(MC.player.abilities.creativeMode) return false; if(!MC.player.canConsume(false)) return false; if(!eatWhileWalking.isChecked() && (MC.player.forwardSpeed != 0 || MC.player.sidewaysSpeed != 0)) return false; if(isClickable(MC.crosshairTarget)) return false; return true; } private boolean isClickable(HitResult hitResult) { if(hitResult == null) return false; if(hitResult instanceof EntityHitResult) { Entity entity = ((EntityHitResult)hitResult).getEntity(); return entity instanceof VillagerEntity || entity instanceof TameableEntity; } if(hitResult instanceof BlockHitResult) { BlockPos pos = ((BlockHitResult)hitResult).getBlockPos(); if(pos == null) return false; Block block = MC.world.getBlockState(pos).getBlock(); return block instanceof BlockWithEntity || block instanceof CraftingTableBlock; } return false; } public boolean isEating() { return oldSlot != -1; } private void stopIfEating() { if(!isEating()) return; MC.options.keyUse.setPressed(false); MC.player.inventory.selectedSlot = oldSlot; oldSlot = -1; } public static enum FoodPriority { HIGH_HUNGER("High Food Points", Comparator.<FoodComponent> comparingInt(food -> food.getHunger())), HIGH_SATURATION("High Saturation", Comparator.<FoodComponent> comparingDouble( food -> food.getSaturationModifier())), LOW_HUNGER("Low Food Points", Comparator.<FoodComponent> comparingInt(food -> food.getHunger()) .reversed()), LOW_SATURATION("Low Saturation", Comparator.<FoodComponent> comparingDouble( food -> food.getSaturationModifier()).reversed()); private final String name; private final Comparator<FoodComponent> comparator; private FoodPriority(String name, Comparator<FoodComponent> comparator) { this.name = name; this.comparator = comparator; } @Override public String toString() { return name; } } }