From 871122fac1b632b1d7412f197aad27fd156464ef Mon Sep 17 00:00:00 2001 From: Osama Date: Fri, 29 Nov 2024 22:21:46 +0600 Subject: [PATCH 01/10] Sorry my autoformat messed up the formatting - cant do nutting bout it --- .../feature/impl/AutoWardrobe.java | 4 + .../farmhelperv2/feature/impl/PestFarmer.java | 5 + .../feature/impl/PestsDestroyer.java | 2805 +++++++++-------- 3 files changed, 1538 insertions(+), 1276 deletions(-) create mode 100644 src/main/java/com/jelly/farmhelperv2/feature/impl/AutoWardrobe.java create mode 100644 src/main/java/com/jelly/farmhelperv2/feature/impl/PestFarmer.java diff --git a/src/main/java/com/jelly/farmhelperv2/feature/impl/AutoWardrobe.java b/src/main/java/com/jelly/farmhelperv2/feature/impl/AutoWardrobe.java new file mode 100644 index 00000000..e8d8797b --- /dev/null +++ b/src/main/java/com/jelly/farmhelperv2/feature/impl/AutoWardrobe.java @@ -0,0 +1,4 @@ +package com.jelly.farmhelperv2.feature.impl; + +public class AutoWardrobe { +} diff --git a/src/main/java/com/jelly/farmhelperv2/feature/impl/PestFarmer.java b/src/main/java/com/jelly/farmhelperv2/feature/impl/PestFarmer.java new file mode 100644 index 00000000..d1e389cf --- /dev/null +++ b/src/main/java/com/jelly/farmhelperv2/feature/impl/PestFarmer.java @@ -0,0 +1,5 @@ +package com.jelly.farmhelperv2.feature.impl; + +public class PestFarmer { + +} diff --git a/src/main/java/com/jelly/farmhelperv2/feature/impl/PestsDestroyer.java b/src/main/java/com/jelly/farmhelperv2/feature/impl/PestsDestroyer.java index def6660e..21dfbe9a 100644 --- a/src/main/java/com/jelly/farmhelperv2/feature/impl/PestsDestroyer.java +++ b/src/main/java/com/jelly/farmhelperv2/feature/impl/PestsDestroyer.java @@ -48,1377 +48,1630 @@ import java.util.stream.Collectors; public class PestsDestroyer implements IFeature { - private static PestsDestroyer instance; - private final Minecraft mc = Minecraft.getMinecraft(); - private final List> pests = Arrays.asList( - new Tuple<>("Beetle", "ewogICJ0aW1lc3RhbXAiIDogMTcyMzE3OTc4OTkzNCwKICAicHJvZmlsZUlkIiA6ICJlMjc5NjliODYyNWY0NDg1YjkyNmM5NTBhMDljMWMwMSIsCiAgInByb2ZpbGVOYW1lIiA6ICJLRVZJTktFTE9LRSIsCiAgInNpZ25hdHVyZVJlcXVpcmVkIiA6IHRydWUsCiAgInRleHR1cmVzIiA6IHsKICAgICJTS0lOIiA6IHsKICAgICAgInVybCIgOiAiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS83MGExZTgzNmJmMTk2OGIyZWFhNDgzNzIyN2ExOTIwNGYxNzI5NWQ4NzBlZTllNzU0YmQ2YjZkNjBkZGJlZDNjIgogICAgfQogIH0KfQ"), - new Tuple<>("Cricket", "ewogICJ0aW1lc3RhbXAiIDogMTcyMzE3OTgxMTI2NCwKICAicHJvZmlsZUlkIiA6ICJjZjc4YzFkZjE3ZTI0Y2Q5YTIxYmU4NWQ0NDk5ZWE4ZiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNYXR0c0FybW9yU3RhbmRzIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2EyNGM2OWY5NmNlNTU2MjIxZTE5NWM4ZWYyYmZhZDcxZWJmN2Y5NWY1YWU5MTRhNDg0YThkMGVjMjE2NzI2NzQiCiAgICB9CiAgfQp9"), - new Tuple<>("Earthworm", "ewogICJ0aW1lc3RhbXAiIDogMTY5NzQ3MDQ1OTc0NywKICAicHJvZmlsZUlkIiA6ICIyNTBlNzc5MjZkNDM0ZDIyYWM2MTQ4N2EyY2M3YzAwNCIsCiAgInByb2ZpbGVOYW1lIiA6ICJMdW5hMTIxMDUiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjQwM2JhNDAyN2EzMzNkOGQyZmQzMmFiNTlkMWNmZGJhYTdkOTA4ZDgwZDIzODFkYjJhNjljYmU2NTQ1MGFkOCIKICAgIH0KICB9Cn0"), - new Tuple<>("Fly", "ewogICJ0aW1lc3RhbXAiIDogMTY5Njk0NTA2MzI4MSwKICAicHJvZmlsZUlkIiA6ICJjN2FmMWNkNjNiNTE0Y2YzOGY4NWQ2ZDUxNzhjYThlNCIsCiAgInByb2ZpbGVOYW1lIiA6ICJtb25zdGVyZ2FtZXIzMTUiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOWQ5MGU3Nzc4MjZhNTI0NjEzNjhlMjZkMWIyZTE5YmZhMWJhNTgyZDYwMjQ4M2U1NDVmNDEyNGQwZjczMTg0MiIKICAgIH0KICB9Cn0"), - new Tuple<>("Locust", "ewogICJ0aW1lc3RhbXAiIDogMTY5NzU1NzA3NzAzNywKICAicHJvZmlsZUlkIiA6ICI0YjJlMGM1ODliZjU0ZTk1OWM1ZmJlMzg5MjQ1MzQzZSIsCiAgInByb2ZpbGVOYW1lIiA6ICJfTmVvdHJvbl8iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNGIyNGE0ODJhMzJkYjFlYTc4ZmI5ODA2MGIwYzJmYTRhMzczY2JkMThhNjhlZGRkZWI3NDE5NDU1YTU5Y2RhOSIKICAgIH0KICB9Cn0"), - new Tuple<>("Mite", "ewogICJ0aW1lc3RhbXAiIDogMTY5Njg3MDQxOTcyNSwKICAicHJvZmlsZUlkIiA6ICJkYjYzNWE3MWI4N2U0MzQ5YThhYTgwOTMwOWFhODA3NyIsCiAgInByb2ZpbGVOYW1lIiA6ICJFbmdlbHMxNzQiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYmU2YmFmNjQzMWE5ZGFhMmNhNjA0ZDVhM2MyNmU5YTc2MWQ1OTUyZjA4MTcxNzRhNGZlMGI3NjQ2MTZlMjFmZiIKICAgIH0KICB9Cn0"), - new Tuple<>("Mosquito", "ewogICJ0aW1lc3RhbXAiIDogMTY5Njk0NTAyOTQ2MSwKICAicHJvZmlsZUlkIiA6ICI3NTE0NDQ4MTkxZTY0NTQ2OGM5NzM5YTZlMzk1N2JlYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJUaGFua3NNb2phbmciLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTJhOWZlMDViYzY2M2VmY2QxMmU1NmEzY2NjNWVjMDM1YmY1NzdiNzg3MDg1NDhiNmY0ZmZjZjFkMzBlY2NmZSIKICAgIH0KICB9Cn0"), - new Tuple<>("Moth", "ewogICJ0aW1lc3RhbXAiIDogMTY5Njg3MDQwNTk1NCwKICAicHJvZmlsZUlkIiA6ICJiMTUyZDlhZTE1MTM0OWNmOWM2NmI0Y2RjMTA5NTZjOCIsCiAgInByb2ZpbGVOYW1lIiA6ICJNaXNxdW90aCIsCiAgInNpZ25hdHVyZVJlcXVpcmVkIiA6IHRydWUsCiAgInRleHR1cmVzIiA6IHsKICAgICJTS0lOIiA6IHsKICAgICAgInVybCIgOiAiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS82NTQ4NWM0YjM0ZTViNTQ3MGJlOTRkZTEwMGU2MWY3ODE2ZjgxYmM1YTExZGZkZjBlY2NmODkwMTcyZGE1ZDBhIgogICAgfQogIH0KfQ"), - new Tuple<>("Rat", "ewogICJ0aW1lc3RhbXAiIDogMTYxODQxOTcwMTc1MywKICAicHJvZmlsZUlkIiA6ICI3MzgyZGRmYmU0ODU0NTVjODI1ZjkwMGY4OGZkMzJmOCIsCiAgInByb2ZpbGVOYW1lIiA6ICJCdUlJZXQiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYThhYmI0NzFkYjBhYjc4NzAzMDExOTc5ZGM4YjQwNzk4YTk0MWYzYTRkZWMzZWM2MWNiZWVjMmFmOGNmZmU4IiwKICAgICAgIm1ldGFkYXRhIiA6IHsKICAgICAgICAibW9kZWwiIDogInNsaW0iCiAgICAgIH0KICAgIH0KICB9Cn0="), - new Tuple<>("Slug", "ewogICJ0aW1lc3RhbXAiIDogMTY5NzQ3MDQ0MzA4MiwKICAicHJvZmlsZUlkIiA6ICJkOGNkMTNjZGRmNGU0Y2IzODJmYWZiYWIwOGIyNzQ4OSIsCiAgInByb2ZpbGVOYW1lIiA6ICJaYWNoeVphY2giLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvN2E3OWQwZmQ2NzdiNTQ1MzA5NjExMTdlZjg0YWRjMjA2ZTJjYzUwNDVjMTM0NGQ2MWQ3NzZiZjhhYzJmZTFiYSIKICAgIH0KICB9Cn0") - ); - private Optional closestPlot = Optional.empty(); - @Getter - private final ArrayList pestsLocations = new ArrayList<>(); - private final List killedEntities = new ArrayList<>(); - @Getter - private final Clock stuckClock = new Clock(); - @Getter - private final Clock delayClock = new Clock(); - private final Clock delayBetweenBackTaps = new Clock(); - private final Clock delayBetweenFireworks = new Clock(); - @Getter - private Optional currentEntityTarget = Optional.empty(); - private boolean enabled = false; - private boolean preparing = false; - @Setter - @Getter - public int cantReachPest = 0; - @Getter - @Setter - private States state = States.IDLE; - @Getter - private EscapeState escapeState = EscapeState.NONE; - private Optional preTpBlockPos = Optional.empty(); - private long lastFireworkTime = 0; - private int getLocationTries = 0; - private int flyPathfinderTries = 0; - private RotationState rotationState = RotationState.NONE; - private boolean needToUpdatePlots = false; - private final HashMap vacuumRange = new HashMap() {{ - put("Skymart Vacuum", 5F); - put("Turbo Vacuum", 7.5F); - put("Hyper Vacuum", 10F); - put("InfiniVacuum™ Hooverius", 15F); - put("InfiniVacuum", 12.5F); - }}; - @Getter - private float currentVacuumRange = -1; - - private boolean gotRangeOfVacuum = false; - private boolean isPlotObstructed = false; - private long lastKillTimestamp = 0; - private int previousCurrentPlotPestsCount = 0; - - private final List killedPestsFrom = new ArrayList<>(); - - public static PestsDestroyer getInstance() { - if (instance == null) { - instance = new PestsDestroyer(); - } - return instance; - } - - @Override - public String getName() { - return "Pests Destroyer"; - } - - @Override - public boolean isRunning() { - return enabled || preparing; - } - - @Override - public boolean shouldPauseMacroExecution() { - return true; - } - @Override - public boolean shouldStartAtMacroStart() { - return false; + private static PestsDestroyer instance; + private final Minecraft mc = Minecraft.getMinecraft(); + private final List> pests = Arrays.asList( + new Tuple<>("Beetle", + "ewogICJ0aW1lc3RhbXAiIDogMTcyMzE3OTc4OTkzNCwKICAicHJvZmlsZUlkIiA6ICJlMjc5NjliODYyNWY0NDg1YjkyNmM5NTBhMDljMWMwMSIsCiAgInByb2ZpbGVOYW1lIiA6ICJLRVZJTktFTE9LRSIsCiAgInNpZ25hdHVyZVJlcXVpcmVkIiA6IHRydWUsCiAgInRleHR1cmVzIiA6IHsKICAgICJTS0lOIiA6IHsKICAgICAgInVybCIgOiAiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS83MGExZTgzNmJmMTk2OGIyZWFhNDgzNzIyN2ExOTIwNGYxNzI5NWQ4NzBlZTllNzU0YmQ2YjZkNjBkZGJlZDNjIgogICAgfQogIH0KfQ"), + new Tuple<>("Cricket", + "ewogICJ0aW1lc3RhbXAiIDogMTcyMzE3OTgxMTI2NCwKICAicHJvZmlsZUlkIiA6ICJjZjc4YzFkZjE3ZTI0Y2Q5YTIxYmU4NWQ0NDk5ZWE4ZiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNYXR0c0FybW9yU3RhbmRzIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2EyNGM2OWY5NmNlNTU2MjIxZTE5NWM4ZWYyYmZhZDcxZWJmN2Y5NWY1YWU5MTRhNDg0YThkMGVjMjE2NzI2NzQiCiAgICB9CiAgfQp9"), + new Tuple<>("Earthworm", + "ewogICJ0aW1lc3RhbXAiIDogMTY5NzQ3MDQ1OTc0NywKICAicHJvZmlsZUlkIiA6ICIyNTBlNzc5MjZkNDM0ZDIyYWM2MTQ4N2EyY2M3YzAwNCIsCiAgInByb2ZpbGVOYW1lIiA6ICJMdW5hMTIxMDUiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjQwM2JhNDAyN2EzMzNkOGQyZmQzMmFiNTlkMWNmZGJhYTdkOTA4ZDgwZDIzODFkYjJhNjljYmU2NTQ1MGFkOCIKICAgIH0KICB9Cn0"), + new Tuple<>("Fly", + "ewogICJ0aW1lc3RhbXAiIDogMTY5Njk0NTA2MzI4MSwKICAicHJvZmlsZUlkIiA6ICJjN2FmMWNkNjNiNTE0Y2YzOGY4NWQ2ZDUxNzhjYThlNCIsCiAgInByb2ZpbGVOYW1lIiA6ICJtb25zdGVyZ2FtZXIzMTUiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOWQ5MGU3Nzc4MjZhNTI0NjEzNjhlMjZkMWIyZTE5YmZhMWJhNTgyZDYwMjQ4M2U1NDVmNDEyNGQwZjczMTg0MiIKICAgIH0KICB9Cn0"), + new Tuple<>("Locust", + "ewogICJ0aW1lc3RhbXAiIDogMTY5NzU1NzA3NzAzNywKICAicHJvZmlsZUlkIiA6ICI0YjJlMGM1ODliZjU0ZTk1OWM1ZmJlMzg5MjQ1MzQzZSIsCiAgInByb2ZpbGVOYW1lIiA6ICJfTmVvdHJvbl8iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNGIyNGE0ODJhMzJkYjFlYTc4ZmI5ODA2MGIwYzJmYTRhMzczY2JkMThhNjhlZGRkZWI3NDE5NDU1YTU5Y2RhOSIKICAgIH0KICB9Cn0"), + new Tuple<>("Mite", + "ewogICJ0aW1lc3RhbXAiIDogMTY5Njg3MDQxOTcyNSwKICAicHJvZmlsZUlkIiA6ICJkYjYzNWE3MWI4N2U0MzQ5YThhYTgwOTMwOWFhODA3NyIsCiAgInByb2ZpbGVOYW1lIiA6ICJFbmdlbHMxNzQiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYmU2YmFmNjQzMWE5ZGFhMmNhNjA0ZDVhM2MyNmU5YTc2MWQ1OTUyZjA4MTcxNzRhNGZlMGI3NjQ2MTZlMjFmZiIKICAgIH0KICB9Cn0"), + new Tuple<>("Mosquito", + "ewogICJ0aW1lc3RhbXAiIDogMTY5Njk0NTAyOTQ2MSwKICAicHJvZmlsZUlkIiA6ICI3NTE0NDQ4MTkxZTY0NTQ2OGM5NzM5YTZlMzk1N2JlYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJUaGFua3NNb2phbmciLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTJhOWZlMDViYzY2M2VmY2QxMmU1NmEzY2NjNWVjMDM1YmY1NzdiNzg3MDg1NDhiNmY0ZmZjZjFkMzBlY2NmZSIKICAgIH0KICB9Cn0"), + new Tuple<>("Moth", + "ewogICJ0aW1lc3RhbXAiIDogMTY5Njg3MDQwNTk1NCwKICAicHJvZmlsZUlkIiA6ICJiMTUyZDlhZTE1MTM0OWNmOWM2NmI0Y2RjMTA5NTZjOCIsCiAgInByb2ZpbGVOYW1lIiA6ICJNaXNxdW90aCIsCiAgInNpZ25hdHVyZVJlcXVpcmVkIiA6IHRydWUsCiAgInRleHR1cmVzIiA6IHsKICAgICJTS0lOIiA6IHsKICAgICAgInVybCIgOiAiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS82NTQ4NWM0YjM0ZTViNTQ3MGJlOTRkZTEwMGU2MWY3ODE2ZjgxYmM1YTExZGZkZjBlY2NmODkwMTcyZGE1ZDBhIgogICAgfQogIH0KfQ"), + new Tuple<>("Rat", + "ewogICJ0aW1lc3RhbXAiIDogMTYxODQxOTcwMTc1MywKICAicHJvZmlsZUlkIiA6ICI3MzgyZGRmYmU0ODU0NTVjODI1ZjkwMGY4OGZkMzJmOCIsCiAgInByb2ZpbGVOYW1lIiA6ICJCdUlJZXQiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYThhYmI0NzFkYjBhYjc4NzAzMDExOTc5ZGM4YjQwNzk4YTk0MWYzYTRkZWMzZWM2MWNiZWVjMmFmOGNmZmU4IiwKICAgICAgIm1ldGFkYXRhIiA6IHsKICAgICAgICAibW9kZWwiIDogInNsaW0iCiAgICAgIH0KICAgIH0KICB9Cn0="), + new Tuple<>("Slug", + "ewogICJ0aW1lc3RhbXAiIDogMTY5NzQ3MDQ0MzA4MiwKICAicHJvZmlsZUlkIiA6ICJkOGNkMTNjZGRmNGU0Y2IzODJmYWZiYWIwOGIyNzQ4OSIsCiAgInByb2ZpbGVOYW1lIiA6ICJaYWNoeVphY2giLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvN2E3OWQwZmQ2NzdiNTQ1MzA5NjExMTdlZjg0YWRjMjA2ZTJjYzUwNDVjMTM0NGQ2MWQ3NzZiZjhhYzJmZTFiYSIKICAgIH0KICB9Cn0") + ); + private Optional closestPlot = Optional.empty(); + @Getter + private final ArrayList pestsLocations = new ArrayList<>(); + private final List killedEntities = new ArrayList<>(); + @Getter + private final Clock stuckClock = new Clock(); + @Getter + private final Clock delayClock = new Clock(); + private final Clock delayBetweenBackTaps = new Clock(); + private final Clock delayBetweenFireworks = new Clock(); + @Getter + private Optional currentEntityTarget = Optional.empty(); + private boolean enabled = false; + private boolean preparing = false; + @Setter + @Getter + public int cantReachPest = 0; + @Getter + @Setter + private States state = States.IDLE; + @Getter + private EscapeState escapeState = EscapeState.NONE; + private Optional preTpBlockPos = Optional.empty(); + private long lastFireworkTime = 0; + private int getLocationTries = 0; + private int flyPathfinderTries = 0; + private RotationState rotationState = RotationState.NONE; + private boolean needToUpdatePlots = false; + private final HashMap vacuumRange = new HashMap() {{ + put("Skymart Vacuum", 5F); + put("Turbo Vacuum", 7.5F); + put("Hyper Vacuum", 10F); + put("InfiniVacuum™ Hooverius", 15F); + put("InfiniVacuum", 12.5F); + }}; + @Getter + private float currentVacuumRange = -1; + + private boolean gotRangeOfVacuum = false; + private boolean isPlotObstructed = false; + private long lastKillTimestamp = 0; + private int previousCurrentPlotPestsCount = 0; + private int currentSlot = -1; + private boolean finishing = false; + + private final List killedPestsFrom = new ArrayList<>(); + + public static PestsDestroyer getInstance() { + if (instance == null) { + instance = new PestsDestroyer(); + } + return instance; + } + + @Override + public String getName() { + return "Pests Destroyer"; + } + + @Override + public boolean isRunning() { + return enabled || preparing; + } + + @Override + public boolean shouldPauseMacroExecution() { + return true; + } + + @Override + public boolean shouldStartAtMacroStart() { + return false; + } + + @Override + public void start() { + if (enabled) { + return; + } + gotRangeOfVacuum = false; + isPlotObstructed = false; + preparing = true; + lastKillTimestamp = 0; + if (MacroHandler.getInstance().isMacroToggled()) { + MacroHandler.getInstance().pauseMacro(); + MacroHandler.getInstance().getCurrentMacro().ifPresent(am -> am.setSavedState(Optional.empty())); + KeyBindUtils.stopMovement(); + } + escapeState = EscapeState.NONE; + rotationState = RotationState.NONE; + state = States.IDLE; + killedEntities.clear(); + killedPestsFrom.clear(); + Multithreading.schedule(() -> { + if (!preparing) { + return; + } + enabled = true; + preparing = false; + LogUtils.sendWarning("[Pests Destroyer] Starting killing shitters!"); + if (FarmHelperConfig.sendWebhookLogWhenPestDestroyerStartsStops) { + LogUtils.webhookLog("[Pests Destroyer]\\nStarting killing shitters!"); + } + }, MacroHandler.getInstance().isMacroToggled() ? (800 + (long) (Math.random() * 500)) : 0, TimeUnit.MILLISECONDS); + IFeature.super.start(); + } + + @Override + public void stop() { + if (enabled || preparing) { + LogUtils.sendWarning("[Pests Destroyer] Stopping!"); + if (FarmHelperConfig.sendWebhookLogWhenPestDestroyerStartsStops) { + LogUtils.webhookLog("[Pests Destroyer]\\nStopping!"); + } + if (GameStateHandler.getInstance().getPestsCount() == 0) { + pestsLocations.clear(); + } + } + PlayerUtils.closeScreen(); + currentEntityTarget = Optional.empty(); + resetFireworkInfo(); + preTpBlockPos = Optional.empty(); + delayBetweenBackTaps.reset(); + delayBetweenFireworks.reset(); + delayClock.reset(); + stuckClock.reset(); + preparing = false; + enabled = false; + isPlotObstructed = false; + lastFireworkTime = 0; + getLocationTries = 0; + flyPathfinderTries = 0; + state = States.IDLE; + FlyPathFinderExecutor.getInstance().stop(); + KeyBindUtils.stopMovement(); + finishing = false; + currentSlot = -1; + IFeature.super.stop(); + } + + @Override + public void resetStatesAfterMacroDisabled() { + stop(); + gotRangeOfVacuum = false; + if (!FarmHelperConfig.pestsDestroyerAfkInfiniteMode) { + return; + } + FarmHelperConfig.pestsDestroyerAfkInfiniteMode = false; + LogUtils.sendWarning("[Pests Destroyer] AFK Mode has been disabled"); + } + + @Override + public boolean isToggled() { + return FarmHelperConfig.enablePestsDestroyer; + } + + @Override + public boolean shouldCheckForFailsafes() { + return escapeState == EscapeState.NONE && + state != States.TELEPORT_TO_PLOT && + state != States.WAIT_FOR_TP && + state != States.CHECKING_PLOT && + state != States.CHECKING_SPAWN && + state != States.GET_LOCATION; + } + + @SubscribeEvent + public void onKeyInput(InputEvent.KeyInputEvent event) { + if (!FarmHelperConfig.pestsDestroyerAfkInfiniteMode) { + return; + } + if (Keyboard.getEventKeyState() && Keyboard.getEventKey() == Keyboard.KEY_ESCAPE) { + LogUtils.sendWarning("[Pests Destroyer] Disabling Pests Destroyer AFK Infinite Mode!"); + stop(); + FarmHelperConfig.pestsDestroyerAfkInfiniteMode = false; } + } - @Override - public void start() { - if (enabled) return; - gotRangeOfVacuum = false; - isPlotObstructed = false; - preparing = true; - lastKillTimestamp = 0; - if (MacroHandler.getInstance().isMacroToggled()) { - MacroHandler.getInstance().pauseMacro(); - MacroHandler.getInstance().getCurrentMacro().ifPresent(am -> am.setSavedState(Optional.empty())); - KeyBindUtils.stopMovement(); - } - escapeState = EscapeState.NONE; - rotationState = RotationState.NONE; - state = States.IDLE; - killedEntities.clear(); - killedPestsFrom.clear(); - Multithreading.schedule(() -> { - if (!preparing) return; - enabled = true; - preparing = false; - LogUtils.sendWarning("[Pests Destroyer] Starting killing shitters!"); - if (FarmHelperConfig.sendWebhookLogWhenPestDestroyerStartsStops) { - LogUtils.webhookLog("[Pests Destroyer]\\nStarting killing shitters!"); - } - }, MacroHandler.getInstance().isMacroToggled() ? (800 + (long) (Math.random() * 500)) : 0, TimeUnit.MILLISECONDS); - IFeature.super.start(); + @SubscribeEvent + public void onTickAFKMode(TickEvent.ClientTickEvent event) { + if (event.phase == TickEvent.Phase.END) { + return; + } + if (mc.thePlayer == null || mc.theWorld == null) { + return; + } + if (!FarmHelperConfig.pestsDestroyerAfkInfiniteMode) { + return; + } + if (MacroHandler.getInstance().isMacroToggled()) { + return; + } + if (!isToggled()) { + return; + } + if (isRunning()) { + return; } - @Override - public void stop() { - if (enabled || preparing) { - LogUtils.sendWarning("[Pests Destroyer] Stopping!"); - if (FarmHelperConfig.sendWebhookLogWhenPestDestroyerStartsStops) { - LogUtils.webhookLog("[Pests Destroyer]\\nStopping!"); - } - if (GameStateHandler.getInstance().getPestsCount() == 0) { - pestsLocations.clear(); - } - } - PlayerUtils.closeScreen(); - currentEntityTarget = Optional.empty(); - resetFireworkInfo(); - preTpBlockPos = Optional.empty(); - delayBetweenBackTaps.reset(); - delayBetweenFireworks.reset(); - delayClock.reset(); - stuckClock.reset(); - preparing = false; - enabled = false; - isPlotObstructed = false; - lastFireworkTime = 0; - getLocationTries = 0; - flyPathfinderTries = 0; - state = States.IDLE; - FlyPathFinderExecutor.getInstance().stop(); - KeyBindUtils.stopMovement(); - IFeature.super.stop(); + if (canEnableMacro(true)) { + start(); } + } + + public boolean canEnableMacro() { + return canEnableMacro(false); + } - @Override - public void resetStatesAfterMacroDisabled() { - stop(); - gotRangeOfVacuum = false; - if (!FarmHelperConfig.pestsDestroyerAfkInfiniteMode) return; + public boolean canEnableMacro(boolean manually) { + if (!isToggled()) { + return false; + } + if (isRunning()) { + return false; + } + if (!GameStateHandler.getInstance().inGarden()) { + return false; + } + if (!MacroHandler.getInstance().isMacroToggled() && !manually) { + return false; + } + if (!FailsafeManager.getInstance().getEmergencyQueue().isEmpty()) { + return false; + } + if (FailsafeManager.getInstance().triggeredFailsafe.isPresent()) { + return false; + } + if (enabled || preparing) { + return false; + } + if (GameStateHandler.getInstance().getPestsCount() < FarmHelperConfig.startKillingPestsAt && !manually || (manually + && GameStateHandler.getInstance().getPestsCount() == 0)) { + return false; + } + if (!manually && FarmHelperConfig.pausePestsDestroyerDuringJacobsContest && GameStateHandler.getInstance().inJacobContest()) { + LogUtils.sendError("[Pests Destroyer] Pests Destroyer won't activate during Jacob's Contest!"); + return false; + } + if (!mc.thePlayer.capabilities.allowFlying) { + LogUtils.sendError("[Pests Destroyer] You need to be able to fly!"); + if (FarmHelperConfig.pestsDestroyerAfkInfiniteMode) { + LogUtils.sendWarning("[Pests Destroyer] Disabling Pests Destroyer AFK Infinite Mode!"); FarmHelperConfig.pestsDestroyerAfkInfiniteMode = false; - LogUtils.sendWarning("[Pests Destroyer] AFK Mode has been disabled"); + } + return false; } + return true; + } - @Override - public boolean isToggled() { - return FarmHelperConfig.enablePestsDestroyer; + @SubscribeEvent + public void onTickExecute(TickEvent.ClientTickEvent event) { + if (mc.thePlayer == null || mc.theWorld == null) { + return; } - - @Override - public boolean shouldCheckForFailsafes() { - return escapeState == EscapeState.NONE && - state != States.TELEPORT_TO_PLOT && - state != States.WAIT_FOR_TP && - state != States.CHECKING_PLOT && - state != States.CHECKING_SPAWN && - state != States.GET_LOCATION; + if (mc.currentScreen == null && checkedThisGui) { + checkedThisGui = false; } - - @SubscribeEvent - public void onKeyInput(InputEvent.KeyInputEvent event) { - if (!FarmHelperConfig.pestsDestroyerAfkInfiniteMode) return; - if (Keyboard.getEventKeyState() && Keyboard.getEventKey() == Keyboard.KEY_ESCAPE) { - LogUtils.sendWarning("[Pests Destroyer] Disabling Pests Destroyer AFK Infinite Mode!"); - stop(); - FarmHelperConfig.pestsDestroyerAfkInfiniteMode = false; + if (!gotRangeOfVacuum && (isToggled() || PestsDestroyerOnTheTrack.getInstance().isToggled())) { + Slot vacuumSlot = InventoryUtils.getSlotOfItemInInventory("Vacuum"); + if (vacuumSlot != null) { + ItemStack vacuumItem = vacuumSlot.getStack(); + for (Map.Entry vacuumRange : this.vacuumRange.entrySet()) { + if (vacuumItem.getDisplayName().contains(vacuumRange.getKey())) { + currentVacuumRange = vacuumRange.getValue(); + gotRangeOfVacuum = true; + LogUtils.sendDebug("[Pests Destroyer] Found vacuum range: " + currentVacuumRange); + break; + } } + } + } + if (!isToggled()) { + return; + } + if (event.phase != TickEvent.Phase.END) { + return; + } + if (!GameStateHandler.getInstance().inGarden() && escapeState == EscapeState.NONE) { + return; + } + if (!enabled) { + return; + } + if (!FailsafeManager.getInstance().getEmergencyQueue().isEmpty()) { + return; + } + if (FailsafeManager.getInstance().triggeredFailsafe.isPresent()) { + stop(); + return; } - @SubscribeEvent - public void onTickAFKMode(TickEvent.ClientTickEvent event) { - if (event.phase == TickEvent.Phase.END) return; - if (mc.thePlayer == null || mc.theWorld == null) return; - if (!FarmHelperConfig.pestsDestroyerAfkInfiniteMode) return; - if (MacroHandler.getInstance().isMacroToggled()) return; - if (!isToggled()) return; - if (isRunning()) return; + if (stuckClock.isScheduled() && stuckClock.passed()) { + LogUtils.sendWarning( + "[Pests Destroyer] The player is struggling killing pest for 5 minutes, will do a quick Garden -> Hub -> Garden teleport."); + LogUtils.sendFailsafeMessage("[Pests Destroyer] Couldn't kill pest for 5 minutes, will do a quick Garden -> Hub -> Garden teleport.", true); + escapeState = EscapeState.GO_TO_HUB; + KeyBindUtils.stopMovement(); + delayClock.schedule(300); + stuckClock.reset(); + return; + } - if (canEnableMacro(true)) { - start(); - } + if (delayClock.isScheduled() && !delayClock.passed()) { + return; } - public boolean canEnableMacro() { - return canEnableMacro(false); + LogUtils.sendDebug("[Pests Destroyer] State: " + state); + + if (escapeState != EscapeState.NONE) { + if (stuckClock.isScheduled()) { + stuckClock.reset(); + } + if (RotationHandler.getInstance().isRotating()) { + RotationHandler.getInstance().reset(); + } + KeyBindUtils.stopMovement(); + switch (escapeState) { + case GO_TO_HUB: + if (isInventoryOpen()) { + break; + } + if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.HUB) { + escapeState = EscapeState.GO_TO_GARDEN; + delayClock.schedule((long) (5_500 + Math.random() * 3_500)); + break; + } + if (GameStateHandler.getInstance().inGarden()) { + mc.thePlayer.sendChatMessage("/hub"); + escapeState = EscapeState.GO_TO_GARDEN; + delayClock.schedule((long) (1_800 + Math.random() * 1_000)); + } + if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.TELEPORTING) { + delayClock.schedule((long) (500 + Math.random() * 500)); + break; + } + if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.LOBBY) { + escapeState = EscapeState.GO_TO_HUB; + mc.thePlayer.sendChatMessage("/skyblock"); + delayClock.schedule((long) (5_000 + Math.random() * 1_500)); + break; + } + break; + case GO_TO_GARDEN: + if (isInventoryOpen()) { + break; + } + if (GameStateHandler.getInstance().inGarden()) { + escapeState = EscapeState.GO_TO_HUB; + delayClock.schedule((long) (2_500 + Math.random() * 1_500)); + break; + } + if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.HUB) { + escapeState = EscapeState.RESUME_MACRO; + MacroHandler.getInstance().triggerWarpGarden(true, false); + delayClock.schedule((long) (2_500 + Math.random() * 1_500)); + break; + } + if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.TELEPORTING) { + delayClock.schedule((long) (500 + Math.random() * 500)); + break; + } + if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.LOBBY) { + escapeState = EscapeState.GO_TO_HUB; + mc.thePlayer.sendChatMessage("/skyblock"); + delayClock.schedule((long) (5_000 + Math.random() * 1_500)); + break; + } + break; + case RESUME_MACRO: + if (isInventoryOpen()) { + break; + } + if (GameStateHandler.getInstance().inGarden()) { + escapeState = EscapeState.NONE; + state = States.IDLE; + cantReachPest = 0; + delayClock.schedule((long) (1_000 + Math.random() * 500)); + LogUtils.sendDebug("[Pests Destroyer] Came back to Garden!"); + break; + } + if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.HUB) { + escapeState = EscapeState.RESUME_MACRO; + MacroHandler.getInstance().triggerWarpGarden(true, false); + delayClock.schedule((long) (2_500 + Math.random() * 1_500)); + break; + } + if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.TELEPORTING) { + delayClock.schedule((long) (500 + Math.random() * 500)); + break; + } + if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.LOBBY) { + escapeState = EscapeState.GO_TO_HUB; + mc.thePlayer.sendChatMessage("/skyblock"); + delayClock.schedule((long) (5_000 + Math.random() * 1_500)); + break; + } + break; + } + return; } - public boolean canEnableMacro(boolean manually) { - if (!isToggled()) return false; - if (isRunning()) return false; - if (!GameStateHandler.getInstance().inGarden()) return false; - if (!MacroHandler.getInstance().isMacroToggled() && !manually) return false; - if (!FailsafeManager.getInstance().getEmergencyQueue().isEmpty()) return false; - if (FailsafeManager.getInstance().triggeredFailsafe.isPresent()) return false; - if (enabled || preparing) return false; - if (GameStateHandler.getInstance().getPestsCount() < FarmHelperConfig.startKillingPestsAt && !manually || (manually && GameStateHandler.getInstance().getPestsCount() == 0)) - return false; - if (!manually && FarmHelperConfig.pausePestsDestroyerDuringJacobsContest && GameStateHandler.getInstance().inJacobContest()) { - LogUtils.sendError("[Pests Destroyer] Pests Destroyer won't activate during Jacob's Contest!"); - return false; + switch (state) { + case IDLE: + ItemStack currentItem = mc.thePlayer.getHeldItem(); + if (GameStateHandler.getInstance().getPestsCount() == 0) { + if (isInventoryOpen()) { + return; + } +// finishMacro(); + state = States.FINISH; + return; + } + if (getVacuum(currentItem)) { + return; + } + state = States.SWAP_ARMOR; + delayClock.schedule((long) (200 + Math.random() * 200)); + break; + case SWAP_ARMOR: + if (FarmHelperConfig.pestSwapArmorBefore) { + currentSlot = FarmHelperConfig.pestArmorSlot0; + if (finishing) { + currentSlot = FarmHelperConfig.pestArmorSlot1; + } + AutoWardrobe.instance.swapTo(currentSlot); } - if (!mc.thePlayer.capabilities.allowFlying) { - LogUtils.sendError("[Pests Destroyer] You need to be able to fly!"); - if (FarmHelperConfig.pestsDestroyerAfkInfiniteMode) { - LogUtils.sendWarning("[Pests Destroyer] Disabling Pests Destroyer AFK Infinite Mode!"); - FarmHelperConfig.pestsDestroyerAfkInfiniteMode = false; + state = States.ARMOR_SWAP_VERIFY; + break; + case ARMOR_SWAP_VERIFY: + if (AutoWardrobe.instance.isRunning()) { + return; + } + if (finishing) { + state = States.FINISH; + } else { + if (needToUpdatePlots || PlotUtils.needToUpdatePlots()) { + state = States.OPEN_DESK; + } else { + if (FarmHelperConfig.dontTeleportToPlots) { + state = States.GET_CLOSEST_PLOT; + } else { + state = States.TELEPORT_TO_PLOT; } - return false; + } } - return true; - } + break; + case OPEN_DESK: + if (isInventoryOpen()) { + break; + } + mc.thePlayer.sendChatMessage("/desk"); + state = States.OPEN_PLOTS; + delayClock.schedule((long) (FarmHelperConfig.pestAdditionalGUIDelay + 500 + Math.random() * 500)); + break; + case OPEN_PLOTS: + String chestName = InventoryUtils.getInventoryName(); + if (mc.currentScreen == null) { + delayClock.schedule((long) (FarmHelperConfig.pestAdditionalGUIDelay + 300 + Math.random() * 300)); + break; + } + if (!InventoryUtils.isInventoryLoaded()) { + break; + } + if (chestName == null || !chestName.equals("Desk")) { + break; + } + Slot configurePlots = InventoryUtils.getSlotOfItemInContainer("Configure Plots"); + if (configurePlots == null) { + break; + } + state = States.WAIT_FOR_INFO; + InventoryUtils.clickContainerSlot(configurePlots.slotNumber, InventoryUtils.ClickType.LEFT, InventoryUtils.ClickMode.PICKUP); + delayClock.schedule((long) (FarmHelperConfig.pestAdditionalGUIDelay + 500 + Math.random() * 500)); + break; + case WAIT_FOR_INFO: + break; + case TELEPORT_TO_PLOT: + PlotUtils.Plot plot; + if (FarmHelperConfig.dontTeleportToPlots) { + delayClock.schedule(1_000 + Math.random() * 500); + MacroHandler.getInstance().triggerWarpGarden(true, false); + state = States.CHECKING_SPAWN; + return; + } else { + plot = getClosestPlot(); + } + if (plot == null) { + state = States.GO_BACK; + delayClock.schedule((long) (500 + Math.random() * 500)); + return; + } + if (GameStateHandler.getInstance().getCurrentPlot() == plot.number && BlockUtils.canFlyHigher(8)) { + state = States.GET_LOCATION; + break; + } + String plotNumber = plot.name; + preTpBlockPos = Optional.of(mc.thePlayer.getPosition()); + mc.thePlayer.sendChatMessage("/tptoplot " + plotNumber); + state = States.WAIT_FOR_TP; + delayClock.schedule((long) (900 + Math.random() * 500)); + break; + case WAIT_FOR_TP: + if (!preTpBlockPos.isPresent()) { + state = States.IDLE; + break; + } + if (mc.thePlayer.getPosition().equals(preTpBlockPos.get())) { + break; + } + state = States.CHECKING_PLOT; + delayClock.schedule((long) (200 + Math.random() * 200)); + break; + case CHECKING_PLOT: + if (isInventoryOpenDelayed()) { + break; + } + KeyBindUtils.stopMovement(); - @SubscribeEvent - public void onTickExecute(TickEvent.ClientTickEvent event) { - if (mc.thePlayer == null || mc.theWorld == null) return; - if (mc.currentScreen == null && checkedThisGui) { - checkedThisGui = false; - } - if (!gotRangeOfVacuum && (isToggled() || PestsDestroyerOnTheTrack.getInstance().isToggled())) { - Slot vacuumSlot = InventoryUtils.getSlotOfItemInInventory("Vacuum"); - if (vacuumSlot != null) { - ItemStack vacuumItem = vacuumSlot.getStack(); - for (Map.Entry vacuumRange : this.vacuumRange.entrySet()) { - if (vacuumItem.getDisplayName().contains(vacuumRange.getKey())) { - currentVacuumRange = vacuumRange.getValue(); - gotRangeOfVacuum = true; - LogUtils.sendDebug("[Pests Destroyer] Found vacuum range: " + currentVacuumRange); - break; - } - } - } + if (PlayerUtils.isPlayerSuffocating() || !BlockUtils.canFlyHigher(5)) { + LogUtils.sendWarning("[Pests Destroyer] The player is suffocating and/or it can't fly higher. Going back to spawnpoint."); + delayClock.schedule(1_000 + Math.random() * 500); + MacroHandler.getInstance().triggerWarpGarden(true, false); + isPlotObstructed = true; + state = States.CHECKING_SPAWN; + return; } - if (!isToggled()) return; - if (event.phase != TickEvent.Phase.END) return; - if (!GameStateHandler.getInstance().inGarden() && escapeState == EscapeState.NONE) return; - if (!enabled) return; - if (!FailsafeManager.getInstance().getEmergencyQueue().isEmpty()) return; - if (FailsafeManager.getInstance().triggeredFailsafe.isPresent()) { - stop(); - return; + state = States.GET_LOCATION; + break; + case CHECKING_SPAWN: + if (MacroHandler.getInstance().isTeleporting()) { + return; } + if (PlayerUtils.isPlayerSuffocating() || !BlockUtils.canFlyHigher(5)) { + LogUtils.sendError( + "[Pests Destroyer] Your spawnpoint is obstructed! Make sure there is no block above your spawnpoint! Disabling Pests Destroyer!"); + stop(); + FarmHelperConfig.enablePestsDestroyer = false; +// finishMacro(); + state = States.FINISH; + } else { + state = States.GET_CLOSEST_PLOT; + LogUtils.sendDebug("[Pests Destroyer] Spawnpoint is not obstructed"); + } + break; + case GET_CLOSEST_PLOT: + if (isInventoryOpenDelayed()) { + break; + } - if (stuckClock.isScheduled() && stuckClock.passed()) { - LogUtils.sendWarning("[Pests Destroyer] The player is struggling killing pest for 5 minutes, will do a quick Garden -> Hub -> Garden teleport."); - LogUtils.sendFailsafeMessage("[Pests Destroyer] Couldn't kill pest for 5 minutes, will do a quick Garden -> Hub -> Garden teleport.", true); - escapeState = EscapeState.GO_TO_HUB; - KeyBindUtils.stopMovement(); - delayClock.schedule(300); - stuckClock.reset(); - return; + PlotUtils.Plot closestPlot = getClosestPlot(); + + if (closestPlot == null) { + LogUtils.sendError("[Pests Destroyer] Couldn't find closest plot!"); + state = States.GET_LOCATION; + return; } - if (delayClock.isScheduled() && !delayClock.passed()) return; + double distance = Math.sqrt(mc.thePlayer.getDistanceSq(PlotUtils.getPlotCenter(closestPlot.number))); - LogUtils.sendDebug("[Pests Destroyer] State: " + state); + this.closestPlot = Optional.of(closestPlot); - if (escapeState != EscapeState.NONE) { - if (stuckClock.isScheduled()) { - stuckClock.reset(); - } - if (RotationHandler.getInstance().isRotating()) { - RotationHandler.getInstance().reset(); - } - KeyBindUtils.stopMovement(); - switch (escapeState) { - case GO_TO_HUB: - if (isInventoryOpen()) break; - if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.HUB) { - escapeState = EscapeState.GO_TO_GARDEN; - delayClock.schedule((long) (5_500 + Math.random() * 3_500)); - break; - } - if (GameStateHandler.getInstance().inGarden()) { - mc.thePlayer.sendChatMessage("/hub"); - escapeState = EscapeState.GO_TO_GARDEN; - delayClock.schedule((long) (1_800 + Math.random() * 1_000)); - } - if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.TELEPORTING) { - delayClock.schedule((long) (500 + Math.random() * 500)); - break; - } - if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.LOBBY) { - escapeState = EscapeState.GO_TO_HUB; - mc.thePlayer.sendChatMessage("/skyblock"); - delayClock.schedule((long) (5_000 + Math.random() * 1_500)); - break; - } - break; - case GO_TO_GARDEN: - if (isInventoryOpen()) break; - if (GameStateHandler.getInstance().inGarden()) { - escapeState = EscapeState.GO_TO_HUB; - delayClock.schedule((long) (2_500 + Math.random() * 1_500)); - break; - } - if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.HUB) { - escapeState = EscapeState.RESUME_MACRO; - MacroHandler.getInstance().triggerWarpGarden(true, false); - delayClock.schedule((long) (2_500 + Math.random() * 1_500)); - break; - } - if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.TELEPORTING) { - delayClock.schedule((long) (500 + Math.random() * 500)); - break; - } - if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.LOBBY) { - escapeState = EscapeState.GO_TO_HUB; - mc.thePlayer.sendChatMessage("/skyblock"); - delayClock.schedule((long) (5_000 + Math.random() * 1_500)); - break; - } - break; - case RESUME_MACRO: - if (isInventoryOpen()) break; - if (GameStateHandler.getInstance().inGarden()) { - escapeState = EscapeState.NONE; - state = States.IDLE; - cantReachPest = 0; - delayClock.schedule((long) (1_000 + Math.random() * 500)); - LogUtils.sendDebug("[Pests Destroyer] Came back to Garden!"); - break; - } - if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.HUB) { - escapeState = EscapeState.RESUME_MACRO; - MacroHandler.getInstance().triggerWarpGarden(true, false); - delayClock.schedule((long) (2_500 + Math.random() * 1_500)); - break; - } - if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.TELEPORTING) { - delayClock.schedule((long) (500 + Math.random() * 500)); - break; - } - if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.LOBBY) { - escapeState = EscapeState.GO_TO_HUB; - mc.thePlayer.sendChatMessage("/skyblock"); - delayClock.schedule((long) (5_000 + Math.random() * 1_500)); - break; - } - break; - } - return; + if (FarmHelperConfig.dontTeleportToPlots) { + if (PlayerUtils.isPlayerSuffocating() || !BlockUtils.canFlyHigher(3)) { + state = States.TELEPORT_TO_PLOT; + LogUtils.sendWarning("[Pests Destroyer] The player is suffocating and/or it can't fly higher. Forcing going back to spawnpoint."); + } else { + state = States.FLY_TO_THE_CLOSEST_PLOT; + } + break; } - switch (state) { - case IDLE: - ItemStack currentItem = mc.thePlayer.getHeldItem(); - if (GameStateHandler.getInstance().getPestsCount() == 0) { - if (isInventoryOpen()) return; - finishMacro(); - return; - } - if (getVacuum(currentItem)) return; - if (needToUpdatePlots || PlotUtils.needToUpdatePlots()) { - state = States.OPEN_DESK; - } else { - if (FarmHelperConfig.dontTeleportToPlots) { - state = States.GET_CLOSEST_PLOT; - } else { - state = States.TELEPORT_TO_PLOT; - } - } - delayClock.schedule((long) (200 + Math.random() * 200)); - break; - case OPEN_DESK: - if (isInventoryOpen()) break; - mc.thePlayer.sendChatMessage("/desk"); - state = States.OPEN_PLOTS; - delayClock.schedule((long) (FarmHelperConfig.pestAdditionalGUIDelay + 500 + Math.random() * 500)); - break; - case OPEN_PLOTS: - String chestName = InventoryUtils.getInventoryName(); - if (mc.currentScreen == null) { - delayClock.schedule((long) (FarmHelperConfig.pestAdditionalGUIDelay + 300 + Math.random() * 300)); - break; - } - if (!InventoryUtils.isInventoryLoaded()) break; - if (chestName == null || !chestName.equals("Desk")) { - break; - } - Slot configurePlots = InventoryUtils.getSlotOfItemInContainer("Configure Plots"); - if (configurePlots == null) { - break; - } - state = States.WAIT_FOR_INFO; - InventoryUtils.clickContainerSlot(configurePlots.slotNumber, InventoryUtils.ClickType.LEFT, InventoryUtils.ClickMode.PICKUP); - delayClock.schedule((long) (FarmHelperConfig.pestAdditionalGUIDelay + 500 + Math.random() * 500)); - break; - case WAIT_FOR_INFO: - break; - case TELEPORT_TO_PLOT: - PlotUtils.Plot plot; - if (FarmHelperConfig.dontTeleportToPlots) { - delayClock.schedule(1_000 + Math.random() * 500); - MacroHandler.getInstance().triggerWarpGarden(true, false); - state = States.CHECKING_SPAWN; - return; - } else { - plot = getClosestPlot(); - } - if (plot == null) { - state = States.GO_BACK; - delayClock.schedule((long) (500 + Math.random() * 500)); - return; - } - if (GameStateHandler.getInstance().getCurrentPlot() == plot.number && BlockUtils.canFlyHigher(8)) { - state = States.GET_LOCATION; - break; - } - String plotNumber = plot.name; - preTpBlockPos = Optional.of(mc.thePlayer.getPosition()); - mc.thePlayer.sendChatMessage("/tptoplot " + plotNumber); - state = States.WAIT_FOR_TP; - delayClock.schedule((long) (900 + Math.random() * 500)); - break; - case WAIT_FOR_TP: - if (!preTpBlockPos.isPresent()) { - state = States.IDLE; - break; - } - if (mc.thePlayer.getPosition().equals(preTpBlockPos.get())) { - break; - } - state = States.CHECKING_PLOT; - delayClock.schedule((long) (200 + Math.random() * 200)); - break; - case CHECKING_PLOT: - if (isInventoryOpenDelayed()) break; - KeyBindUtils.stopMovement(); - - if (PlayerUtils.isPlayerSuffocating() || !BlockUtils.canFlyHigher(5)) { - LogUtils.sendWarning("[Pests Destroyer] The player is suffocating and/or it can't fly higher. Going back to spawnpoint."); - delayClock.schedule(1_000 + Math.random() * 500); - MacroHandler.getInstance().triggerWarpGarden(true, false); - isPlotObstructed = true; - state = States.CHECKING_SPAWN; - return; - } - state = States.GET_LOCATION; - break; - case CHECKING_SPAWN: - if (MacroHandler.getInstance().isTeleporting()) return; - - if (PlayerUtils.isPlayerSuffocating() || !BlockUtils.canFlyHigher(5)) { - LogUtils.sendError("[Pests Destroyer] Your spawnpoint is obstructed! Make sure there is no block above your spawnpoint! Disabling Pests Destroyer!"); - stop(); - FarmHelperConfig.enablePestsDestroyer = false; - finishMacro(); - } else { - state = States.GET_CLOSEST_PLOT; - LogUtils.sendDebug("[Pests Destroyer] Spawnpoint is not obstructed"); - } - break; - case GET_CLOSEST_PLOT: - if (isInventoryOpenDelayed()) break; - - PlotUtils.Plot closestPlot = getClosestPlot(); - - if (closestPlot == null) { - LogUtils.sendError("[Pests Destroyer] Couldn't find closest plot!"); - state = States.GET_LOCATION; - return; - } - - double distance = Math.sqrt(mc.thePlayer.getDistanceSq(PlotUtils.getPlotCenter(closestPlot.number))); - - this.closestPlot = Optional.of(closestPlot); - - if (FarmHelperConfig.dontTeleportToPlots) { - if (PlayerUtils.isPlayerSuffocating() || !BlockUtils.canFlyHigher(3)) { - state = States.TELEPORT_TO_PLOT; - LogUtils.sendWarning("[Pests Destroyer] The player is suffocating and/or it can't fly higher. Forcing going back to spawnpoint."); - } else { - state = States.FLY_TO_THE_CLOSEST_PLOT; - } - break; - } - - if (distance > 150 && !isPlotObstructed) { - state = States.TELEPORT_TO_PLOT; - } else { - state = States.FLY_TO_THE_CLOSEST_PLOT; - } - delayClock.schedule((long) (500 + Math.random() * 500)); - break; - case FLY_TO_THE_CLOSEST_PLOT: - if (MacroHandler.getInstance().isTeleporting()) return; - if (isInventoryOpenDelayed()) break; - - if (!this.closestPlot.isPresent()) { - LogUtils.sendError("[Pests Destroyer] Couldn't find closest plot!"); - state = States.GET_LOCATION; - return; - } - - BlockPos plotCenter = PlotUtils.getPlotCenter(this.closestPlot.get().number); - - if (getClosestPest() != null) { - KeyBindUtils.stopMovement(); - state = States.FIND_PEST; - break; - } - - if ((mc.thePlayer.onGround || !flyDelay.passed()) && mc.thePlayer.capabilities.allowFlying && !mc.thePlayer.capabilities.isFlying) { - fly(); - break; - } - - if (mc.thePlayer.getDistance(plotCenter.getX(), mc.thePlayer.posY, plotCenter.getZ()) < 15) { - state = States.GET_LOCATION; - KeyBindUtils.stopMovement(); - FlyPathFinderExecutor.getInstance().stop(); - break; - } - - if (!FlyPathFinderExecutor.getInstance().isRunning()) { - FlyPathFinderExecutor.getInstance().setSprinting(true); - FlyPathFinderExecutor.getInstance().setDontRotate(false); - FlyPathFinderExecutor.getInstance().setUseAOTV(InventoryUtils.hasItemInHotbar("Aspect of the Void", "Aspect of the End")); - FlyPathFinderExecutor.getInstance().findPath(new Vec3(plotCenter.getX(), 80, plotCenter.getZ()), true, true); - } - break; - case GET_LOCATION: - if (GameStateHandler.getInstance().getPestsCount() == 0) { - state = States.GO_BACK; - return; - } - if (isInventoryOpenDelayed()) break; - ItemStack currentItem2 = mc.thePlayer.getHeldItem(); - if (getVacuum(currentItem2)) return; - - if (getClosestPest() != null) { - FlyPathFinderExecutor.getInstance().stop(); - state = States.FIND_PEST; - break; - } - - if (FlyPathFinderExecutor.getInstance().isRunning()) { - return; - } - - if (!mc.thePlayer.capabilities.isFlying) { - fly(); - break; - } - if (hasBlocksAround()) { - KeyBindUtils.holdThese(mc.gameSettings.keyBindJump); - break; - } else { - if (mc.gameSettings.keyBindJump.isKeyDown()) { - KeyBindUtils.stopMovement(); - } - } - - if (getLocationTries > 2) { - PlotUtils.Plot currentPlot = getClosestPlot(); - - if (!isNearPlotCenter()) { - if (currentPlot != null) { - BlockPos plotCenter2 = PlotUtils.getPlotCenter(currentPlot.number); - FlyPathFinderExecutor.getInstance().setSprinting(FarmHelperConfig.sprintWhileFlying); - FlyPathFinderExecutor.getInstance().setDontRotate(false); - FlyPathFinderExecutor.getInstance().setUseAOTV(InventoryUtils.hasItemInHotbar("Aspect of the Void", "Aspect of the End")); - FlyPathFinderExecutor.getInstance().findPath(new Vec3(plotCenter2.getX(), 80, plotCenter2.getZ()), true, true); - LogUtils.sendDebug("[Pests Destroyer] Flying to plot center"); - } else { - LogUtils.sendWarning("[Pests Destroyer] Couldn't find closest plot!"); - state = States.GO_BACK; - } - break; - } - } - - resetFireworkInfo(); - lastFireworkTime = System.currentTimeMillis(); - MovingObjectPosition mop = mc.objectMouseOver; - if (RotationHandler.getInstance().isRotating()) break; - float yaw = -1; - Vec3 playerPos = mc.thePlayer.getPositionEyes(1); - for (float i = 0; i < 360; i += 10) { - Vec3 testRotation = AngleUtils.getVectorForRotation(0, i); - Vec3 lookVector = playerPos.addVector(testRotation.xCoord * 5, testRotation.yCoord * 5, testRotation.zCoord * 5); - MovingObjectPosition mop2 = mc.theWorld.rayTraceBlocks(playerPos, lookVector, false, true, false); - if (mop2 == null || mop2.typeOfHit != MovingObjectPosition.MovingObjectType.BLOCK) { - yaw = i; - break; - } - } - Rotation upRotation = new Rotation((float) (yaw + (Math.random() * 5 - 2.5)), (float) (-20 + (Math.random() * 6 - 4))); - if (mop != null && mop.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK && RotationHandler.getInstance().shouldRotate(upRotation, 10)) { - RotationHandler.getInstance().easeTo(new RotationConfiguration( - upRotation, - FarmHelperConfig.getRandomRotationTime(), - null - ).easeOutBack(true)); - delayClock.schedule(300); - break; - } - state = States.WAIT_FOR_LOCATION; - if (getLocationTries > 4) { - LogUtils.sendWarning("[Pests Destroyer] Couldn't find any firework location. Trying to fix it by sending /pq low."); - mc.thePlayer.sendChatMessage("/pq low"); - getLocationTries = 0; - } - KeyBindUtils.leftClick(); - getLocationTries++; - if (!stuckClock.isScheduled()) - stuckClock.schedule(1_000 * 60 * FarmHelperConfig.pestsKillerStuckTime); - delayClock.schedule(300); - break; - case WAIT_FOR_LOCATION: - if (isInventoryOpenDelayed()) break; - - if (RotationHandler.getInstance().isRotating()) return; - - if (getClosestPest() != null) { - state = States.FIND_PEST; - break; - } - - if (lastLocation != null && lastFireworkTime + 250 < System.currentTimeMillis()) { - Vec3 firework = calculateWaypoint(); - if (firework == null) { - LogUtils.sendDebug("[Pests Destroyer] Couldn't find any firework location. Looking for a firework."); - state = States.GET_LOCATION; - break; - } - if (mc.thePlayer.getDistance(firework.xCoord, firework.yCoord, firework.zCoord) < 2) { - int y = 150; - Block block = mc.theWorld.getBlockState(new BlockPos(firework.xCoord, y, firework.zCoord)).getBlock(); - Block[] blocksAround = new Block[]{ - mc.theWorld.getBlockState(new BlockPos(firework.xCoord + 1, y, firework.zCoord)).getBlock(), - mc.theWorld.getBlockState(new BlockPos(firework.xCoord - 1, y, firework.zCoord)).getBlock(), - mc.theWorld.getBlockState(new BlockPos(firework.xCoord, y, firework.zCoord + 1)).getBlock(), - mc.theWorld.getBlockState(new BlockPos(firework.xCoord, y, firework.zCoord - 1)).getBlock(), - block - }; - while (y > 90 && Arrays.stream(blocksAround).allMatch(b -> b.equals(Blocks.air))) { - y--; - } - y += 3; - FlyPathFinderExecutor.getInstance().setSprinting(false); - FlyPathFinderExecutor.getInstance().setDontRotate(true); - FlyPathFinderExecutor.getInstance().findPath(new Vec3(firework.xCoord, y, firework.zCoord), true, true); - LogUtils.sendWarning("[Pests Destroyer] Firework is too close to player. Flying to x: " + firework.xCoord + " y: " + y + " z: " + firework.zCoord); - break; - } - RotationHandler.getInstance().reset(); - state = States.FIND_PEST; - delayBetweenFireworks.schedule(3_000); - delayClock.schedule(300); - break; - } - if (System.currentTimeMillis() - lastFireworkTime > 6_000) { - state = States.GET_LOCATION; - break; - } - break; - case FIND_PEST: - if (isInventoryOpenDelayed()) break; - getLocationTries = 0; - if (GameStateHandler.getInstance().getPestsCount() == 0) { - RotationHandler.getInstance().reset(); - state = States.CHECK_ANOTHER_PEST; - return; - } - - Entity closestPest = getClosestPest(); - - if (closestPest == null) { - if (lastLocation == null) { - LogUtils.sendDebug("[Pests Destroyer] No firework location found. Looking for a firework."); - state = States.GET_LOCATION; - break; - } - - if (!FlyPathFinderExecutor.getInstance().isRunning()) { - Vec3 firework = calculateWaypoint(); - if (firework == null) { - LogUtils.sendDebug("[Pests Destroyer] Couldn't find any firework location. Looking for a firework."); - state = States.GET_LOCATION; - break; - } - if (mc.thePlayer.getDistance(firework.xCoord, firework.yCoord, firework.zCoord) < 2) { - state = States.GET_LOCATION; - break; - } - FlyPathFinderExecutor.getInstance().setSprinting(true); - FlyPathFinderExecutor.getInstance().setDontRotate(false); - FlyPathFinderExecutor.getInstance().setUseAOTV(InventoryUtils.hasItemInHotbar("Aspect of the Void", "Aspect of the End")); - FlyPathFinderExecutor.getInstance().findPath(firework, true, true); - } - break; - } - if (closestPest instanceof EntityArmorStand) { - Entity realEntity = PlayerUtils.getEntityCuttingOtherEntity(closestPest, (e) -> e instanceof EntityBat || e instanceof EntitySilverfish); - if (realEntity != null) { - closestPest = realEntity; - } - } - if (FlyPathFinderExecutor.getInstance().isRunning()) { - FlyPathFinderExecutor.getInstance().stop(); - } - - currentEntityTarget = Optional.of(closestPest); - - state = States.KILL_PEST; - cantReachPest = 0; - KeyBindUtils.stopMovement(); - if (!stuckClock.isScheduled()) - stuckClock.schedule(1_000 * 60 * FarmHelperConfig.pestsKillerStuckTime); - delayClock.schedule(300); - break; - case KILL_PEST: - if (isInventoryOpenDelayed()) break; - if (mc.thePlayer.posY < 67 && FlyPathFinderExecutor.getInstance().isRunning()) { - FlyPathFinderExecutor.getInstance().stop(); - RotationHandler.getInstance().reset(); - state = States.GET_LOCATION; - return; - } - if (!currentEntityTarget.isPresent()) { - FlyPathFinderExecutor.getInstance().stop(); - RotationHandler.getInstance().reset(); - state = States.CHECK_ANOTHER_PEST; - return; - } - Entity entity = currentEntityTarget.get(); - if (entity.isDead || killedEntities.contains(entity) || !mc.theWorld.loadedEntityList.contains(entity)) { - RotationHandler.getInstance().reset(); - state = States.CHECK_ANOTHER_PEST; - FlyPathFinderExecutor.getInstance().stop(); - return; - } - - double distance2 = mc.thePlayer.getDistance(entity.posX, entity.posY + entity.getEyeHeight(), entity.posZ); - double distanceXZ = mc.thePlayer.getDistance(entity.posX, mc.thePlayer.posY, entity.posZ); - - float vacuumMinRange = Math.max(currentVacuumRange - 2, 3); - if (FarmHelperConfig.pestsKillerTicksOfNotSeeingPestWhileAttacking > 0 - && (distanceXZ < 1.5 || distance2 <= Math.max(vacuumMinRange - 2, 10)) - && Math.abs(mc.thePlayer.motionX) < 0.1 - && Math.abs(mc.thePlayer.motionZ) < 0.1 - && !canEntityBeSeenIgnoreNonCollidable(entity)) { - cantReachPest++; - } - - if (cantReachPest >= FarmHelperConfig.pestsKillerTicksOfNotSeeingPestWhileAttacking) { - LogUtils.sendWarning("[Pests Destroyer] Can't reach the pest, will do a quick Garden -> Hub -> Garden teleport."); - escapeState = EscapeState.GO_TO_HUB; - KeyBindUtils.stopMovement(); - delayClock.schedule(300); - return; - } - - if (distance2 < vacuumMinRange) { - float targetVelocity = (float) (Math.abs(entity.motionX) + Math.abs(entity.motionZ)); - if (vacuumMinRange > 8 || targetVelocity < 0.15) { - if (FlyPathFinderExecutor.getInstance().isRunning()) { - FlyPathFinderExecutor.getInstance().stop(); - LogUtils.sendDebug("[Pests Destroyer] Stopping pathfinder because the pest is close enough"); - float playerVelocity = (float) (Math.abs(mc.thePlayer.motionX) + Math.abs(mc.thePlayer.motionZ)); - if (playerVelocity > 0.9) - KeyBindUtils.onTick(mc.gameSettings.keyBindBack); - } else { - float playerVelocity = (float) (Math.abs(mc.thePlayer.motionX) + Math.abs(mc.thePlayer.motionZ)); - if (playerVelocity > 0.15 && distanceXZ < 3) - KeyBindUtils.onTick(mc.gameSettings.keyBindBack); - } - } - if (rotationState != RotationState.CLOSE) { - rotationState = RotationState.CLOSE; - RotationHandler.getInstance().reset(); - } - if (!RotationHandler.getInstance().isRotating()) { - RotationHandler.getInstance().easeTo(new RotationConfiguration( - new Target(entity), - (long) (400 + Math.random() * 200), - null - ).followTarget(true)); - } - FlyPathFinderExecutor.getInstance().setUseAOTV(false); - ItemStack currentItem3 = mc.thePlayer.getHeldItem(); - if (getVacuum(currentItem3)) { - break; - } - KeyBindUtils.setKeyBindState(mc.gameSettings.keyBindUseItem, true); - } else { - if (rotationState != RotationState.FAR) { - FlyPathFinderExecutor.getInstance().stop(); - rotationState = RotationState.FAR; - RotationHandler.getInstance().reset(); - } - if (!FlyPathFinderExecutor.getInstance().isRunning()) { - double yAddition = Math.max(2.75, Math.min(currentVacuumRange - 5, 10)); - LogUtils.sendDebug("Should pathfind to: " + entity.posX + " " + yAddition + " " + entity.posZ); - FlyPathFinderExecutor.getInstance().setSprinting(FarmHelperConfig.sprintWhileFlying); - FlyPathFinderExecutor.getInstance().setUseAOTV(InventoryUtils.hasItemInHotbar("Aspect of the Void", "Aspect of the End")); - FlyPathFinderExecutor.getInstance().findPath(entity, true, true, (float) yAddition, true); - } - if (FlyPathFinderExecutor.getInstance().getState() == FlyPathFinderExecutor.State.FAILED - && mc.thePlayer.motionX == 0 && mc.thePlayer.motionZ == 0) { - flyPathfinderTries++; - } else { - flyPathfinderTries = 0; - } - if (flyPathfinderTries > 5) { - LogUtils.sendWarning("[Pests Destroyer] Couldn't pathfind to the pest. Flying from the spawnpoint."); - flyPathfinderTries = 0; - KeyBindUtils.stopMovement(); - delayClock.schedule(1_000 + Math.random() * 500); - MacroHandler.getInstance().triggerWarpGarden(true, false); - state = States.CHECKING_SPAWN; - return; - } - if (!RotationHandler.getInstance().isRotating()) { - RotationHandler.getInstance().easeTo(new RotationConfiguration( - new Target(entity).additionalY(-0.3f), - (long) (400 + Math.random() * 200), - null - )); - } - FlyPathFinderExecutor.getInstance().setUseAOTV(distanceXZ > vacuumMinRange && InventoryUtils.hasItemInHotbar("Aspect of the Void", "Aspect of the End")); - if (distance2 < currentVacuumRange && getVacuum(mc.thePlayer.getHeldItem())) { - break; - } - KeyBindUtils.setKeyBindState(mc.gameSettings.keyBindUseItem, distance2 < currentVacuumRange); - } - break; - case CHECK_ANOTHER_PEST: - if (previousCurrentPlotPestsCount == GameStateHandler.getInstance().getCurrentPlotPestsCount() && System.currentTimeMillis() - lastKillTimestamp < 2_000) - return; - - LogUtils.sendDebug(GameStateHandler.getInstance().getPestsCount() + " pest" + (GameStateHandler.getInstance().getPestsCount() == 1 ? "" : "s") + " left"); - if (GameStateHandler.getInstance().getPestsCount() == 0) { - state = States.GO_BACK; - delayClock.schedule((long) (500 + Math.random() * 500)); - break; - } - System.out.println("Curr plot pests: " + GameStateHandler.getInstance().getCurrentPlotPestsCount()); - isPlotObstructed = false; - Entity closestPest2 = getClosestPest(); - KeyBindUtils.stopMovement(); - if (closestPest2 != null) { - LogUtils.sendDebug("Found another pest"); - state = States.KILL_PEST; - currentEntityTarget = Optional.of(closestPest2); - delayClock.schedule(50 + (long) (Math.random() * 100)); - } else { - PlotUtils.Plot plotOpt = getClosestPlot(); - if (plotOpt != null) { - double distanceToPlot = Math.sqrt(mc.thePlayer.getDistanceSqToCenter(PlotUtils.getPlotCenter(plotOpt.number))); - LogUtils.sendDebug("Distance to plot: " + distanceToPlot); - if (distanceToPlot < 150 || FarmHelperConfig.dontTeleportToPlots) { - LogUtils.sendDebug("Going manually to another plot"); - state = States.GET_CLOSEST_PLOT; - delayClock.schedule(100 + (long) (Math.random() * 150)); - break; - } else { - LogUtils.sendDebug("Teleporting to plot"); - state = States.TELEPORT_TO_PLOT; - delayClock.schedule(400 + (long) (Math.random() * 400)); - } - } else { - state = States.GO_BACK; - delayClock.schedule(300 + (long) (Math.random() * 300)); - } - } - break; - case GO_BACK: - finishMacro(); - break; - } - } - - @Nullable - private Entity getClosestPest() { - Entity closestPest = null; - double closestDistance = Double.MAX_VALUE; - for (Entity entity : pestsLocations) { - double distance = mc.thePlayer.getDistanceToEntity(entity); - if (distance < closestDistance) { - closestDistance = distance; - closestPest = entity; - } + if (distance > 150 && !isPlotObstructed) { + state = States.TELEPORT_TO_PLOT; + } else { + state = States.FLY_TO_THE_CLOSEST_PLOT; + } + delayClock.schedule((long) (500 + Math.random() * 500)); + break; + case FLY_TO_THE_CLOSEST_PLOT: + if (MacroHandler.getInstance().isTeleporting()) { + return; + } + if (isInventoryOpenDelayed()) { + break; } - return closestPest; - } - public boolean getVacuum(ItemStack currentItem2) { - if (currentItem2 == null || !currentItem2.getDisplayName().contains("Vacuum")) { - int vacuum = InventoryUtils.getSlotIdOfItemInHotbar("Vacuum"); - if (vacuum == -1) { - LogUtils.sendError("[Pests Destroyer] Failed to find vacuum in hotbar!"); - state = States.GO_BACK; - FarmHelperConfig.enablePestsDestroyer = false; - finishMacro(); - return true; - } - mc.thePlayer.inventory.currentItem = vacuum; - delayClock.schedule((long) (200 + Math.random() * 200)); - return true; + if (!this.closestPlot.isPresent()) { + LogUtils.sendError("[Pests Destroyer] Couldn't find closest plot!"); + state = States.GET_LOCATION; + return; } - return false; - } - private boolean isInventoryOpenDelayed() { - if (mc.currentScreen != null) { - KeyBindUtils.stopMovement(); - delayClock.schedule(300 + (long) (Math.random() * 300)); - Multithreading.schedule(() -> { - if (mc.currentScreen != null) { - PlayerUtils.closeScreen(); - delayClock.schedule(100 + (long) (Math.random() * 200)); - } - }, (long) (200 + Math.random() * 100), TimeUnit.MILLISECONDS); - return true; + BlockPos plotCenter = PlotUtils.getPlotCenter(this.closestPlot.get().number); + + if (getClosestPest() != null) { + KeyBindUtils.stopMovement(); + state = States.FIND_PEST; + break; } - return false; - } - private boolean isInventoryOpen() { - if (mc.currentScreen != null) { - PlayerUtils.closeScreen(); - delayClock.schedule(500 + (long) (Math.random() * 500)); - return true; + if ((mc.thePlayer.onGround || !flyDelay.passed()) && mc.thePlayer.capabilities.allowFlying && !mc.thePlayer.capabilities.isFlying) { + fly(); + break; } - return false; - } + if (mc.thePlayer.getDistance(plotCenter.getX(), mc.thePlayer.posY, plotCenter.getZ()) < 15) { + state = States.GET_LOCATION; + KeyBindUtils.stopMovement(); + FlyPathFinderExecutor.getInstance().stop(); + break; + } - private void finishMacro() { - if (isInventoryOpen()) return; - if (FlyPathFinderExecutor.getInstance().isPathing()) { - FlyPathFinderExecutor.getInstance().stop(); + if (!FlyPathFinderExecutor.getInstance().isRunning()) { + FlyPathFinderExecutor.getInstance().setSprinting(true); + FlyPathFinderExecutor.getInstance().setDontRotate(false); + FlyPathFinderExecutor.getInstance().setUseAOTV(InventoryUtils.hasItemInHotbar("Aspect of the Void", "Aspect of the End")); + FlyPathFinderExecutor.getInstance().findPath(new Vec3(plotCenter.getX(), 80, plotCenter.getZ()), true, true); + } + break; + case GET_LOCATION: + if (GameStateHandler.getInstance().getPestsCount() == 0) { + state = States.GO_BACK; + return; + } + if (isInventoryOpenDelayed()) { + break; + } + ItemStack currentItem2 = mc.thePlayer.getHeldItem(); + if (getVacuum(currentItem2)) { + return; + } + + if (getClosestPest() != null) { + FlyPathFinderExecutor.getInstance().stop(); + state = States.FIND_PEST; + break; } - if (MacroHandler.getInstance().isMacroToggled()) { - stop(); - MacroHandler.getInstance().triggerWarpGarden(true, true, false); - delayClock.schedule(2_000 + Math.random() * 500); + + if (FlyPathFinderExecutor.getInstance().isRunning()) { + return; + } + + if (!mc.thePlayer.capabilities.isFlying) { + fly(); + break; + } + if (hasBlocksAround()) { + KeyBindUtils.holdThese(mc.gameSettings.keyBindJump); + break; } else { - stop(); + if (mc.gameSettings.keyBindJump.isKeyDown()) { + KeyBindUtils.stopMovement(); + } + } + + if (getLocationTries > 2) { + PlotUtils.Plot currentPlot = getClosestPlot(); + + if (!isNearPlotCenter()) { + if (currentPlot != null) { + BlockPos plotCenter2 = PlotUtils.getPlotCenter(currentPlot.number); + FlyPathFinderExecutor.getInstance().setSprinting(FarmHelperConfig.sprintWhileFlying); + FlyPathFinderExecutor.getInstance().setDontRotate(false); + FlyPathFinderExecutor.getInstance().setUseAOTV(InventoryUtils.hasItemInHotbar("Aspect of the Void", "Aspect of the End")); + FlyPathFinderExecutor.getInstance().findPath(new Vec3(plotCenter2.getX(), 80, plotCenter2.getZ()), true, true); + LogUtils.sendDebug("[Pests Destroyer] Flying to plot center"); + } else { + LogUtils.sendWarning("[Pests Destroyer] Couldn't find closest plot!"); + state = States.GO_BACK; + } + break; + } } - } - private boolean hasBlocksAround() { - Vec3 angle0 = AngleUtils.getVectorForRotation(0, mc.thePlayer.rotationYaw); - Vec3 angle90 = AngleUtils.getVectorForRotation(90, mc.thePlayer.rotationYaw); - Vec3 angle180 = AngleUtils.getVectorForRotation(180, mc.thePlayer.rotationYaw); - Vec3 angle270 = AngleUtils.getVectorForRotation(270, mc.thePlayer.rotationYaw); + resetFireworkInfo(); + lastFireworkTime = System.currentTimeMillis(); + MovingObjectPosition mop = mc.objectMouseOver; + if (RotationHandler.getInstance().isRotating()) { + break; + } + float yaw = -1; Vec3 playerPos = mc.thePlayer.getPositionEyes(1); - if (checkIfBlockExists(angle0, playerPos)) return true; - if (checkIfBlockExists(angle90, playerPos)) return true; - if (checkIfBlockExists(angle180, playerPos)) return true; - return checkIfBlockExists(angle270, playerPos); - } + for (float i = 0; i < 360; i += 10) { + Vec3 testRotation = AngleUtils.getVectorForRotation(0, i); + Vec3 lookVector = playerPos.addVector(testRotation.xCoord * 5, testRotation.yCoord * 5, testRotation.zCoord * 5); + MovingObjectPosition mop2 = mc.theWorld.rayTraceBlocks(playerPos, lookVector, false, true, false); + if (mop2 == null || mop2.typeOfHit != MovingObjectPosition.MovingObjectType.BLOCK) { + yaw = i; + break; + } + } + Rotation upRotation = new Rotation((float) (yaw + (Math.random() * 5 - 2.5)), (float) (-20 + (Math.random() * 6 - 4))); + if (mop != null && mop.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK && RotationHandler.getInstance() + .shouldRotate(upRotation, 10)) { + RotationHandler.getInstance().easeTo(new RotationConfiguration( + upRotation, + FarmHelperConfig.getRandomRotationTime(), + null + ).easeOutBack(true)); + delayClock.schedule(300); + break; + } + state = States.WAIT_FOR_LOCATION; + if (getLocationTries > 4) { + LogUtils.sendWarning("[Pests Destroyer] Couldn't find any firework location. Trying to fix it by sending /pq low."); + mc.thePlayer.sendChatMessage("/pq low"); + getLocationTries = 0; + } + KeyBindUtils.leftClick(); + getLocationTries++; + if (!stuckClock.isScheduled()) { + stuckClock.schedule(1_000 * 60 * FarmHelperConfig.pestsKillerStuckTime); + } + delayClock.schedule(300); + break; + case WAIT_FOR_LOCATION: + if (isInventoryOpenDelayed()) { + break; + } - private boolean checkIfBlockExists(Vec3 angle0, Vec3 playerPos) { - MovingObjectPosition mop0 = mc.theWorld.rayTraceBlocks(playerPos, playerPos.addVector(angle0.xCoord * 1.5, angle0.yCoord * 1.5, angle0.zCoord * 1.5), false, true, false); - return mop0 != null && mop0.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK; - } + if (RotationHandler.getInstance().isRotating()) { + return; + } - @SubscribeEvent(receiveCanceled = true) - public void onChat(ClientChatReceivedEvent event) { - if (event.type != 0 || event.message == null) return; - String message = StringUtils.stripControlCodes(event.message.getUnformattedText().trim()); - if (message.startsWith("You can't fast travel while in combat!") && enabled) { - LogUtils.sendWarning("[Pests Destroyer] Can't fast travel while in combat, will try again to teleport."); - Multithreading.schedule(this::finishMacro, 1_000 + (long) (Math.random() * 1_000), TimeUnit.MILLISECONDS); - return; + if (getClosestPest() != null) { + state = States.FIND_PEST; + break; } - if (message.toLowerCase().startsWith("there are not any pests on your garden right now") && enabled && state != States.GO_BACK) { - LogUtils.sendDebug("[Pests Destroyer] There are not any Pests on your Garden right now! Keep farming!"); - state = States.GO_BACK; - delayClock.schedule((long) (500 + Math.random() * 500)); - return; + + if (lastLocation != null && lastFireworkTime + 250 < System.currentTimeMillis()) { + Vec3 firework = calculateWaypoint(); + if (firework == null) { + LogUtils.sendDebug("[Pests Destroyer] Couldn't find any firework location. Looking for a firework."); + state = States.GET_LOCATION; + break; + } + if (mc.thePlayer.getDistance(firework.xCoord, firework.yCoord, firework.zCoord) < 2) { + int y = 150; + Block block = mc.theWorld.getBlockState(new BlockPos(firework.xCoord, y, firework.zCoord)).getBlock(); + Block[] blocksAround = new Block[]{ + mc.theWorld.getBlockState(new BlockPos(firework.xCoord + 1, y, firework.zCoord)).getBlock(), + mc.theWorld.getBlockState(new BlockPos(firework.xCoord - 1, y, firework.zCoord)).getBlock(), + mc.theWorld.getBlockState(new BlockPos(firework.xCoord, y, firework.zCoord + 1)).getBlock(), + mc.theWorld.getBlockState(new BlockPos(firework.xCoord, y, firework.zCoord - 1)).getBlock(), + block + }; + while (y > 90 && Arrays.stream(blocksAround).allMatch(b -> b.equals(Blocks.air))) { + y--; + } + y += 3; + FlyPathFinderExecutor.getInstance().setSprinting(false); + FlyPathFinderExecutor.getInstance().setDontRotate(true); + FlyPathFinderExecutor.getInstance().findPath(new Vec3(firework.xCoord, y, firework.zCoord), true, true); + LogUtils.sendWarning( + "[Pests Destroyer] Firework is too close to player. Flying to x: " + firework.xCoord + " y: " + y + " z: " + firework.zCoord); + break; + } + RotationHandler.getInstance().reset(); + state = States.FIND_PEST; + delayBetweenFireworks.schedule(3_000); + delayClock.schedule(300); + break; } - if (message.contains("The worm seems to have burrowed")) { - cantReachPest = 0; - return; + if (System.currentTimeMillis() - lastFireworkTime > 6_000) { + state = States.GET_LOCATION; + break; } - if (message.contains("Couldn't find Plot")) { - needToUpdatePlots = true; - delayClock.schedule((long) (500 + Math.random() * 500)); + break; + case FIND_PEST: + if (isInventoryOpenDelayed()) { + break; + } + getLocationTries = 0; + if (GameStateHandler.getInstance().getPestsCount() == 0) { + RotationHandler.getInstance().reset(); + state = States.CHECK_ANOTHER_PEST; + return; } - } - private final Color vacuumRangeColor = new Color(200, 30, 30, 100); - - @SubscribeEvent - public void onRender(RenderWorldLastEvent event) { - if (mc.thePlayer == null || mc.theWorld == null) return; - if (!GameStateHandler.getInstance().inGarden()) return; - - killedEntities.removeIf(e -> !mc.theWorld.loadedEntityList.contains(e)); - - List pests = mc.theWorld.loadedEntityList.stream().filter(entity -> { - if (entity.isDead) return false; - if (entity.posY < 50) return false; - if (entity instanceof EntityArmorStand) { - if (killedEntities.contains(entity)) return false; - ItemStack itemStack = ((EntityArmorStand) entity).getEquipmentInSlot(4); - if (itemStack == null || !itemStack.hasTagCompound()) return false; - String displayName = itemStack.getTagCompound().toString(); - if (displayName.contains("display:")) return false; - if (this.pests.stream().noneMatch(pest -> displayName.contains(pest.getSecond()))) return false; - if (killedEntities.contains(entity)) return false; - Entity realEntity = PlayerUtils.getEntityCuttingOtherEntity(entity, (e) -> e instanceof EntityBat || e instanceof EntitySilverfish); - Entity nameEntity = PlayerUtils.getEntityCuttingOtherEntity(entity, (e) -> e instanceof EntityArmorStand && e != entity); - if (realEntity != null && (killedEntities.contains(realEntity) || realEntity.isDead)) { - return false; - } - if (nameEntity != null && (killedEntities.contains(nameEntity))) { - return false; - } - if (killedEntities.stream().noneMatch(ke -> ke.getDistanceToEntity(entity) < 1.5)) { - if (!FarmHelperConfig.streamerMode) - drawESP(entity); - return true; - } - return false; + Entity closestPest = getClosestPest(); + + if (closestPest == null) { + if (lastLocation == null) { + LogUtils.sendDebug("[Pests Destroyer] No firework location found. Looking for a firework."); + state = States.GET_LOCATION; + break; + } + + if (!FlyPathFinderExecutor.getInstance().isRunning()) { + Vec3 firework = calculateWaypoint(); + if (firework == null) { + LogUtils.sendDebug("[Pests Destroyer] Couldn't find any firework location. Looking for a firework."); + state = States.GET_LOCATION; + break; + } + if (mc.thePlayer.getDistance(firework.xCoord, firework.yCoord, firework.zCoord) < 2) { + state = States.GET_LOCATION; + break; } - return false; - }).collect(Collectors.toList()); + FlyPathFinderExecutor.getInstance().setSprinting(true); + FlyPathFinderExecutor.getInstance().setDontRotate(false); + FlyPathFinderExecutor.getInstance().setUseAOTV(InventoryUtils.hasItemInHotbar("Aspect of the Void", "Aspect of the End")); + FlyPathFinderExecutor.getInstance().findPath(firework, true, true); + } + break; + } + if (closestPest instanceof EntityArmorStand) { + Entity realEntity = PlayerUtils.getEntityCuttingOtherEntity(closestPest, (e) -> e instanceof EntityBat || e instanceof EntitySilverfish); + if (realEntity != null) { + closestPest = realEntity; + } + } + if (FlyPathFinderExecutor.getInstance().isRunning()) { + FlyPathFinderExecutor.getInstance().stop(); + } - pestsLocations.clear(); - pestsLocations.addAll(pests); + currentEntityTarget = Optional.of(closestPest); - if (!FarmHelperConfig.highlightPlotWithPests) return; + state = States.KILL_PEST; + cantReachPest = 0; + KeyBindUtils.stopMovement(); + if (!stuckClock.isScheduled()) { + stuckClock.schedule(1_000 * 60 * FarmHelperConfig.pestsKillerStuckTime); + } + delayClock.schedule(300); + break; + case KILL_PEST: + if (isInventoryOpenDelayed()) { + break; + } + if (mc.thePlayer.posY < 67 && FlyPathFinderExecutor.getInstance().isRunning()) { + FlyPathFinderExecutor.getInstance().stop(); + RotationHandler.getInstance().reset(); + state = States.GET_LOCATION; + return; + } + if (!currentEntityTarget.isPresent()) { + FlyPathFinderExecutor.getInstance().stop(); + RotationHandler.getInstance().reset(); + state = States.CHECK_ANOTHER_PEST; + return; + } + Entity entity = currentEntityTarget.get(); + if (entity.isDead || killedEntities.contains(entity) || !mc.theWorld.loadedEntityList.contains(entity)) { + RotationHandler.getInstance().reset(); + state = States.CHECK_ANOTHER_PEST; + FlyPathFinderExecutor.getInstance().stop(); + return; + } + + double distance2 = mc.thePlayer.getDistance(entity.posX, entity.posY + entity.getEyeHeight(), entity.posZ); + double distanceXZ = mc.thePlayer.getDistance(entity.posX, mc.thePlayer.posY, entity.posZ); - double d0 = Minecraft.getMinecraft().getRenderManager().viewerPosX; - double d1 = Minecraft.getMinecraft().getRenderManager().viewerPosY; - double d2 = Minecraft.getMinecraft().getRenderManager().viewerPosZ; - for (int plotNumber : GameStateHandler.getInstance().getInfestedPlots()) { - List> chunks = PlotUtils.getPlotChunksBasedOnNumber(plotNumber); - if (chunks.isEmpty()) continue; - AxisAlignedBB boundingBox = new AxisAlignedBB(chunks.get(0).getFirst() * 16, 66, chunks.get(0).getSecond() * 16, chunks.get(chunks.size() - 1).getFirst() * 16 + 16, 80, chunks.get(chunks.size() - 1).getSecond() * 16 + 16); - float centerX = (float) (boundingBox.minX + (boundingBox.maxX - boundingBox.minX) / 2); - float centerZ = (float) (boundingBox.minZ + (boundingBox.maxZ - boundingBox.minZ) / 2); - boundingBox = boundingBox.offset(-d0, -d1, -d2); - RenderUtils.drawBox(boundingBox, FarmHelperConfig.plotHighlightColor.toJavaColor()); - RenderUtils.drawText("Plot " + plotNumber, centerX, 80, centerZ, 1); + float vacuumMinRange = Math.max(currentVacuumRange - 2, 3); + if (FarmHelperConfig.pestsKillerTicksOfNotSeeingPestWhileAttacking > 0 + && (distanceXZ < 1.5 || distance2 <= Math.max(vacuumMinRange - 2, 10)) + && Math.abs(mc.thePlayer.motionX) < 0.1 + && Math.abs(mc.thePlayer.motionZ) < 0.1 + && !canEntityBeSeenIgnoreNonCollidable(entity)) { + cantReachPest++; } - if (!FarmHelperConfig.debugMode) return; + if (cantReachPest >= FarmHelperConfig.pestsKillerTicksOfNotSeeingPestWhileAttacking) { + LogUtils.sendWarning("[Pests Destroyer] Can't reach the pest, will do a quick Garden -> Hub -> Garden teleport."); + escapeState = EscapeState.GO_TO_HUB; + KeyBindUtils.stopMovement(); + delayClock.schedule(300); + return; + } - ItemStack currentItem = mc.thePlayer.getHeldItem(); - if (currentItem == null || !currentItem.getDisplayName().contains("Vacuum")) return; - Vec3 lookVec = mc.thePlayer.getLookVec(); - Vec3 playerPos = new Vec3(0, mc.thePlayer.eyeHeight, 0); - Vec3 vacuumRange = playerPos.addVector(lookVec.xCoord * currentVacuumRange, lookVec.yCoord * currentVacuumRange, lookVec.zCoord * currentVacuumRange); - AxisAlignedBB aabb = new AxisAlignedBB(vacuumRange.xCoord - 0.05, vacuumRange.yCoord - 0.05, vacuumRange.zCoord - 0.05, vacuumRange.xCoord + 0.05, vacuumRange.yCoord + 0.05, vacuumRange.zCoord + 0.05); - RenderUtils.drawBox(aabb, vacuumRangeColor); - } - - private void drawESP(Entity entity) { - AxisAlignedBB boundingBox = new AxisAlignedBB(entity.posX - 0.5, entity.posY + entity.getEyeHeight() - 0.35, entity.posZ - 0.5, entity.posX + 0.5, entity.posY + entity.getEyeHeight() + 0.65, entity.posZ + 0.5); - double d0 = Minecraft.getMinecraft().getRenderManager().viewerPosX; - double d1 = Minecraft.getMinecraft().getRenderManager().viewerPosY; - double d2 = Minecraft.getMinecraft().getRenderManager().viewerPosZ; - boundingBox = boundingBox.offset(-d0, -d1, -d2); - if (FarmHelperConfig.pestsESP) { - Color color = FarmHelperConfig.pestsESPColor.toJavaColor(); - Vec3 entityPos = new Vec3(entity.posX, entity.posY + entity.getEyeHeight(), entity.posZ); - double distance = mc.thePlayer.getPositionEyes(1).distanceTo(entityPos); - boolean isInVacuumRange = distance < currentVacuumRange; - if (isInVacuumRange) { - color = new Color(color.getRed(), 255, color.getBlue(), Math.min(50, color.getAlpha())); + if (distance2 < vacuumMinRange) { + float targetVelocity = (float) (Math.abs(entity.motionX) + Math.abs(entity.motionZ)); + if (vacuumMinRange > 8 || targetVelocity < 0.15) { + if (FlyPathFinderExecutor.getInstance().isRunning()) { + FlyPathFinderExecutor.getInstance().stop(); + LogUtils.sendDebug("[Pests Destroyer] Stopping pathfinder because the pest is close enough"); + float playerVelocity = (float) (Math.abs(mc.thePlayer.motionX) + Math.abs(mc.thePlayer.motionZ)); + if (playerVelocity > 0.9) { + KeyBindUtils.onTick(mc.gameSettings.keyBindBack); + } + } else { + float playerVelocity = (float) (Math.abs(mc.thePlayer.motionX) + Math.abs(mc.thePlayer.motionZ)); + if (playerVelocity > 0.15 && distanceXZ < 3) { + KeyBindUtils.onTick(mc.gameSettings.keyBindBack); + } } - if (distance > 5) { - try { - EnumChatFormatting distanceColor = distance > currentVacuumRange ? EnumChatFormatting.RED : EnumChatFormatting.GREEN; - ItemStack itemStack = ((EntityArmorStand) entity).getEquipmentInSlot(4); - NBTTagCompound tagCompound = itemStack.getTagCompound(); - String texture = tagCompound.getCompoundTag("SkullOwner").getCompoundTag("Properties").getTagList("textures", 10).getCompoundTagAt(0).getString("Value"); - String pestName = this.pests.stream().filter(pest -> texture.equals(pest.getSecond())).findFirst().get().getFirst(); - RenderUtils.drawText(pestName + String.format(distanceColor + " %.1fm", distance), entity.posX, entity.posY + entity.getEyeHeight() + 0.65 + 0.5, entity.posZ, (float) (1 + Math.min((distance / 20f), 2f))); - } catch (Exception ignored) { - } + } + if (rotationState != RotationState.CLOSE) { + rotationState = RotationState.CLOSE; + RotationHandler.getInstance().reset(); + } + if (!RotationHandler.getInstance().isRotating()) { + RotationHandler.getInstance().easeTo(new RotationConfiguration( + new Target(entity), + (long) (400 + Math.random() * 200), + null + ).followTarget(true)); + } + FlyPathFinderExecutor.getInstance().setUseAOTV(false); + ItemStack currentItem3 = mc.thePlayer.getHeldItem(); + if (getVacuum(currentItem3)) { + break; + } + KeyBindUtils.setKeyBindState(mc.gameSettings.keyBindUseItem, true); + } else { + if (rotationState != RotationState.FAR) { + FlyPathFinderExecutor.getInstance().stop(); + rotationState = RotationState.FAR; + RotationHandler.getInstance().reset(); + } + if (!FlyPathFinderExecutor.getInstance().isRunning()) { + double yAddition = Math.max(2.75, Math.min(currentVacuumRange - 5, 10)); + LogUtils.sendDebug("Should pathfind to: " + entity.posX + " " + yAddition + " " + entity.posZ); + FlyPathFinderExecutor.getInstance().setSprinting(FarmHelperConfig.sprintWhileFlying); + FlyPathFinderExecutor.getInstance().setUseAOTV(InventoryUtils.hasItemInHotbar("Aspect of the Void", "Aspect of the End")); + FlyPathFinderExecutor.getInstance().findPath(entity, true, true, (float) yAddition, true); + } + if (FlyPathFinderExecutor.getInstance().getState() == FlyPathFinderExecutor.State.FAILED + && mc.thePlayer.motionX == 0 && mc.thePlayer.motionZ == 0) { + flyPathfinderTries++; + } else { + flyPathfinderTries = 0; + } + if (flyPathfinderTries > 5) { + LogUtils.sendWarning("[Pests Destroyer] Couldn't pathfind to the pest. Flying from the spawnpoint."); + flyPathfinderTries = 0; + KeyBindUtils.stopMovement(); + delayClock.schedule(1_000 + Math.random() * 500); + MacroHandler.getInstance().triggerWarpGarden(true, false); + state = States.CHECKING_SPAWN; + return; + } + if (!RotationHandler.getInstance().isRotating()) { + RotationHandler.getInstance().easeTo(new RotationConfiguration( + new Target(entity).additionalY(-0.3f), + (long) (400 + Math.random() * 200), + null + )); + } + FlyPathFinderExecutor.getInstance() + .setUseAOTV(distanceXZ > vacuumMinRange && InventoryUtils.hasItemInHotbar("Aspect of the Void", "Aspect of the End")); + if (distance2 < currentVacuumRange && getVacuum(mc.thePlayer.getHeldItem())) { + break; + } + KeyBindUtils.setKeyBindState(mc.gameSettings.keyBindUseItem, distance2 < currentVacuumRange); + } + break; + case CHECK_ANOTHER_PEST: + if (previousCurrentPlotPestsCount == GameStateHandler.getInstance().getCurrentPlotPestsCount() + && System.currentTimeMillis() - lastKillTimestamp < 2_000) { + return; + } + + LogUtils.sendDebug( + GameStateHandler.getInstance().getPestsCount() + " pest" + (GameStateHandler.getInstance().getPestsCount() == 1 ? "" : "s") + " left"); + if (GameStateHandler.getInstance().getPestsCount() == 0) { + state = States.GO_BACK; + delayClock.schedule((long) (500 + Math.random() * 500)); + break; + } + System.out.println("Curr plot pests: " + GameStateHandler.getInstance().getCurrentPlotPestsCount()); + isPlotObstructed = false; + Entity closestPest2 = getClosestPest(); + KeyBindUtils.stopMovement(); + if (closestPest2 != null) { + LogUtils.sendDebug("Found another pest"); + state = States.KILL_PEST; + currentEntityTarget = Optional.of(closestPest2); + delayClock.schedule(50 + (long) (Math.random() * 100)); + } else { + PlotUtils.Plot plotOpt = getClosestPlot(); + if (plotOpt != null) { + double distanceToPlot = Math.sqrt(mc.thePlayer.getDistanceSqToCenter(PlotUtils.getPlotCenter(plotOpt.number))); + LogUtils.sendDebug("Distance to plot: " + distanceToPlot); + if (distanceToPlot < 150 || FarmHelperConfig.dontTeleportToPlots) { + LogUtils.sendDebug("Going manually to another plot"); + state = States.GET_CLOSEST_PLOT; + delayClock.schedule(100 + (long) (Math.random() * 150)); + break; + } else { + LogUtils.sendDebug("Teleporting to plot"); + state = States.TELEPORT_TO_PLOT; + delayClock.schedule(400 + (long) (Math.random() * 400)); } - RenderUtils.drawBox(boundingBox, color); + } else { + state = States.GO_BACK; + delayClock.schedule(300 + (long) (Math.random() * 300)); + } + } + break; + case GO_BACK: + state = States.FINISH; + break; + case FINISH: + finishing = true; + if (FarmHelperConfig.pestSwapArmorAfter && currentSlot != FarmHelperConfig.pestArmorSlot1) { + state = States.SWAP_ARMOR; + return; } - if (FarmHelperConfig.pestsTracers) { - RenderUtils.drawTracer(new Vec3(entity.posX, entity.posY + entity.getEyeHeight(), entity.posZ), FarmHelperConfig.pestsTracersColor.toJavaColor()); + finishMacro(); +// state = States.FINISH; + break; + } + } + + @Nullable + private Entity getClosestPest() { + Entity closestPest = null; + double closestDistance = Double.MAX_VALUE; + for (Entity entity : pestsLocations) { + double distance = mc.thePlayer.getDistanceToEntity(entity); + if (distance < closestDistance) { + closestDistance = distance; + closestPest = entity; + } + } + return closestPest; + } + + public boolean getVacuum(ItemStack currentItem2) { + if (currentItem2 == null || !currentItem2.getDisplayName().contains("Vacuum")) { + int vacuum = InventoryUtils.getSlotIdOfItemInHotbar("Vacuum"); + if (vacuum == -1) { + LogUtils.sendError("[Pests Destroyer] Failed to find vacuum in hotbar!"); + state = States.GO_BACK; + FarmHelperConfig.enablePestsDestroyer = false; +// finishMacro(); + state = States.FINISH; + return true; + } + mc.thePlayer.inventory.currentItem = vacuum; + delayClock.schedule((long) (200 + Math.random() * 200)); + return true; + } + return false; + } + + private boolean isInventoryOpenDelayed() { + if (mc.currentScreen != null) { + KeyBindUtils.stopMovement(); + delayClock.schedule(300 + (long) (Math.random() * 300)); + Multithreading.schedule(() -> { + if (mc.currentScreen != null) { + PlayerUtils.closeScreen(); + delayClock.schedule(100 + (long) (Math.random() * 200)); } + }, (long) (200 + Math.random() * 100), TimeUnit.MILLISECONDS); + return true; } + return false; + } + + private boolean isInventoryOpen() { + if (mc.currentScreen != null) { + PlayerUtils.closeScreen(); + delayClock.schedule(500 + (long) (Math.random() * 500)); + return true; + } + return false; + } + - private boolean canEntityBeSeenIgnoreNonCollidable(Entity entity) { - Vec3 vec3 = new Vec3(entity.posX, entity.posY + entity.getEyeHeight() + 0.5, entity.posZ); - Vec3 vec31 = new Vec3(mc.thePlayer.posX, mc.thePlayer.posY + mc.thePlayer.getEyeHeight(), mc.thePlayer.posZ); - MovingObjectPosition mop = mc.theWorld.rayTraceBlocks(vec31, vec3, false, true, false); - return mop == null || mop.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK && (mc.theWorld.getBlockState(mop.getBlockPos()).getBlock().equals(Blocks.cactus) || !BlockUtils.hasCollision(mop.getBlockPos())); + private void finishMacro() { + if (isInventoryOpen()) { + return; + } + if (FlyPathFinderExecutor.getInstance().isPathing()) { + FlyPathFinderExecutor.getInstance().stop(); + } + if (MacroHandler.getInstance().isMacroToggled()) { + stop(); + MacroHandler.getInstance().triggerWarpGarden(true, true, false); + delayClock.schedule(2_000 + Math.random() * 500); + } else { + stop(); + } + } + + private boolean hasBlocksAround() { + Vec3 angle0 = AngleUtils.getVectorForRotation(0, mc.thePlayer.rotationYaw); + Vec3 angle90 = AngleUtils.getVectorForRotation(90, mc.thePlayer.rotationYaw); + Vec3 angle180 = AngleUtils.getVectorForRotation(180, mc.thePlayer.rotationYaw); + Vec3 angle270 = AngleUtils.getVectorForRotation(270, mc.thePlayer.rotationYaw); + Vec3 playerPos = mc.thePlayer.getPositionEyes(1); + if (checkIfBlockExists(angle0, playerPos)) { + return true; + } + if (checkIfBlockExists(angle90, playerPos)) { + return true; + } + if (checkIfBlockExists(angle180, playerPos)) { + return true; + } + return checkIfBlockExists(angle270, playerPos); + } + + private boolean checkIfBlockExists(Vec3 angle0, Vec3 playerPos) { + MovingObjectPosition mop0 = mc.theWorld.rayTraceBlocks(playerPos, + playerPos.addVector(angle0.xCoord * 1.5, angle0.yCoord * 1.5, angle0.zCoord * 1.5), false, true, false); + return mop0 != null && mop0.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK; + } + + @SubscribeEvent(receiveCanceled = true) + public void onChat(ClientChatReceivedEvent event) { + if (event.type != 0 || event.message == null) { + return; + } + String message = StringUtils.stripControlCodes(event.message.getUnformattedText().trim()); + if (message.startsWith("You can't fast travel while in combat!") && enabled) { + LogUtils.sendWarning("[Pests Destroyer] Can't fast travel while in combat, will try again to teleport."); +// Multithreading.schedule(this::finishMacro, 1_000 + (long) (Math.random() * 1_000), TimeUnit.MILLISECONDS); + state = States.FINISH; + return; } + if (message.toLowerCase().startsWith("there are not any pests on your garden right now") && enabled && state != States.GO_BACK) { + LogUtils.sendDebug("[Pests Destroyer] There are not any Pests on your Garden right now! Keep farming!"); + state = States.GO_BACK; + delayClock.schedule((long) (500 + Math.random() * 500)); + return; + } + if (message.contains("The worm seems to have burrowed")) { + cantReachPest = 0; + return; + } + if (message.contains("Couldn't find Plot")) { + needToUpdatePlots = true; + delayClock.schedule((long) (500 + Math.random() * 500)); + } + } - @SubscribeEvent(receiveCanceled = true, priority = EventPriority.HIGHEST) - public void onEntityDeath(LivingDeathEvent event) { - if (mc.thePlayer == null || mc.theWorld == null) return; - if (!GameStateHandler.getInstance().inGarden()) return; + private final Color vacuumRangeColor = new Color(200, 30, 30, 100); - Entity entity = event.entity; - LogUtils.sendDebug("[Pests Destroyer] Entity died: " + entity.getName() + "(" + entity.getEntityId() + ")" + " at: " + entity.getPosition()); - killedEntities.add(entity); - if (mc.thePlayer.getDistanceToEntity(entity) < 20) { - lastKillTimestamp = System.currentTimeMillis(); - previousCurrentPlotPestsCount = GameStateHandler.getInstance().getCurrentPlotPestsCount(); - state = States.CHECK_ANOTHER_PEST; + @SubscribeEvent + public void onRender(RenderWorldLastEvent event) { + if (mc.thePlayer == null || mc.theWorld == null) { + return; + } + if (!GameStateHandler.getInstance().inGarden()) { + return; + } + + killedEntities.removeIf(e -> !mc.theWorld.loadedEntityList.contains(e)); + + List pests = mc.theWorld.loadedEntityList.stream().filter(entity -> { + if (entity.isDead) { + return false; + } + if (entity.posY < 50) { + return false; + } + if (entity instanceof EntityArmorStand) { + if (killedEntities.contains(entity)) { + return false; } - if (entity instanceof EntityArmorStand) { - Entity realEntity = PlayerUtils.getEntityCuttingOtherEntity(entity, (e) -> e instanceof EntityBat || e instanceof EntitySilverfish); - Entity nameEntity = PlayerUtils.getEntityCuttingOtherEntity(entity, (e) -> e instanceof EntityArmorStand && e != entity); - if (realEntity != null) { - LogUtils.sendDebug("[Pests Destroyer] Found real entity: " + realEntity.getName() + "(" + realEntity.getEntityId() + ")" + " at: " + realEntity.getPosition()); - killedEntities.add(realEntity); - } - if (nameEntity != null) { - LogUtils.sendDebug("[Pests Destroyer] Found name entity: " + nameEntity.getName() + "(" + nameEntity.getEntityId() + ")" + " at: " + nameEntity.getPosition()); - killedEntities.add(nameEntity); - } + ItemStack itemStack = ((EntityArmorStand) entity).getEquipmentInSlot(4); + if (itemStack == null || !itemStack.hasTagCompound()) { + return false; } - if (entity instanceof EntityBat || entity instanceof EntitySilverfish) { - Entity armorStand = PlayerUtils.getEntityCuttingOtherEntity(entity, (e) -> e instanceof EntityArmorStand && e.getName().contains("Armor Stand")); - Entity nameEntity = PlayerUtils.getEntityCuttingOtherEntity(entity, (e) -> e instanceof EntityArmorStand && e != armorStand); - if (armorStand != null) { - LogUtils.sendDebug("[Pests Destroyer] Found armor stand: " + armorStand.getName() + "(" + armorStand.getEntityId() + ")" + " at: " + armorStand.getPosition()); - killedEntities.add(armorStand); - } - if (nameEntity != null) { - LogUtils.sendDebug("[Pests Destroyer] Found name entity: " + nameEntity.getName() + "(" + nameEntity.getEntityId() + ")" + " at: " + nameEntity.getPosition()); - killedEntities.add(nameEntity); - } + String displayName = itemStack.getTagCompound().toString(); + if (displayName.contains("display:")) { + return false; } - if (isRunning()) - FlyPathFinderExecutor.getInstance().stop(); - resetFireworkInfo(); - lastFireworkTime = 0; - currentEntityTarget.ifPresent(e -> { - if (!e.equals(event.entity)) { - return; - } - if (isRunning()) - KeyBindUtils.stopMovement(); - currentEntityTarget = Optional.empty(); - stuckClock.reset(); - }); - PlotUtils.Plot plot = PlotUtils.getPlotNumberBasedOnLocation(entity.getPosition()); - if (plot == null) { - if (isRunning()) - LogUtils.sendDebug("[Pests Destroyer] Failed to get plot for entity: " + entity.getName() + " at: " + entity.getPosition()); - return; + if (this.pests.stream().noneMatch(pest -> displayName.contains(pest.getSecond()))) { + return false; } - LogUtils.sendDebug("[Pests Destroyer] Removed 1 pest from plot number: " + plot.number); - killedPestsFrom.add(plot.number); - } + if (killedEntities.contains(entity)) { + return false; + } + Entity realEntity = PlayerUtils.getEntityCuttingOtherEntity(entity, (e) -> e instanceof EntityBat || e instanceof EntitySilverfish); + Entity nameEntity = PlayerUtils.getEntityCuttingOtherEntity(entity, (e) -> e instanceof EntityArmorStand && e != entity); + if (realEntity != null && (killedEntities.contains(realEntity) || realEntity.isDead)) { + return false; + } + if (nameEntity != null && (killedEntities.contains(nameEntity))) { + return false; + } + if (killedEntities.stream().noneMatch(ke -> ke.getDistanceToEntity(entity) < 1.5)) { + if (!FarmHelperConfig.streamerMode) { + drawESP(entity); + } + return true; + } + return false; + } + return false; + }).collect(Collectors.toList()); - private final List locations = new ArrayList<>(); - private Vec3 firstLocation = null; - private Vec3 lastLocation = null; + pestsLocations.clear(); + pestsLocations.addAll(pests); - @SubscribeEvent(receiveCanceled = true, priority = EventPriority.HIGHEST) - public void onFirework(SpawnParticleEvent event) { - if (mc.thePlayer == null || mc.theWorld == null) return; - if (!GameStateHandler.getInstance().inGarden()) return; - if (!enabled) return; - if (state != States.WAIT_FOR_LOCATION) return; + if (!FarmHelperConfig.highlightPlotWithPests) { + return; + } - EnumParticleTypes type = event.getParticleTypes(); - if (type != EnumParticleTypes.VILLAGER_ANGRY) return; + double d0 = Minecraft.getMinecraft().getRenderManager().viewerPosX; + double d1 = Minecraft.getMinecraft().getRenderManager().viewerPosY; + double d2 = Minecraft.getMinecraft().getRenderManager().viewerPosZ; + for (int plotNumber : GameStateHandler.getInstance().getInfestedPlots()) { + List> chunks = PlotUtils.getPlotChunksBasedOnNumber(plotNumber); + if (chunks.isEmpty()) { + continue; + } + AxisAlignedBB boundingBox = new AxisAlignedBB(chunks.get(0).getFirst() * 16, 66, chunks.get(0).getSecond() * 16, + chunks.get(chunks.size() - 1).getFirst() * 16 + 16, 80, chunks.get(chunks.size() - 1).getSecond() * 16 + 16); + float centerX = (float) (boundingBox.minX + (boundingBox.maxX - boundingBox.minX) / 2); + float centerZ = (float) (boundingBox.minZ + (boundingBox.maxZ - boundingBox.minZ) / 2); + boundingBox = boundingBox.offset(-d0, -d1, -d2); + RenderUtils.drawBox(boundingBox, FarmHelperConfig.plotHighlightColor.toJavaColor()); + RenderUtils.drawText("Plot " + plotNumber, centerX, 80, centerZ, 1); + } - lastFireworkTime = System.currentTimeMillis(); - if (firstLocation == null) { - if (mc.thePlayer.getPositionVector().distanceTo(event.getPos()) > 5) return; - firstLocation = event.getPos(); - locations.add(firstLocation); - lastLocation = firstLocation; - return; - } - double dist = lastLocation.distanceTo(event.getPos()); - if (dist > 1.75) { - return; + if (!FarmHelperConfig.debugMode) { + return; + } + + ItemStack currentItem = mc.thePlayer.getHeldItem(); + if (currentItem == null || !currentItem.getDisplayName().contains("Vacuum")) { + return; + } + Vec3 lookVec = mc.thePlayer.getLookVec(); + Vec3 playerPos = new Vec3(0, mc.thePlayer.eyeHeight, 0); + Vec3 vacuumRange = playerPos.addVector(lookVec.xCoord * currentVacuumRange, lookVec.yCoord * currentVacuumRange, + lookVec.zCoord * currentVacuumRange); + AxisAlignedBB aabb = new AxisAlignedBB(vacuumRange.xCoord - 0.05, vacuumRange.yCoord - 0.05, vacuumRange.zCoord - 0.05, vacuumRange.xCoord + 0.05, + vacuumRange.yCoord + 0.05, vacuumRange.zCoord + 0.05); + RenderUtils.drawBox(aabb, vacuumRangeColor); + } + + private void drawESP(Entity entity) { + AxisAlignedBB boundingBox = new AxisAlignedBB(entity.posX - 0.5, entity.posY + entity.getEyeHeight() - 0.35, entity.posZ - 0.5, entity.posX + 0.5, + entity.posY + entity.getEyeHeight() + 0.65, entity.posZ + 0.5); + double d0 = Minecraft.getMinecraft().getRenderManager().viewerPosX; + double d1 = Minecraft.getMinecraft().getRenderManager().viewerPosY; + double d2 = Minecraft.getMinecraft().getRenderManager().viewerPosZ; + boundingBox = boundingBox.offset(-d0, -d1, -d2); + if (FarmHelperConfig.pestsESP) { + Color color = FarmHelperConfig.pestsESPColor.toJavaColor(); + Vec3 entityPos = new Vec3(entity.posX, entity.posY + entity.getEyeHeight(), entity.posZ); + double distance = mc.thePlayer.getPositionEyes(1).distanceTo(entityPos); + boolean isInVacuumRange = distance < currentVacuumRange; + if (isInVacuumRange) { + color = new Color(color.getRed(), 255, color.getBlue(), Math.min(50, color.getAlpha())); + } + if (distance > 5) { + try { + EnumChatFormatting distanceColor = distance > currentVacuumRange ? EnumChatFormatting.RED : EnumChatFormatting.GREEN; + ItemStack itemStack = ((EntityArmorStand) entity).getEquipmentInSlot(4); + NBTTagCompound tagCompound = itemStack.getTagCompound(); + String texture = tagCompound.getCompoundTag("SkullOwner").getCompoundTag("Properties").getTagList("textures", 10).getCompoundTagAt(0) + .getString("Value"); + String pestName = this.pests.stream().filter(pest -> texture.equals(pest.getSecond())).findFirst().get().getFirst(); + RenderUtils.drawText(pestName + String.format(distanceColor + " %.1fm", distance), entity.posX, + entity.posY + entity.getEyeHeight() + 0.65 + 0.5, entity.posZ, (float) (1 + Math.min((distance / 20f), 2f))); + } catch (Exception ignored) { } - locations.add(event.getPos()); - lastLocation = event.getPos(); + } + RenderUtils.drawBox(boundingBox, color); + } + if (FarmHelperConfig.pestsTracers) { + RenderUtils.drawTracer(new Vec3(entity.posX, entity.posY + entity.getEyeHeight(), entity.posZ), + FarmHelperConfig.pestsTracersColor.toJavaColor()); + } + } + + private boolean canEntityBeSeenIgnoreNonCollidable(Entity entity) { + Vec3 vec3 = new Vec3(entity.posX, entity.posY + entity.getEyeHeight() + 0.5, entity.posZ); + Vec3 vec31 = new Vec3(mc.thePlayer.posX, mc.thePlayer.posY + mc.thePlayer.getEyeHeight(), mc.thePlayer.posZ); + MovingObjectPosition mop = mc.theWorld.rayTraceBlocks(vec31, vec3, false, true, false); + return mop == null || mop.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK && ( + mc.theWorld.getBlockState(mop.getBlockPos()).getBlock().equals(Blocks.cactus) || !BlockUtils.hasCollision(mop.getBlockPos())); + } + + @SubscribeEvent(receiveCanceled = true, priority = EventPriority.HIGHEST) + public void onEntityDeath(LivingDeathEvent event) { + if (mc.thePlayer == null || mc.theWorld == null) { + return; + } + if (!GameStateHandler.getInstance().inGarden()) { + return; } - private Vec3 calculateWaypoint() { - if (lastLocation == null) return null; - Vec3 direction = lastLocation.subtract(firstLocation).normalize(); - return lastLocation.addVector(direction.xCoord * 10, 0, direction.zCoord * 10); + Entity entity = event.entity; + LogUtils.sendDebug("[Pests Destroyer] Entity died: " + entity.getName() + "(" + entity.getEntityId() + ")" + " at: " + entity.getPosition()); + killedEntities.add(entity); + if (mc.thePlayer.getDistanceToEntity(entity) < 20) { + lastKillTimestamp = System.currentTimeMillis(); + previousCurrentPlotPestsCount = GameStateHandler.getInstance().getCurrentPlotPestsCount(); + state = States.CHECK_ANOTHER_PEST; + } + if (entity instanceof EntityArmorStand) { + Entity realEntity = PlayerUtils.getEntityCuttingOtherEntity(entity, (e) -> e instanceof EntityBat || e instanceof EntitySilverfish); + Entity nameEntity = PlayerUtils.getEntityCuttingOtherEntity(entity, (e) -> e instanceof EntityArmorStand && e != entity); + if (realEntity != null) { + LogUtils.sendDebug("[Pests Destroyer] Found real entity: " + realEntity.getName() + "(" + realEntity.getEntityId() + ")" + " at: " + + realEntity.getPosition()); + killedEntities.add(realEntity); + } + if (nameEntity != null) { + LogUtils.sendDebug("[Pests Destroyer] Found name entity: " + nameEntity.getName() + "(" + nameEntity.getEntityId() + ")" + " at: " + + nameEntity.getPosition()); + killedEntities.add(nameEntity); + } + } + if (entity instanceof EntityBat || entity instanceof EntitySilverfish) { + Entity armorStand = PlayerUtils.getEntityCuttingOtherEntity(entity, + (e) -> e instanceof EntityArmorStand && e.getName().contains("Armor Stand")); + Entity nameEntity = PlayerUtils.getEntityCuttingOtherEntity(entity, (e) -> e instanceof EntityArmorStand && e != armorStand); + if (armorStand != null) { + LogUtils.sendDebug("[Pests Destroyer] Found armor stand: " + armorStand.getName() + "(" + armorStand.getEntityId() + ")" + " at: " + + armorStand.getPosition()); + killedEntities.add(armorStand); + } + if (nameEntity != null) { + LogUtils.sendDebug("[Pests Destroyer] Found name entity: " + nameEntity.getName() + "(" + nameEntity.getEntityId() + ")" + " at: " + + nameEntity.getPosition()); + killedEntities.add(nameEntity); + } + } + if (isRunning()) { + FlyPathFinderExecutor.getInstance().stop(); + } + resetFireworkInfo(); + lastFireworkTime = 0; + currentEntityTarget.ifPresent(e -> { + if (!e.equals(event.entity)) { + return; + } + if (isRunning()) { + KeyBindUtils.stopMovement(); + } + currentEntityTarget = Optional.empty(); + stuckClock.reset(); + }); + PlotUtils.Plot plot = PlotUtils.getPlotNumberBasedOnLocation(entity.getPosition()); + if (plot == null) { + if (isRunning()) { + LogUtils.sendDebug("[Pests Destroyer] Failed to get plot for entity: " + entity.getName() + " at: " + entity.getPosition()); + } + return; + } + LogUtils.sendDebug("[Pests Destroyer] Removed 1 pest from plot number: " + plot.number); + killedPestsFrom.add(plot.number); + } + + private final List locations = new ArrayList<>(); + private Vec3 firstLocation = null; + private Vec3 lastLocation = null; + + @SubscribeEvent(receiveCanceled = true, priority = EventPriority.HIGHEST) + public void onFirework(SpawnParticleEvent event) { + if (mc.thePlayer == null || mc.theWorld == null) { + return; + } + if (!GameStateHandler.getInstance().inGarden()) { + return; + } + if (!enabled) { + return; + } + if (state != States.WAIT_FOR_LOCATION) { + return; } - public void resetFireworkInfo() { - locations.clear(); - firstLocation = null; - lastLocation = null; - lastFireworkTime = 0; + EnumParticleTypes type = event.getParticleTypes(); + if (type != EnumParticleTypes.VILLAGER_ANGRY) { + return; } - @SubscribeEvent - public void onSpawnObject(SpawnObjectEvent event) { - if (mc.thePlayer == null || mc.theWorld == null) return; - if (!GameStateHandler.getInstance().inGarden()) return; - if (event.type != 76) return; - if (!enabled) return; - if (state != States.WAIT_FOR_LOCATION) return; + lastFireworkTime = System.currentTimeMillis(); + if (firstLocation == null) { + if (mc.thePlayer.getPositionVector().distanceTo(event.getPos()) > 5) { + return; + } + firstLocation = event.getPos(); + locations.add(firstLocation); + lastLocation = firstLocation; + return; + } + double dist = lastLocation.distanceTo(event.getPos()); + if (dist > 1.75) { + return; + } + locations.add(event.getPos()); + lastLocation = event.getPos(); + } - double distance = mc.thePlayer.getDistance(event.pos.xCoord, event.pos.yCoord, event.pos.zCoord); - if (distance < 3) { - int y = 130; - Block block = mc.theWorld.getBlockState(new BlockPos(event.pos.xCoord, y, event.pos.zCoord)).getBlock(); - while (y > 90 && block.equals(Blocks.air)) { - y--; - } - y += 3; - FlyPathFinderExecutor.getInstance().setDontRotate(true); - FlyPathFinderExecutor.getInstance().setSprinting(false); - FlyPathFinderExecutor.getInstance().findPath(new Vec3(event.pos.xCoord, y, event.pos.zCoord), true, true); - LogUtils.sendWarning("[Pests Destroyer] Firework is too close to player. Flying to x: " + event.pos.xCoord + " y: " + y + " z: " + event.pos.zCoord); - state = States.GET_LOCATION; - } + private Vec3 calculateWaypoint() { + if (lastLocation == null) { + return null; + } + Vec3 direction = lastLocation.subtract(firstLocation).normalize(); + return lastLocation.addVector(direction.xCoord * 10, 0, direction.zCoord * 10); + } + + public void resetFireworkInfo() { + locations.clear(); + firstLocation = null; + lastLocation = null; + lastFireworkTime = 0; + } + + @SubscribeEvent + public void onSpawnObject(SpawnObjectEvent event) { + if (mc.thePlayer == null || mc.theWorld == null) { + return; + } + if (!GameStateHandler.getInstance().inGarden()) { + return; + } + if (event.type != 76) { + return; + } + if (!enabled) { + return; + } + if (state != States.WAIT_FOR_LOCATION) { + return; } - private boolean checkedThisGui = false; - - @SubscribeEvent - public void onGuiOpen(DrawScreenAfterEvent event) { - if (mc.thePlayer == null || mc.theWorld == null) return; - if (!GameStateHandler.getInstance().inGarden()) return; - if (checkedThisGui) return; - if (!(event.guiScreen instanceof GuiChest)) return; - String guiName = InventoryUtils.getInventoryName(); - if (guiName == null) return; - if (!delayClock.passed()) return; - ContainerChest guiChest = (ContainerChest) ((GuiChest) event.guiScreen).inventorySlots; - - if (!InventoryUtils.isInventoryLoaded()) return; - - int plotCounter = 0; - if (StringUtils.stripControlCodes(guiName).equals("Configure Plots")) { - for (int i = 0; i < guiChest.inventorySlots.size(); i++) { - Slot slot = guiChest.inventorySlots.get(i); - if (slot == null || !slot.getHasStack()) continue; - if (slot.getStack().getDisplayName().contains("Plot")) { - String displayName = StringUtils.stripControlCodes(slot.getStack().getDisplayName()); - try { - String plotName = displayName.replace("Plot - ", "").trim(); - int plotNumber = PlotUtils.getPLOT_NUMBERS().get(plotCounter); - PlotUtils.setPlot(plotNumber, plotName); - } catch (Exception e) { - LogUtils.sendError("[Pests Destroyer] Failed to parse plot number: " + displayName); - } - plotCounter++; - } else if (StringUtils.stripControlCodes(slot.getStack().getDisplayName()).equals("The Barn")) - plotCounter++; - } + double distance = mc.thePlayer.getDistance(event.pos.xCoord, event.pos.yCoord, event.pos.zCoord); + if (distance < 3) { + int y = 130; + Block block = mc.theWorld.getBlockState(new BlockPos(event.pos.xCoord, y, event.pos.zCoord)).getBlock(); + while (y > 90 && block.equals(Blocks.air)) { + y--; + } + y += 3; + FlyPathFinderExecutor.getInstance().setDontRotate(true); + FlyPathFinderExecutor.getInstance().setSprinting(false); + FlyPathFinderExecutor.getInstance().findPath(new Vec3(event.pos.xCoord, y, event.pos.zCoord), true, true); + LogUtils.sendWarning( + "[Pests Destroyer] Firework is too close to player. Flying to x: " + event.pos.xCoord + " y: " + y + " z: " + event.pos.zCoord); + state = States.GET_LOCATION; + } + } - } else { - return; + private boolean checkedThisGui = false; + + @SubscribeEvent + public void onGuiOpen(DrawScreenAfterEvent event) { + if (mc.thePlayer == null || mc.theWorld == null) { + return; + } + if (!GameStateHandler.getInstance().inGarden()) { + return; + } + if (checkedThisGui) { + return; + } + if (!(event.guiScreen instanceof GuiChest)) { + return; + } + String guiName = InventoryUtils.getInventoryName(); + if (guiName == null) { + return; + } + if (!delayClock.passed()) { + return; + } + ContainerChest guiChest = (ContainerChest) ((GuiChest) event.guiScreen).inventorySlots; + + if (!InventoryUtils.isInventoryLoaded()) { + return; + } + + int plotCounter = 0; + if (StringUtils.stripControlCodes(guiName).equals("Configure Plots")) { + for (int i = 0; i < guiChest.inventorySlots.size(); i++) { + Slot slot = guiChest.inventorySlots.get(i); + if (slot == null || !slot.getHasStack()) { + continue; } - needToUpdatePlots = false; - checkedThisGui = true; - PlotUtils.savePlots(); - LogUtils.sendDebug("[Pests Destroyer] Updated plots"); - if (state == States.WAIT_FOR_INFO) { - PlayerUtils.closeScreen(); - if (FarmHelperConfig.dontTeleportToPlots) { - state = States.GET_CLOSEST_PLOT; - } else { - state = States.TELEPORT_TO_PLOT; - } - delayClock.schedule(300 + (long) (Math.random() * 250)); + if (slot.getStack().getDisplayName().contains("Plot")) { + String displayName = StringUtils.stripControlCodes(slot.getStack().getDisplayName()); + try { + String plotName = displayName.replace("Plot - ", "").trim(); + int plotNumber = PlotUtils.getPLOT_NUMBERS().get(plotCounter); + PlotUtils.setPlot(plotNumber, plotName); + } catch (Exception e) { + LogUtils.sendError("[Pests Destroyer] Failed to parse plot number: " + displayName); + } + plotCounter++; + } else if (StringUtils.stripControlCodes(slot.getStack().getDisplayName()).equals("The Barn")) { + plotCounter++; } + } + + } else { + return; } + needToUpdatePlots = false; + checkedThisGui = true; + PlotUtils.savePlots(); + LogUtils.sendDebug("[Pests Destroyer] Updated plots"); + if (state == States.WAIT_FOR_INFO) { + PlayerUtils.closeScreen(); + if (FarmHelperConfig.dontTeleportToPlots) { + state = States.GET_CLOSEST_PLOT; + } else { + state = States.TELEPORT_TO_PLOT; + } + delayClock.schedule(300 + (long) (Math.random() * 250)); + } + } - private final Clock flyDelay = new Clock(); + private final Clock flyDelay = new Clock(); - private void fly() { - if (mc.thePlayer.capabilities.isFlying) { - KeyBindUtils.holdThese(mc.gameSettings.keyBindJump); - return; - } - if (mc.thePlayer.motionY < -0.0784000015258789 || BlockUtils.getRelativeBlock(0, 0, 0).getMaterial().isLiquid()) - if (flyDelay.passed()) { - if (!mc.thePlayer.capabilities.isFlying) { - mc.thePlayer.capabilities.isFlying = true; - mc.thePlayer.sendPlayerAbilities(); - } - flyDelay.reset(); - } else if (flyDelay.isScheduled()) { - return; - } - if (mc.thePlayer.onGround) { - mc.thePlayer.jump(); - flyDelay.schedule(80 + (long) (Math.random() * 80)); - } else if (!mc.thePlayer.capabilities.isFlying && !flyDelay.isScheduled()) { - flyDelay.schedule(80 + (long) (Math.random() * 80)); - } - } - - private PlotUtils.Plot getClosestPlot() { - List infestedPlots = GameStateHandler.getInstance().getInfestedPlots(); - if (infestedPlots.isEmpty()) { - LogUtils.sendError("[Pests Destroyer] Couldn't find infested plots on Tablist! Make sure you have it enabled in Tablist Widgets"); - return null; - } - if (GameStateHandler.getInstance().getCurrentPlotPestsCount() == 0) { - infestedPlots.removeIf(killedPestsFrom::contains); - } - PlotUtils.Plot closestPlot = null; - double closestDistance = Double.MAX_VALUE; - for (int plot : infestedPlots) { - double distance = mc.thePlayer.getDistanceSqToCenter(PlotUtils.getPlotCenter(plot)); - if (distance < closestDistance) { - closestDistance = distance; - closestPlot = PlotUtils.getPlotBasedOnNumber(plot); - } + private void fly() { + if (mc.thePlayer.capabilities.isFlying) { + KeyBindUtils.holdThese(mc.gameSettings.keyBindJump); + return; + } + if (mc.thePlayer.motionY < -0.0784000015258789 || BlockUtils.getRelativeBlock(0, 0, 0).getMaterial().isLiquid()) { + if (flyDelay.passed()) { + if (!mc.thePlayer.capabilities.isFlying) { + mc.thePlayer.capabilities.isFlying = true; + mc.thePlayer.sendPlayerAbilities(); } - if (closestPlot == null) { - LogUtils.sendDebug("[Pests Destroyer] Failed to get closest plot"); - return null; - } - return closestPlot; - } - - private boolean isNearPlotCenter() { - if (!closestPlot.isPresent()) return false; - BlockPos plotCenter = PlotUtils.getPlotCenter(closestPlot.get().number); - double distance = mc.thePlayer.getDistance(plotCenter.getX(), mc.thePlayer.posY, plotCenter.getZ()); - return distance < 15; - } - - public enum States { - IDLE, - OPEN_DESK, - OPEN_PLOTS, - WAIT_FOR_INFO, - TELEPORT_TO_PLOT, - WAIT_FOR_TP, - CHECKING_PLOT, - CHECKING_SPAWN, - GET_CLOSEST_PLOT, - FLY_TO_THE_CLOSEST_PLOT, - GET_LOCATION, - WAIT_FOR_LOCATION, - FIND_PEST, - KILL_PEST, - CHECK_ANOTHER_PEST, - GO_BACK - } - - enum RotationState { - NONE, - CLOSE, - MEDIUM, - FAR - } - - public enum EscapeState { - NONE, - GO_TO_HUB, - GO_TO_GARDEN, - RESUME_MACRO + flyDelay.reset(); + } else if (flyDelay.isScheduled()) { + return; + } + } + if (mc.thePlayer.onGround) { + mc.thePlayer.jump(); + flyDelay.schedule(80 + (long) (Math.random() * 80)); + } else if (!mc.thePlayer.capabilities.isFlying && !flyDelay.isScheduled()) { + flyDelay.schedule(80 + (long) (Math.random() * 80)); + } + } + + private PlotUtils.Plot getClosestPlot() { + List infestedPlots = GameStateHandler.getInstance().getInfestedPlots(); + if (infestedPlots.isEmpty()) { + LogUtils.sendError("[Pests Destroyer] Couldn't find infested plots on Tablist! Make sure you have it enabled in Tablist Widgets"); + return null; + } + if (GameStateHandler.getInstance().getCurrentPlotPestsCount() == 0) { + infestedPlots.removeIf(killedPestsFrom::contains); + } + PlotUtils.Plot closestPlot = null; + double closestDistance = Double.MAX_VALUE; + for (int plot : infestedPlots) { + double distance = mc.thePlayer.getDistanceSqToCenter(PlotUtils.getPlotCenter(plot)); + if (distance < closestDistance) { + closestDistance = distance; + closestPlot = PlotUtils.getPlotBasedOnNumber(plot); + } + } + if (closestPlot == null) { + LogUtils.sendDebug("[Pests Destroyer] Failed to get closest plot"); + return null; + } + return closestPlot; + } + + private boolean isNearPlotCenter() { + if (!closestPlot.isPresent()) { + return false; } + BlockPos plotCenter = PlotUtils.getPlotCenter(closestPlot.get().number); + double distance = mc.thePlayer.getDistance(plotCenter.getX(), mc.thePlayer.posY, plotCenter.getZ()); + return distance < 15; + } + + public enum States { + IDLE, + SWAP_ARMOR, + ARMOR_SWAP_VERIFY, + OPEN_DESK, + OPEN_PLOTS, + WAIT_FOR_INFO, + TELEPORT_TO_PLOT, + WAIT_FOR_TP, + CHECKING_PLOT, + CHECKING_SPAWN, + GET_CLOSEST_PLOT, + FLY_TO_THE_CLOSEST_PLOT, + GET_LOCATION, + WAIT_FOR_LOCATION, + FIND_PEST, + KILL_PEST, + CHECK_ANOTHER_PEST, + GO_BACK, + FINISH + } + + enum RotationState { + NONE, + CLOSE, + MEDIUM, + FAR + } + + public enum EscapeState { + NONE, + GO_TO_HUB, + GO_TO_GARDEN, + RESUME_MACRO + } } From 9303aa6e922f639536a0d1cb20ce0a72aa0eeb70 Mon Sep 17 00:00:00 2001 From: Osama Date: Sat, 30 Nov 2024 00:11:02 +0600 Subject: [PATCH 02/10] Goat --- gradle.properties | 2 +- .../command/FarmHelperMainCommand.java | 6 +- .../farmhelperv2/config/FarmHelperConfig.java | 74 +++++++ .../farmhelperv2/feature/FeatureManager.java | 4 +- .../feature/impl/AutoWardrobe.java | 198 +++++++++++++++++- .../farmhelperv2/feature/impl/BPSTracker.java | 6 +- .../farmhelperv2/feature/impl/PestFarmer.java | 157 +++++++++++++- .../farmhelperv2/macro/AbstractMacro.java | 5 +- .../mixin/client/MixinMinecraft.java | 10 + 9 files changed, 449 insertions(+), 13 deletions(-) diff --git a/gradle.properties b/gradle.properties index 0323d62c..8cb0c277 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,5 +4,5 @@ baseGroup=com.jelly.farmhelperv2 mcVersion=1.8.9 modid=farmhelperv2 modName=FarmHelper -version=2.8.14 +version=2.9.2 shouldRelease=true diff --git a/src/main/java/com/jelly/farmhelperv2/command/FarmHelperMainCommand.java b/src/main/java/com/jelly/farmhelperv2/command/FarmHelperMainCommand.java index 0fd0b219..851f3cb4 100644 --- a/src/main/java/com/jelly/farmhelperv2/command/FarmHelperMainCommand.java +++ b/src/main/java/com/jelly/farmhelperv2/command/FarmHelperMainCommand.java @@ -6,6 +6,7 @@ import cc.polyfrost.oneconfig.utils.commands.annotations.SubCommand; import com.jelly.farmhelperv2.FarmHelper; import com.jelly.farmhelperv2.config.FarmHelperConfig; +import com.jelly.farmhelperv2.feature.impl.AutoWardrobe; import com.jelly.farmhelperv2.handler.GameStateHandler; import com.jelly.farmhelperv2.pathfinder.FlyPathFinderExecutor; import com.jelly.farmhelperv2.util.LogUtils; @@ -70,7 +71,8 @@ public void update() { } @SubCommand - public void test(){ - LogUtils.sendSuccess("SprayonatorState: " + GameStateHandler.getInstance().getSprayonatorState()); + public void wd(int slot) { + AutoWardrobe.instance.swapTo(slot); } + } diff --git a/src/main/java/com/jelly/farmhelperv2/config/FarmHelperConfig.java b/src/main/java/com/jelly/farmhelperv2/config/FarmHelperConfig.java index 70a5562e..40ca9b59 100644 --- a/src/main/java/com/jelly/farmhelperv2/config/FarmHelperConfig.java +++ b/src/main/java/com/jelly/farmhelperv2/config/FarmHelperConfig.java @@ -51,6 +51,7 @@ public class FarmHelperConfig extends Config { private transient static final String JACOBS_CONTEST = "Jacob's Contest"; private transient static final String VISITORS_MACRO = "Visitors Macro"; private transient static final String PESTS_DESTROYER = "Pests Destroyer"; + private transient static final String PEST_FARMER = "Pest Farmer"; private transient static final String AUTO_PEST_EXCHANGE = "Auto Pest Exchange"; private transient static final String AUTO_GOD_POT = "Auto God Pot"; private transient static final String AUTO_SELL = "Auto Sell"; @@ -1290,7 +1291,32 @@ public static void triggerManuallyPestsDestroyer() { size = 2 ) public static OneKeyBind enablePestsDestroyerKeyBind = new OneKeyBind(Keyboard.KEY_NONE); + // + // + @Switch( + name = "Swap Armor Before Killing", category = PESTS_DESTROYER, subcategory = "Armor Swapper" + ) + public static boolean pestSwapArmorBefore = false; + + @Slider( + name = "Wardrobe Slot To Kill With", category = PESTS_DESTROYER, subcategory = "Armor Swapper", + description = "Wardrobe slot to use before turning on pest destroyer", + min = 1, max = 18 + ) + public static int pestArmorSlot0 = 1; + + @Switch( + name = "Swap Armor After Killing", category = PESTS_DESTROYER, subcategory = "Armor Swapper" + ) + public static boolean pestSwapArmorAfter = false; + + @Slider( + name = "Wardrobe Slot To Farm With", category = PESTS_DESTROYER, subcategory = "Armor Swapper", + description = "Wardrobe slot to equip after turning off pest destroyer", + min = 1, max = 18 + ) + public static int pestArmorSlot1 = 1; // // @@ -1350,6 +1376,51 @@ public static void triggerManuallyPestsDestroyer() { // // + // + @Header( + text = "Read the comments below this page before using pest farmer.", + category = PEST_FARMER, size = 2 + ) + public static boolean ignored1; + + @Switch( + name = "Enable Pest Farming", category = PEST_FARMER, + description = "Enables Pest Farming" + ) + public static boolean pestFarming = false; + + @Slider( + name = "Farming Armor Slot", category = PEST_FARMER, + min = 1, max = 18 + ) + public static int pestFarmingSet0Slot = 1; + + @Slider( + name = "Pest Chance Armor Slot", category = PEST_FARMER, + min = 1, max = 18 + ) + public static int pestFarmingSet1Slot = 1; + + @Slider( + name = "Pest Spawn Timer (In seconds)", category = PEST_FARMER, + description = "The time it should wait after pests spawn to swap slots (should be your pest spawn time - 5/10 seconds)", + min = 30, max = 300 + ) + public static int pestFarmingWaitTime = 255; + + @Info( + text = "Use this Auto-Pet Rule: 1. On Equip Farming Armor -> Farming Pet | 2. On Equip Pest Chance Armor -> Slug Pet | 3. On Enter Combat -> Hedgehog Pet", + type = InfoType.INFO, category = PEST_FARMER + ) + public static boolean ignored2; + + @Info( + text = "Use Armor Swapper in Pest Destroyer. Swap to Farming Armor On Start Just in case Pest Farmer doesn't do that itself.", + type = InfoType.INFO, category = PEST_FARMER + ) + public static boolean ignored3; + + // // // @Switch( @@ -2256,6 +2327,9 @@ public FarmHelperConfig() { this.addDependency("rotationTimeDuringJacob", "customRotationDelaysDuringJacob"); this.addDependency("rotationTimeRandomnessDuringJacob", "customRotationDelaysDuringJacob"); + this.addDependency("pestArmorSlot0", "pestSwapArmorBefore"); + this.addDependency("pestArmorSlot1", "pestSwapArmorAfter"); + this.addDependency("leaveTime", "leaveTimer"); this.hideIf("shownWelcomeGUI", () -> true); diff --git a/src/main/java/com/jelly/farmhelperv2/feature/FeatureManager.java b/src/main/java/com/jelly/farmhelperv2/feature/FeatureManager.java index 4baef0a3..e571d82c 100644 --- a/src/main/java/com/jelly/farmhelperv2/feature/FeatureManager.java +++ b/src/main/java/com/jelly/farmhelperv2/feature/FeatureManager.java @@ -48,7 +48,9 @@ public List fillFeatures() { Scheduler.getInstance(), UngrabMouse.getInstance(), VisitorsMacro.getInstance(), - PiPMode.getInstance() + PiPMode.getInstance(), + AutoWardrobe.instance, + PestFarmer.instance// sue me ); features.addAll(featuresList); return features; diff --git a/src/main/java/com/jelly/farmhelperv2/feature/impl/AutoWardrobe.java b/src/main/java/com/jelly/farmhelperv2/feature/impl/AutoWardrobe.java index e8d8797b..3a9cdd60 100644 --- a/src/main/java/com/jelly/farmhelperv2/feature/impl/AutoWardrobe.java +++ b/src/main/java/com/jelly/farmhelperv2/feature/impl/AutoWardrobe.java @@ -1,4 +1,200 @@ package com.jelly.farmhelperv2.feature.impl; -public class AutoWardrobe { +import com.jelly.farmhelperv2.config.FarmHelperConfig; +import com.jelly.farmhelperv2.feature.IFeature; +import com.jelly.farmhelperv2.util.InventoryUtils; +import com.jelly.farmhelperv2.util.InventoryUtils.ClickMode; +import com.jelly.farmhelperv2.util.InventoryUtils.ClickType; +import com.jelly.farmhelperv2.util.LogUtils; +import com.jelly.farmhelperv2.util.PlayerUtils; +import com.jelly.farmhelperv2.util.helper.Clock; +import kotlinx.serialization.descriptors.PolymorphicKind.OPEN; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.inventory.GuiChest; +import net.minecraft.inventory.ContainerChest; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent; + +public class AutoWardrobe implements IFeature { + + public static AutoWardrobe instance = new AutoWardrobe(); + private static final Minecraft mc = Minecraft.getMinecraft(); + private boolean enabled = false; + private int swapTo = -1; + private State state = State.STARTING; + private Clock timer = new Clock(); + + @Override + public String getName() { + return "AutoWardrobe"; + } + + @Override + public boolean isRunning() { + return enabled; + } + + @Override + public boolean shouldPauseMacroExecution() { + return true; + } + + @Override + public boolean shouldStartAtMacroStart() { + return false; + } + + @Override + public void resetStatesAfterMacroDisabled() { + + } + + @Override + public boolean isToggled() { + return true; + } + + @Override + public boolean shouldCheckForFailsafes() { + return false; + } + + public void swapTo(int slot) { + if (slot < 1 || slot > 18) { + return; + } + + swapTo = slot; + enabled = true; + LogUtils.sendSuccess("[AutoWardrobe] Starting. Swapping to slot " + slot); + } + + @Override + public void stop() { + if (!enabled) { + return; + } + enabled = false; + swapTo = -1; + state = State.STARTING; + timer.reset(); + + LogUtils.sendSuccess("[AutoWardrobe] Stopping."); + } + + public void setState(State state, long time) { + this.state = state; + timer.schedule(time); + if (time == 0) { + timer.reset(); + } + } + + public boolean isTimerRunning() { + return timer.isScheduled() && !timer.passed(); + } + + public boolean hasTimerEnded() { + return !timer.isScheduled() || timer.passed(); + } + + @SubscribeEvent + public void onTick(ClientTickEvent event) { + if (!enabled) { + return; + } + + switch (state) { + case STARTING: + setState(State.OPENING_WD, FarmHelperConfig.getRandomGUIMacroDelay()); + break; + case OPENING_WD: + if (isTimerRunning()) { + return; + } + + mc.thePlayer.sendChatMessage("/wd"); + setState(State.WD_VERIFY, 2000); + break; + case WD_VERIFY: + if (hasTimerEnded()) { + LogUtils.sendError("Could not open wardrobe in under 2 seconds. Stopping"); + setState(State.ENDING, 0); + return; + } + + if (inventoryName().startsWith("Wardrobe")) { + setState(State.NAVIGATING, FarmHelperConfig.getRandomGUIMacroDelay()); + } + break; + case NAVIGATING: + if (isTimerRunning()) { + return; + } + if (swapTo < 9) { + setState(State.CLICKING_SLOT, 0); + return; + } + InventoryUtils.clickContainerSlot(InventoryUtils.getSlotIdOfItemInContainer("Next Page"), ClickType.LEFT, ClickMode.PICKUP); + setState(State.NAVIGATION_VERIFY, 2000); + break; + case NAVIGATION_VERIFY: + if (hasTimerEnded()) { + LogUtils.sendError("Could not switch to next page in under 2 seconds. Stopping"); + setState(State.ENDING, 0); + return; + } + + if (inventoryName().endsWith("2)")) { + setState(State.CLICKING_SLOT, FarmHelperConfig.getRandomGUIMacroDelay()); + } + break; + case CLICKING_SLOT: + if (isTimerRunning()) { + return; + } + int slotId = 35 + (swapTo - 1) % 9 + 1; + Slot slot = InventoryUtils.getSlotOfIdInContainer(slotId); + if (slot != null && slot.getHasStack()) { + ItemStack stack = slot.getStack(); + // remove this to make it unequip armor (click the same slot) + if (stack.hasDisplayName() && !stack.getDisplayName().contains("Equipped") && !stack.getDisplayName().contains("Locked")) { + InventoryUtils.clickContainerSlot(35 + (swapTo - 1) % 9 + 1, ClickType.LEFT, ClickMode.PICKUP); + } + } + setState(State.ENDING, FarmHelperConfig.getRandomGUIMacroDelay()); + break; + case ENDING: + if (isTimerRunning()) { + return; + } + PlayerUtils.closeScreen(); + stop(); + break; + } + } + + private String inventoryName() { + try { + if (mc.currentScreen instanceof GuiChest) { + final ContainerChest chest = (ContainerChest) mc.thePlayer.openContainer; + if (chest == null) { + return ""; + } + final IInventory inv = chest.getLowerChestInventory(); + return inv.hasCustomName() ? inv.getName() : ""; + } + return ""; + } catch (Exception e) { + return ""; + } + } + + + enum State { + STARTING, OPENING_WD, WD_VERIFY, NAVIGATING, NAVIGATION_VERIFY, CLICKING_SLOT, ENDING + } } diff --git a/src/main/java/com/jelly/farmhelperv2/feature/impl/BPSTracker.java b/src/main/java/com/jelly/farmhelperv2/feature/impl/BPSTracker.java index 96c836de..5c32aed2 100644 --- a/src/main/java/com/jelly/farmhelperv2/feature/impl/BPSTracker.java +++ b/src/main/java/com/jelly/farmhelperv2/feature/impl/BPSTracker.java @@ -93,11 +93,7 @@ public void start() { } private boolean checkForBPS(AbstractMacro.State currentState) { - return currentState != AbstractMacro.State.NONE && - currentState != AbstractMacro.State.DROPPING && - currentState != AbstractMacro.State.SWITCHING_SIDE && - currentState != AbstractMacro.State.SWITCHING_LANE && - Minecraft.getMinecraft().currentScreen == null; + return currentState.ordinal() > 3 && Minecraft.getMinecraft().currentScreen == null; } public float elapsedTime = 0; diff --git a/src/main/java/com/jelly/farmhelperv2/feature/impl/PestFarmer.java b/src/main/java/com/jelly/farmhelperv2/feature/impl/PestFarmer.java index d1e389cf..8e266f10 100644 --- a/src/main/java/com/jelly/farmhelperv2/feature/impl/PestFarmer.java +++ b/src/main/java/com/jelly/farmhelperv2/feature/impl/PestFarmer.java @@ -1,5 +1,160 @@ package com.jelly.farmhelperv2.feature.impl; -public class PestFarmer { +import com.jelly.farmhelperv2.config.FarmHelperConfig; +import com.jelly.farmhelperv2.failsafe.FailsafeManager; +import com.jelly.farmhelperv2.feature.FeatureManager; +import com.jelly.farmhelperv2.feature.IFeature; +import com.jelly.farmhelperv2.handler.GameStateHandler; +import com.jelly.farmhelperv2.handler.MacroHandler; +import com.jelly.farmhelperv2.util.LogUtils; +import net.minecraft.client.Minecraft; +import net.minecraftforge.client.event.ClientChatReceivedEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent.Phase; +public class PestFarmer implements IFeature { + + public static PestFarmer instance = new PestFarmer(); + private final Minecraft mc = Minecraft.getMinecraft(); + private boolean enabled = false; + private long pestSpawnTime = 0L; + private int swapTo = 1; // 0 = fermento, 1 = biohazard + private State state = State.SWAPPING; + private boolean pestSpawned = false; + + @Override + public String getName() { + return "PestFarmer"; + } + + @Override + public boolean isRunning() { + return enabled; + } + + @Override + public boolean shouldPauseMacroExecution() { + return true; + } + + @Override + public boolean shouldStartAtMacroStart() { + return false; + } + + @Override + public void resetStatesAfterMacroDisabled() { + state = State.SWAPPING; + pestSpawned = false; + swapTo = -1; + } + + @Override + public boolean isToggled() { + return FarmHelperConfig.pestFarming; + } + + @Override + public boolean shouldCheckForFailsafes() { + return false; + } + + @Override + public void start() { + if (enabled) { + return; + } + MacroHandler.getInstance().pauseMacro(); + enabled = true; + } + + @Override + public void stop() { + if (!enabled) { + return; + } + + enabled = false; + state = State.SWAPPING; + if (MacroHandler.getInstance().isMacroToggled()) { + MacroHandler.getInstance().resumeMacro(); + } + } + + @SubscribeEvent + public void onTick(ClientTickEvent event) { + if (event.phase != Phase.START) { + return; + } + if (!this.isToggled() || !MacroHandler.getInstance().isCurrentMacroEnabled() || MacroHandler.getInstance().getCurrentMacro().get().currentState.ordinal() < 4 || enabled) { + return; + } + if (!GameStateHandler.getInstance().inGarden()) { + return; + } + if (GameStateHandler.getInstance().getServerClosingSeconds().isPresent()) { + return; + } + if (!Scheduler.getInstance().isFarming()) { + return; + } + if (FailsafeManager.getInstance().triggeredFailsafe.isPresent()) { + return; + } + if (FeatureManager.getInstance().isAnyOtherFeatureEnabled(this)) { + return; + } + + if (pestSpawned) { + long timeDiff = System.currentTimeMillis() - pestSpawnTime; + if (timeDiff >= FarmHelperConfig.pestFarmingWaitTime * 1000L && swapTo != 1) { + swapTo = 1; + start(); + pestSpawned = false; + } else if(swapTo != 0) { + swapTo = 0; + start(); + } + } + } + + @SubscribeEvent + public void onChat(ClientChatReceivedEvent event) { + if (event.type != 0) { + return; + } + String message = event.message.getUnformattedText(); + if (message.startsWith("§6§lYUCK!") || message.startsWith("§6§lEWW!") || message.startsWith("§6§lGROSS!")) { + pestSpawnTime = System.currentTimeMillis(); + pestSpawned = true; + LogUtils.sendDebug("[PestFarmer] Pest Spawned."); + } + } + + @SubscribeEvent + public void onTickSwap(ClientTickEvent event) { + if (!enabled) { + return; + } + + switch (state) { + case SWAPPING: + AutoWardrobe.instance.swapTo(swapTo == 0 ? FarmHelperConfig.pestFarmingSet0Slot : FarmHelperConfig.pestFarmingSet1Slot); + state = State.ENDING; + break; + case ENDING: + if (AutoWardrobe.instance.isRunning()) { + return; + } + stop(); + break; + } + } + + // bleh, its only for the tracker basically + enum State { + SWAPPING, + ENDING + } } diff --git a/src/main/java/com/jelly/farmhelperv2/macro/AbstractMacro.java b/src/main/java/com/jelly/farmhelperv2/macro/AbstractMacro.java index afda426a..879dbebd 100644 --- a/src/main/java/com/jelly/farmhelperv2/macro/AbstractMacro.java +++ b/src/main/java/com/jelly/farmhelperv2/macro/AbstractMacro.java @@ -382,14 +382,15 @@ public void setBreakTime(double time, double timeBefore) { public enum State { // Add default values like NONE and DROPPING + // DO NOT REARRAGE, IT WILL BREAK PEST FARMER IF YOU DO - osama NONE, DROPPING, + SWITCHING_SIDE, + SWITCHING_LANE, LEFT, RIGHT, BACKWARD, FORWARD, - SWITCHING_SIDE, - SWITCHING_LANE, A, D, diff --git a/src/main/java/com/jelly/farmhelperv2/mixin/client/MixinMinecraft.java b/src/main/java/com/jelly/farmhelperv2/mixin/client/MixinMinecraft.java index 9925d6cd..e54eec0f 100644 --- a/src/main/java/com/jelly/farmhelperv2/mixin/client/MixinMinecraft.java +++ b/src/main/java/com/jelly/farmhelperv2/mixin/client/MixinMinecraft.java @@ -16,10 +16,12 @@ import net.minecraft.init.Blocks; import net.minecraft.util.BlockPos; import net.minecraft.util.MovingObjectPosition; +import org.lwjgl.opengl.Display; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(value = Minecraft.class, priority = Integer.MAX_VALUE) @@ -110,4 +112,12 @@ private void sendClickBlockToController(CallbackInfo ci) { } } + + @Redirect(method = "setIngameFocus", at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/Display;isActive()Z")) + public boolean isActive() { + if (MacroHandler.getInstance().isMacroToggled()) { + return true; + } + return Display.isActive(); + } } \ No newline at end of file From 2b9660040ad9ca1cb7a8552aff7ca4e292f89c29 Mon Sep 17 00:00:00 2001 From: Osama Date: Sun, 1 Dec 2024 20:30:09 +0600 Subject: [PATCH 03/10] Pest Farmer --- gradle.properties | 2 +- .../command/FarmHelperMainCommand.java | 8 +--- .../farmhelperv2/config/FarmHelperConfig.java | 46 ++++++++++++++++--- .../feature/impl/AutoWardrobe.java | 22 +++++---- .../farmhelperv2/feature/impl/PestFarmer.java | 29 ++++++++---- .../feature/impl/PestsDestroyer.java | 4 +- .../farmhelperv2/macro/AbstractMacro.java | 13 +++++- .../mixin/client/MixinMinecraft.java | 5 ++ 8 files changed, 97 insertions(+), 32 deletions(-) diff --git a/gradle.properties b/gradle.properties index 8cb0c277..7af6b265 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,5 +4,5 @@ baseGroup=com.jelly.farmhelperv2 mcVersion=1.8.9 modid=farmhelperv2 modName=FarmHelper -version=2.9.2 +version=2.9.0 shouldRelease=true diff --git a/src/main/java/com/jelly/farmhelperv2/command/FarmHelperMainCommand.java b/src/main/java/com/jelly/farmhelperv2/command/FarmHelperMainCommand.java index 851f3cb4..9c1bc20f 100644 --- a/src/main/java/com/jelly/farmhelperv2/command/FarmHelperMainCommand.java +++ b/src/main/java/com/jelly/farmhelperv2/command/FarmHelperMainCommand.java @@ -69,10 +69,4 @@ public void update() { PlayerUtils.closeScreen(); FarmHelperConfig.checkForUpdate(); } - - @SubCommand - public void wd(int slot) { - AutoWardrobe.instance.swapTo(slot); - } - -} +} \ No newline at end of file diff --git a/src/main/java/com/jelly/farmhelperv2/config/FarmHelperConfig.java b/src/main/java/com/jelly/farmhelperv2/config/FarmHelperConfig.java index 40ca9b59..b69d244b 100644 --- a/src/main/java/com/jelly/farmhelperv2/config/FarmHelperConfig.java +++ b/src/main/java/com/jelly/farmhelperv2/config/FarmHelperConfig.java @@ -1197,6 +1197,11 @@ public class FarmHelperConfig extends Config { ) public static int pestAdditionalGUIDelay = 0; + @Switch( + name = "Force Enable Pest Destroyer at X Pests", category = PESTS_DESTROYER, subcategory = "Pests Destroyer" + ) + public static boolean pestForceEnable = false; + @Switch( name = "Sprint while flying", category = PESTS_DESTROYER, subcategory = "Pests Destroyer", description = "Sprints while flying" @@ -1320,7 +1325,6 @@ public static void triggerManuallyPestsDestroyer() { // // - @Switch( name = "Pests ESP", category = PESTS_DESTROYER, subcategory = "Drawings", description = "Draws a box around pests" @@ -1389,6 +1393,12 @@ public static void triggerManuallyPestsDestroyer() { ) public static boolean pestFarming = false; + @Switch( + name = "Hold Daedalus Axe", category = PEST_FARMER, + description = "Farms with daedalus axe while waiting for pests to spawn" + ) + public static boolean pestFarmingHoldDaedalus = false; + @Slider( name = "Farming Armor Slot", category = PEST_FARMER, min = 1, max = 18 @@ -1409,16 +1419,40 @@ public static void triggerManuallyPestsDestroyer() { public static int pestFarmingWaitTime = 255; @Info( - text = "Use this Auto-Pet Rule: 1. On Equip Farming Armor -> Farming Pet | 2. On Equip Pest Chance Armor -> Slug Pet | 3. On Enter Combat -> Hedgehog Pet", - type = InfoType.INFO, category = PEST_FARMER + text = "It's supposed to swap armor before pest spawns, swap back after pest spawns and kill with Pest Destryoer/the other one.", + type = InfoType.INFO, category = PEST_FARMER, size = 2 + ) + public static boolean ignored0; + @Info( + text = "Use this Auto-Pet Rule:", + type = InfoType.INFO, category = PEST_FARMER, size = 2 ) public static boolean ignored2; - @Info( - text = "Use Armor Swapper in Pest Destroyer. Swap to Farming Armor On Start Just in case Pest Farmer doesn't do that itself.", - type = InfoType.INFO, category = PEST_FARMER + text = " 1. On Gain Crop Collection -> Farming Pet, Except if slug is Equipped", + type = InfoType.INFO, category = PEST_FARMER, size = 2 ) public static boolean ignored3; + @Info( + text = " 2. On Equip Farming Armor -> Farming Pet", + type = InfoType.INFO, category = PEST_FARMER, size = 2 + ) + public static boolean ignored4; + @Info( + text = " 3. On Equip Pest Chance Armor -> Slug Pet", + type = InfoType.INFO, category = PEST_FARMER, size = 2 + ) + public static boolean ignored5; + @Info( + text = " 4. On Enter Combat -> Hedgehog Pet", + type = InfoType.INFO, category = PEST_FARMER, size = 2 + ) + public static boolean ignored6; + @Info( + text = "Use Armor Swapper in Pest Destroyer. Swap to Farming Armor On Start Just in case Pest Farmer doesn't do that itself.", + type = InfoType.INFO, category = PEST_FARMER, size = 2 + ) + public static boolean ignored7; // // diff --git a/src/main/java/com/jelly/farmhelperv2/feature/impl/AutoWardrobe.java b/src/main/java/com/jelly/farmhelperv2/feature/impl/AutoWardrobe.java index 3a9cdd60..80323821 100644 --- a/src/main/java/com/jelly/farmhelperv2/feature/impl/AutoWardrobe.java +++ b/src/main/java/com/jelly/farmhelperv2/feature/impl/AutoWardrobe.java @@ -8,7 +8,6 @@ import com.jelly.farmhelperv2.util.LogUtils; import com.jelly.farmhelperv2.util.PlayerUtils; import com.jelly.farmhelperv2.util.helper.Clock; -import kotlinx.serialization.descriptors.PolymorphicKind.OPEN; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.inventory.GuiChest; import net.minecraft.inventory.ContainerChest; @@ -21,7 +20,8 @@ public class AutoWardrobe implements IFeature { public static AutoWardrobe instance = new AutoWardrobe(); - private static final Minecraft mc = Minecraft.getMinecraft(); + public static int activeSlot = -1; + private final Minecraft mc = Minecraft.getMinecraft(); private boolean enabled = false; private int swapTo = -1; private State state = State.STARTING; @@ -49,7 +49,7 @@ public boolean shouldStartAtMacroStart() { @Override public void resetStatesAfterMacroDisabled() { - + activeSlot = -1; } @Override @@ -122,7 +122,7 @@ public void onTick(ClientTickEvent event) { case WD_VERIFY: if (hasTimerEnded()) { LogUtils.sendError("Could not open wardrobe in under 2 seconds. Stopping"); - setState(State.ENDING, 0); + setState(State.WAITING, 0); return; } @@ -144,7 +144,7 @@ public void onTick(ClientTickEvent event) { case NAVIGATION_VERIFY: if (hasTimerEnded()) { LogUtils.sendError("Could not switch to next page in under 2 seconds. Stopping"); - setState(State.ENDING, 0); + setState(State.WAITING, 0); return; } @@ -165,13 +165,19 @@ public void onTick(ClientTickEvent event) { InventoryUtils.clickContainerSlot(35 + (swapTo - 1) % 9 + 1, ClickType.LEFT, ClickMode.PICKUP); } } - setState(State.ENDING, FarmHelperConfig.getRandomGUIMacroDelay()); + activeSlot = swapTo; + setState(State.WAITING, FarmHelperConfig.getRandomGUIMacroDelay()); break; - case ENDING: + case WAITING: if (isTimerRunning()) { return; } PlayerUtils.closeScreen(); + setState(State.ENDING, FarmHelperConfig.getRandomGUIMacroDelay()); + break; + // this is just here to give a bit extra pause before it stops + case ENDING: + if (isTimerRunning()) return; stop(); break; } @@ -195,6 +201,6 @@ private String inventoryName() { enum State { - STARTING, OPENING_WD, WD_VERIFY, NAVIGATING, NAVIGATION_VERIFY, CLICKING_SLOT, ENDING + STARTING, OPENING_WD, WD_VERIFY, NAVIGATING, NAVIGATION_VERIFY, CLICKING_SLOT, WAITING, ENDING } } diff --git a/src/main/java/com/jelly/farmhelperv2/feature/impl/PestFarmer.java b/src/main/java/com/jelly/farmhelperv2/feature/impl/PestFarmer.java index 8e266f10..721d897d 100644 --- a/src/main/java/com/jelly/farmhelperv2/feature/impl/PestFarmer.java +++ b/src/main/java/com/jelly/farmhelperv2/feature/impl/PestFarmer.java @@ -1,12 +1,16 @@ package com.jelly.farmhelperv2.feature.impl; +import com.jelly.farmhelperv2.FarmHelper; import com.jelly.farmhelperv2.config.FarmHelperConfig; import com.jelly.farmhelperv2.failsafe.FailsafeManager; import com.jelly.farmhelperv2.feature.FeatureManager; import com.jelly.farmhelperv2.feature.IFeature; import com.jelly.farmhelperv2.handler.GameStateHandler; import com.jelly.farmhelperv2.handler.MacroHandler; +import com.jelly.farmhelperv2.util.InventoryUtils; import com.jelly.farmhelperv2.util.LogUtils; +import java.util.ArrayList; +import java.util.List; import net.minecraft.client.Minecraft; import net.minecraftforge.client.event.ClientChatReceivedEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; @@ -16,12 +20,12 @@ public class PestFarmer implements IFeature { public static PestFarmer instance = new PestFarmer(); - private final Minecraft mc = Minecraft.getMinecraft(); private boolean enabled = false; private long pestSpawnTime = 0L; - private int swapTo = 1; // 0 = fermento, 1 = biohazard + private int swapTo = -1; private State state = State.SWAPPING; private boolean pestSpawned = false; + private boolean holdDae = false; @Override public String getName() { @@ -47,6 +51,7 @@ public boolean shouldStartAtMacroStart() { public void resetStatesAfterMacroDisabled() { state = State.SWAPPING; pestSpawned = false; + holdDae = false; swapTo = -1; } @@ -82,6 +87,10 @@ public void stop() { } } + public boolean holdDaedalus() { + return holdDae && FarmHelperConfig.pestFarming && FarmHelperConfig.pestFarmingHoldDaedalus && AutoWardrobe.activeSlot == FarmHelperConfig.pestFarmingSet1Slot && InventoryUtils.holdItem("Daedalus Axe"); + } + @SubscribeEvent public void onTick(ClientTickEvent event) { if (event.phase != Phase.START) { @@ -108,12 +117,16 @@ public void onTick(ClientTickEvent event) { if (pestSpawned) { long timeDiff = System.currentTimeMillis() - pestSpawnTime; - if (timeDiff >= FarmHelperConfig.pestFarmingWaitTime * 1000L && swapTo != 1) { - swapTo = 1; - start(); + if (timeDiff >= FarmHelperConfig.pestFarmingWaitTime * 1000L && AutoWardrobe.activeSlot != FarmHelperConfig.pestFarmingSet1Slot) { + LogUtils.sendDebug("Swapping to " + FarmHelperConfig.pestFarmingSet1Slot); + swapTo = FarmHelperConfig.pestFarmingSet1Slot; pestSpawned = false; - } else if(swapTo != 0) { - swapTo = 0; + holdDae = true; + start(); + } else if (AutoWardrobe.activeSlot != FarmHelperConfig.pestFarmingSet0Slot) { + LogUtils.sendDebug("Swapping to " + FarmHelperConfig.pestFarmingSet0Slot); + swapTo = FarmHelperConfig.pestFarmingSet0Slot; + holdDae = false; start(); } } @@ -140,7 +153,7 @@ public void onTickSwap(ClientTickEvent event) { switch (state) { case SWAPPING: - AutoWardrobe.instance.swapTo(swapTo == 0 ? FarmHelperConfig.pestFarmingSet0Slot : FarmHelperConfig.pestFarmingSet1Slot); + AutoWardrobe.instance.swapTo(swapTo); state = State.ENDING; break; case ENDING: diff --git a/src/main/java/com/jelly/farmhelperv2/feature/impl/PestsDestroyer.java b/src/main/java/com/jelly/farmhelperv2/feature/impl/PestsDestroyer.java index 21dfbe9a..962dcf03 100644 --- a/src/main/java/com/jelly/farmhelperv2/feature/impl/PestsDestroyer.java +++ b/src/main/java/com/jelly/farmhelperv2/feature/impl/PestsDestroyer.java @@ -497,7 +497,9 @@ public void onTickExecute(TickEvent.ClientTickEvent event) { if (finishing) { currentSlot = FarmHelperConfig.pestArmorSlot1; } - AutoWardrobe.instance.swapTo(currentSlot); + if (AutoWardrobe.activeSlot != currentSlot) { + AutoWardrobe.instance.swapTo(currentSlot); + } } state = States.ARMOR_SWAP_VERIFY; break; diff --git a/src/main/java/com/jelly/farmhelperv2/macro/AbstractMacro.java b/src/main/java/com/jelly/farmhelperv2/macro/AbstractMacro.java index 879dbebd..d03d89cc 100644 --- a/src/main/java/com/jelly/farmhelperv2/macro/AbstractMacro.java +++ b/src/main/java/com/jelly/farmhelperv2/macro/AbstractMacro.java @@ -7,6 +7,8 @@ import com.jelly.farmhelperv2.feature.FeatureManager; import com.jelly.farmhelperv2.feature.impl.DesyncChecker; import com.jelly.farmhelperv2.feature.impl.LagDetector; +import com.jelly.farmhelperv2.feature.impl.PestFarmer; +import com.jelly.farmhelperv2.feature.impl.PestsDestroyer; import com.jelly.farmhelperv2.handler.GameStateHandler; import com.jelly.farmhelperv2.handler.MacroHandler; import com.jelly.farmhelperv2.handler.RotationHandler; @@ -147,6 +149,13 @@ public void onTick() { } checkOnSpawnClock.schedule(5000); } + + if (FarmHelperConfig.pestForceEnable && PestsDestroyer.getInstance().canEnableMacro()) { + PestsDestroyer.getInstance().start(); + LogUtils.sendDebug("Activating Pests Destroyer"); + return; + } + if (mc.thePlayer.getPosition().getY() < 0) { LogUtils.sendError("Build a wall between the rewarp point and the void to prevent falling out of the garden! Disabling the macro..."); MacroHandler.getInstance().disableMacro(); @@ -226,7 +235,9 @@ public void onTick() { return; } - PlayerUtils.getTool(); + if (!PestFarmer.instance.holdDaedalus()) { + PlayerUtils.getTool(); + } // Update or invoke state, based on if player is moving or not if (GameStateHandler.getInstance().canChangeDirection()) { diff --git a/src/main/java/com/jelly/farmhelperv2/mixin/client/MixinMinecraft.java b/src/main/java/com/jelly/farmhelperv2/mixin/client/MixinMinecraft.java index e54eec0f..7745d10b 100644 --- a/src/main/java/com/jelly/farmhelperv2/mixin/client/MixinMinecraft.java +++ b/src/main/java/com/jelly/farmhelperv2/mixin/client/MixinMinecraft.java @@ -4,12 +4,14 @@ import com.jelly.farmhelperv2.feature.impl.BanInfoWS; import com.jelly.farmhelperv2.handler.GameStateHandler; import com.jelly.farmhelperv2.handler.MacroHandler; +import com.jelly.farmhelperv2.util.LogUtils; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.multiplayer.PlayerControllerMP; +import net.minecraft.client.multiplayer.ServerData; import net.minecraft.client.multiplayer.WorldClient; import net.minecraft.client.settings.GameSettings; import net.minecraft.entity.Entity; @@ -51,6 +53,8 @@ public class MixinMinecraft { @Shadow public EntityPlayerSP thePlayer; + @Shadow private ServerData currentServerData; + @Inject(method = "sendClickBlockToController", at = @At("RETURN")) private void sendClickBlockToController(CallbackInfo ci) { if (!FarmHelperConfig.fastBreak || !(MacroHandler.getInstance().getCurrentMacro().isPresent() && MacroHandler.getInstance().isMacroToggled())) { @@ -115,6 +119,7 @@ private void sendClickBlockToController(CallbackInfo ci) { @Redirect(method = "setIngameFocus", at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/Display;isActive()Z")) public boolean isActive() { + System.out.println("Trying to set in game focus. Macro Toggled: " + MacroHandler.getInstance().isMacroToggled()); if (MacroHandler.getInstance().isMacroToggled()) { return true; } From 96489440e8d3e4b1cbbdecdd3ae8cfb0bfeb3801 Mon Sep 17 00:00:00 2001 From: Osama Date: Mon, 2 Dec 2024 18:22:42 +0600 Subject: [PATCH 04/10] Fixed Spacing --- .../farmhelperv2/config/FarmHelperConfig.java | 112 +++--- .../feature/impl/AutoWardrobe.java | 324 +++++++++--------- .../farmhelperv2/feature/impl/PestFarmer.java | 262 +++++++------- .../mixin/client/MixinMinecraft.java | 2 - 4 files changed, 352 insertions(+), 348 deletions(-) diff --git a/src/main/java/com/jelly/farmhelperv2/config/FarmHelperConfig.java b/src/main/java/com/jelly/farmhelperv2/config/FarmHelperConfig.java index b69d244b..04743128 100644 --- a/src/main/java/com/jelly/farmhelperv2/config/FarmHelperConfig.java +++ b/src/main/java/com/jelly/farmhelperv2/config/FarmHelperConfig.java @@ -43,6 +43,7 @@ // THIS IS RAT - CatalizCS @SuppressWarnings({"unused", "DefaultAnnotationParam"}) public class FarmHelperConfig extends Config { + private transient static final Minecraft mc = Minecraft.getMinecraft(); private transient static final String GENERAL = "General"; private transient static final String MISCELLANEOUS = "Miscellaneous"; @@ -803,26 +804,26 @@ public class FarmHelperConfig extends Config { ) public static boolean openInventoryOnSchedulerBreaks = true; @Switch( - name = "Disconnect during break", category = SCHEDULER, subcategory = "Scheduler", - description = "Logs out of game and logs back in after break ends" + name = "Disconnect during break", category = SCHEDULER, subcategory = "Scheduler", + description = "Logs out of game and logs back in after break ends" ) public static boolean schedulerDisconnectDuringBreak = false; @Switch( - name = "Wait Until Rewarp Point for break", category = SCHEDULER, subcategory = "Scheduler", - description = "Waits until player is standing on rewarp point to take break" + name = "Wait Until Rewarp Point for break", category = SCHEDULER, subcategory = "Scheduler", + description = "Waits until player is standing on rewarp point to take break" ) public static boolean schedulerWaitUntilRewarp = false; @Switch( - name = "Reset Scheduler on Macro Disabled", category = SCHEDULER, subcategory = "Scheduler", - description = "Resets Scheduler When macro is disabled" + name = "Reset Scheduler on Macro Disabled", category = SCHEDULER, subcategory = "Scheduler", + description = "Resets Scheduler When macro is disabled" ) public static boolean schedulerResetOnDisable = true; @Button( - name = "Reset Scheduler", category = SCHEDULER, subcategory = "Scheduler", - text = "Reset Scheduler", description = "Resets Scheduler (Only works when macro is of)" + name = "Reset Scheduler", category = SCHEDULER, subcategory = "Scheduler", + text = "Reset Scheduler", description = "Resets Scheduler (Only works when macro is of)" ) public Runnable schedulerReset = () -> { - if(!MacroHandler.getInstance().isMacroToggled()){ + if (!MacroHandler.getInstance().isMacroToggled()) { boolean old = FarmHelperConfig.schedulerResetOnDisable; FarmHelperConfig.schedulerResetOnDisable = true; Scheduler.getInstance().stop(); @@ -1198,7 +1199,7 @@ public class FarmHelperConfig extends Config { public static int pestAdditionalGUIDelay = 0; @Switch( - name = "Force Enable Pest Destroyer at X Pests", category = PESTS_DESTROYER, subcategory = "Pests Destroyer" + name = "Force Enable Pest Destroyer at X Pests", category = PESTS_DESTROYER, subcategory = "Pests Destroyer" ) public static boolean pestForceEnable = false; @@ -1300,26 +1301,26 @@ public static void triggerManuallyPestsDestroyer() { // @Switch( - name = "Swap Armor Before Killing", category = PESTS_DESTROYER, subcategory = "Armor Swapper" + name = "Swap Armor Before Killing", category = PESTS_DESTROYER, subcategory = "Armor Swapper" ) public static boolean pestSwapArmorBefore = false; @Slider( - name = "Wardrobe Slot To Kill With", category = PESTS_DESTROYER, subcategory = "Armor Swapper", - description = "Wardrobe slot to use before turning on pest destroyer", - min = 1, max = 18 + name = "Wardrobe Slot To Kill With", category = PESTS_DESTROYER, subcategory = "Armor Swapper", + description = "Wardrobe slot to use before turning on pest destroyer", + min = 1, max = 18 ) public static int pestArmorSlot0 = 1; @Switch( - name = "Swap Armor After Killing", category = PESTS_DESTROYER, subcategory = "Armor Swapper" + name = "Swap Armor After Killing", category = PESTS_DESTROYER, subcategory = "Armor Swapper" ) public static boolean pestSwapArmorAfter = false; @Slider( - name = "Wardrobe Slot To Farm With", category = PESTS_DESTROYER, subcategory = "Armor Swapper", - description = "Wardrobe slot to equip after turning off pest destroyer", - min = 1, max = 18 + name = "Wardrobe Slot To Farm With", category = PESTS_DESTROYER, subcategory = "Armor Swapper", + description = "Wardrobe slot to equip after turning off pest destroyer", + min = 1, max = 18 ) public static int pestArmorSlot1 = 1; // @@ -1382,75 +1383,75 @@ public static void triggerManuallyPestsDestroyer() { // @Header( - text = "Read the comments below this page before using pest farmer.", - category = PEST_FARMER, size = 2 + text = "Read the comments below this page before using pest farmer.", + category = PEST_FARMER, size = 2 ) public static boolean ignored1; @Switch( - name = "Enable Pest Farming", category = PEST_FARMER, - description = "Enables Pest Farming" + name = "Enable Pest Farming", category = PEST_FARMER, + description = "Enables Pest Farming" ) public static boolean pestFarming = false; @Switch( - name = "Hold Daedalus Axe", category = PEST_FARMER, - description = "Farms with daedalus axe while waiting for pests to spawn" + name = "Hold Daedalus Axe", category = PEST_FARMER, + description = "Farms with daedalus axe while waiting for pests to spawn" ) public static boolean pestFarmingHoldDaedalus = false; @Slider( - name = "Farming Armor Slot", category = PEST_FARMER, - min = 1, max = 18 + name = "Farming Armor Slot", category = PEST_FARMER, + min = 1, max = 18 ) public static int pestFarmingSet0Slot = 1; @Slider( - name = "Pest Chance Armor Slot", category = PEST_FARMER, - min = 1, max = 18 + name = "Pest Chance Armor Slot", category = PEST_FARMER, + min = 1, max = 18 ) public static int pestFarmingSet1Slot = 1; @Slider( - name = "Pest Spawn Timer (In seconds)", category = PEST_FARMER, - description = "The time it should wait after pests spawn to swap slots (should be your pest spawn time - 5/10 seconds)", - min = 30, max = 300 + name = "Pest Spawn Timer (In seconds)", category = PEST_FARMER, + description = "The time it should wait after pests spawn to swap slots (should be your pest spawn time - 5/10 seconds)", + min = 30, max = 300 ) public static int pestFarmingWaitTime = 255; @Info( - text = "It's supposed to swap armor before pest spawns, swap back after pest spawns and kill with Pest Destryoer/the other one.", - type = InfoType.INFO, category = PEST_FARMER, size = 2 + text = "It's supposed to swap armor before pest spawns, swap back after pest spawns and kill with Pest Destryoer/the other one.", + type = InfoType.INFO, category = PEST_FARMER, size = 2 ) public static boolean ignored0; @Info( - text = "Use this Auto-Pet Rule:", - type = InfoType.INFO, category = PEST_FARMER, size = 2 + text = "Use this Auto-Pet Rule:", + type = InfoType.INFO, category = PEST_FARMER, size = 2 ) public static boolean ignored2; @Info( - text = " 1. On Gain Crop Collection -> Farming Pet, Except if slug is Equipped", - type = InfoType.INFO, category = PEST_FARMER, size = 2 + text = " 1. On Gain Crop Collection -> Farming Pet, Except if slug is Equipped", + type = InfoType.INFO, category = PEST_FARMER, size = 2 ) public static boolean ignored3; @Info( - text = " 2. On Equip Farming Armor -> Farming Pet", - type = InfoType.INFO, category = PEST_FARMER, size = 2 + text = " 2. On Equip Farming Armor -> Farming Pet", + type = InfoType.INFO, category = PEST_FARMER, size = 2 ) public static boolean ignored4; @Info( - text = " 3. On Equip Pest Chance Armor -> Slug Pet", - type = InfoType.INFO, category = PEST_FARMER, size = 2 + text = " 3. On Equip Pest Chance Armor -> Slug Pet", + type = InfoType.INFO, category = PEST_FARMER, size = 2 ) public static boolean ignored5; @Info( - text = " 4. On Enter Combat -> Hedgehog Pet", - type = InfoType.INFO, category = PEST_FARMER, size = 2 + text = " 4. On Enter Combat -> Hedgehog Pet", + type = InfoType.INFO, category = PEST_FARMER, size = 2 ) public static boolean ignored6; @Info( - text = "Use Armor Swapper in Pest Destroyer. Swap to Farming Armor On Start Just in case Pest Farmer doesn't do that itself.", - type = InfoType.INFO, category = PEST_FARMER, size = 2 + text = "Use Armor Swapper in Pest Destroyer. Swap to Farming Armor On Start Just in case Pest Farmer doesn't do that itself.", + type = InfoType.INFO, category = PEST_FARMER, size = 2 ) public static boolean ignored7; @@ -2078,7 +2079,7 @@ public static void triggerManuallyAutoPestExchange() { name = "Reset stats between disabling", category = HUD, subcategory = "Profit Calculator" ) public static boolean resetStatsBetweenDisabling = false; -// @Button( + // @Button( // name = "Reset Profit Calculator", category = HUD, subcategory = "Profit Calculator", // text = "Reset Now", size = 2 // ) @@ -2113,7 +2114,6 @@ public static void triggerManuallyAutoPestExchange() { ) public static boolean debugMode = false; - // // @@ -2194,7 +2194,6 @@ public static void triggerManuallyAutoPestExchange() { ) public static boolean showDebugLogsAboutPDOTT = false; - // @Number(name = "Config Version", category = EXPERIMENTAL, subcategory = "Experimental", min = 0, max = 1337) @@ -2287,8 +2286,8 @@ public FarmHelperConfig() { this.addDependency("sprintWhileFlying", "enablePestsDestroyer"); this.addDependency("pausePestsDestroyerDuringJacobsContest", "enablePestsDestroyer"); - - this.hideIf("infoCookieBuffRequired", () -> GameStateHandler.getInstance().inGarden() || GameStateHandler.getInstance().getCookieBuffState() == BuffState.NOT_ACTIVE); + this.hideIf("infoCookieBuffRequired", + () -> GameStateHandler.getInstance().inGarden() || GameStateHandler.getInstance().getCookieBuffState() == BuffState.NOT_ACTIVE); this.addDependency("sendLogs", "enableWebHook"); this.addDependency("sendStatusUpdates", "enableWebHook"); @@ -2299,9 +2298,9 @@ public FarmHelperConfig() { this.addDependency("discordRemoteControlAddress", "enableRemoteControl"); this.addDependency("remoteControlPort", "enableRemoteControl"); - this.hideIf("infoRemoteControl", () -> Loader.isModLoaded("farmhelperjdadependency")); - this.hideIf("info2RemoteControl", () -> !Loader.isModLoaded("farmhelperjdadependency") || (Loader.isModLoaded("farmhelperjdadependency") && FarmHelper.isJDAVersionCorrect)); + this.hideIf("info2RemoteControl", () -> !Loader.isModLoaded("farmhelperjdadependency") || (Loader.isModLoaded("farmhelperjdadependency") + && FarmHelper.isJDAVersionCorrect)); this.hideIf("failsafeSoundTimes", () -> true); this.addDependency("debugMode", "Streamer Mode", () -> !streamerMode); @@ -2446,8 +2445,9 @@ public static void removeAllRewarps() { public static void saveRewarpConfig() { try { - if (!configRewarpFile.exists()) + if (!configRewarpFile.exists()) { Files.createFile(configRewarpFile.toPath()); + } Files.write(configRewarpFile.toPath(), FarmHelper.gson.toJson(rewarpList).getBytes(StandardCharsets.UTF_8)); } catch (IOException e) { @@ -2460,8 +2460,9 @@ public static MacroEnum getMacro() { } public static long getRandomTimeBetweenChangingRows() { - if (customRowChangeDelaysDuringJacob && GameStateHandler.getInstance().inJacobContest()) + if (customRowChangeDelaysDuringJacob && GameStateHandler.getInstance().inJacobContest()) { return (long) (timeBetweenChangingRowsDuringJacob + (float) Math.random() * randomTimeBetweenChangingRowsDuringJacob); + } return (long) (timeBetweenChangingRows + (float) Math.random() * randomTimeBetweenChangingRows); } @@ -2470,8 +2471,9 @@ public static long getMaxTimeBetweenChangingRows() { } public static long getRandomRotationTime() { - if (customRotationDelaysDuringJacob && GameStateHandler.getInstance().inJacobContest()) + if (customRotationDelaysDuringJacob && GameStateHandler.getInstance().inJacobContest()) { return (long) (rotationTimeDuringJacob + (float) Math.random() * rotationTimeRandomnessDuringJacob); + } return (long) (rotationTime + (float) Math.random() * rotationTimeRandomness); } diff --git a/src/main/java/com/jelly/farmhelperv2/feature/impl/AutoWardrobe.java b/src/main/java/com/jelly/farmhelperv2/feature/impl/AutoWardrobe.java index 80323821..cdcb7de1 100644 --- a/src/main/java/com/jelly/farmhelperv2/feature/impl/AutoWardrobe.java +++ b/src/main/java/com/jelly/farmhelperv2/feature/impl/AutoWardrobe.java @@ -19,188 +19,190 @@ public class AutoWardrobe implements IFeature { - public static AutoWardrobe instance = new AutoWardrobe(); - public static int activeSlot = -1; - private final Minecraft mc = Minecraft.getMinecraft(); - private boolean enabled = false; - private int swapTo = -1; - private State state = State.STARTING; - private Clock timer = new Clock(); - - @Override - public String getName() { - return "AutoWardrobe"; - } - - @Override - public boolean isRunning() { - return enabled; - } - - @Override - public boolean shouldPauseMacroExecution() { - return true; - } - - @Override - public boolean shouldStartAtMacroStart() { - return false; - } - - @Override - public void resetStatesAfterMacroDisabled() { - activeSlot = -1; - } - - @Override - public boolean isToggled() { - return true; - } - - @Override - public boolean shouldCheckForFailsafes() { - return false; - } - - public void swapTo(int slot) { - if (slot < 1 || slot > 18) { - return; + public static AutoWardrobe instance = new AutoWardrobe(); + public static int activeSlot = -1; + private final Minecraft mc = Minecraft.getMinecraft(); + private boolean enabled = false; + private int swapTo = -1; + private State state = State.STARTING; + private Clock timer = new Clock(); + + @Override + public String getName() { + return "AutoWardrobe"; } - swapTo = slot; - enabled = true; - LogUtils.sendSuccess("[AutoWardrobe] Starting. Swapping to slot " + slot); - } + @Override + public boolean isRunning() { + return enabled; + } - @Override - public void stop() { - if (!enabled) { - return; + @Override + public boolean shouldPauseMacroExecution() { + return true; } - enabled = false; - swapTo = -1; - state = State.STARTING; - timer.reset(); - - LogUtils.sendSuccess("[AutoWardrobe] Stopping."); - } - - public void setState(State state, long time) { - this.state = state; - timer.schedule(time); - if (time == 0) { - timer.reset(); + + @Override + public boolean shouldStartAtMacroStart() { + return false; } - } - public boolean isTimerRunning() { - return timer.isScheduled() && !timer.passed(); - } + @Override + public void resetStatesAfterMacroDisabled() { + activeSlot = -1; + } - public boolean hasTimerEnded() { - return !timer.isScheduled() || timer.passed(); - } + @Override + public boolean isToggled() { + return true; + } - @SubscribeEvent - public void onTick(ClientTickEvent event) { - if (!enabled) { - return; + @Override + public boolean shouldCheckForFailsafes() { + return false; } - switch (state) { - case STARTING: - setState(State.OPENING_WD, FarmHelperConfig.getRandomGUIMacroDelay()); - break; - case OPENING_WD: - if (isTimerRunning()) { - return; + public void swapTo(int slot) { + if (slot < 1 || slot > 18) { + return; } - mc.thePlayer.sendChatMessage("/wd"); - setState(State.WD_VERIFY, 2000); - break; - case WD_VERIFY: - if (hasTimerEnded()) { - LogUtils.sendError("Could not open wardrobe in under 2 seconds. Stopping"); - setState(State.WAITING, 0); - return; - } + swapTo = slot; + enabled = true; + LogUtils.sendSuccess("[AutoWardrobe] Starting. Swapping to slot " + slot); + } - if (inventoryName().startsWith("Wardrobe")) { - setState(State.NAVIGATING, FarmHelperConfig.getRandomGUIMacroDelay()); - } - break; - case NAVIGATING: - if (isTimerRunning()) { - return; - } - if (swapTo < 9) { - setState(State.CLICKING_SLOT, 0); - return; - } - InventoryUtils.clickContainerSlot(InventoryUtils.getSlotIdOfItemInContainer("Next Page"), ClickType.LEFT, ClickMode.PICKUP); - setState(State.NAVIGATION_VERIFY, 2000); - break; - case NAVIGATION_VERIFY: - if (hasTimerEnded()) { - LogUtils.sendError("Could not switch to next page in under 2 seconds. Stopping"); - setState(State.WAITING, 0); - return; + @Override + public void stop() { + if (!enabled) { + return; } + enabled = false; + swapTo = -1; + state = State.STARTING; + timer.reset(); - if (inventoryName().endsWith("2)")) { - setState(State.CLICKING_SLOT, FarmHelperConfig.getRandomGUIMacroDelay()); - } - break; - case CLICKING_SLOT: - if (isTimerRunning()) { - return; + LogUtils.sendSuccess("[AutoWardrobe] Stopping."); + } + + public void setState(State state, long time) { + this.state = state; + timer.schedule(time); + if (time == 0) { + timer.reset(); } - int slotId = 35 + (swapTo - 1) % 9 + 1; - Slot slot = InventoryUtils.getSlotOfIdInContainer(slotId); - if (slot != null && slot.getHasStack()) { - ItemStack stack = slot.getStack(); - // remove this to make it unequip armor (click the same slot) - if (stack.hasDisplayName() && !stack.getDisplayName().contains("Equipped") && !stack.getDisplayName().contains("Locked")) { - InventoryUtils.clickContainerSlot(35 + (swapTo - 1) % 9 + 1, ClickType.LEFT, ClickMode.PICKUP); - } + } + + public boolean isTimerRunning() { + return timer.isScheduled() && !timer.passed(); + } + + public boolean hasTimerEnded() { + return !timer.isScheduled() || timer.passed(); + } + + @SubscribeEvent + public void onTick(ClientTickEvent event) { + if (!enabled) { + return; } - activeSlot = swapTo; - setState(State.WAITING, FarmHelperConfig.getRandomGUIMacroDelay()); - break; - case WAITING: - if (isTimerRunning()) { - return; + + switch (state) { + case STARTING: + setState(State.OPENING_WD, FarmHelperConfig.getRandomGUIMacroDelay()); + break; + case OPENING_WD: + if (isTimerRunning()) { + return; + } + + mc.thePlayer.sendChatMessage("/wd"); + setState(State.WD_VERIFY, 2000); + break; + case WD_VERIFY: + if (hasTimerEnded()) { + LogUtils.sendError("Could not open wardrobe in under 2 seconds. Stopping"); + setState(State.WAITING, 0); + return; + } + + if (inventoryName().startsWith("Wardrobe")) { + setState(State.NAVIGATING, FarmHelperConfig.getRandomGUIMacroDelay()); + } + break; + case NAVIGATING: + if (isTimerRunning()) { + return; + } + if (swapTo < 9) { + setState(State.CLICKING_SLOT, 0); + return; + } + InventoryUtils.clickContainerSlot(InventoryUtils.getSlotIdOfItemInContainer("Next Page"), ClickType.LEFT, ClickMode.PICKUP); + setState(State.NAVIGATION_VERIFY, 2000); + break; + case NAVIGATION_VERIFY: + if (hasTimerEnded()) { + LogUtils.sendError("Could not switch to next page in under 2 seconds. Stopping"); + setState(State.WAITING, 0); + return; + } + + if (inventoryName().endsWith("2)")) { + setState(State.CLICKING_SLOT, FarmHelperConfig.getRandomGUIMacroDelay()); + } + break; + case CLICKING_SLOT: + if (isTimerRunning()) { + return; + } + int slotId = 35 + (swapTo - 1) % 9 + 1; + Slot slot = InventoryUtils.getSlotOfIdInContainer(slotId); + if (slot != null && slot.getHasStack()) { + ItemStack stack = slot.getStack(); + // remove this to make it unequip armor (click the same slot) + if (stack.hasDisplayName() && !stack.getDisplayName().contains("Equipped") && !stack.getDisplayName().contains("Locked")) { + InventoryUtils.clickContainerSlot(35 + (swapTo - 1) % 9 + 1, ClickType.LEFT, ClickMode.PICKUP); + } + } + activeSlot = swapTo; + setState(State.WAITING, FarmHelperConfig.getRandomGUIMacroDelay()); + break; + case WAITING: + if (isTimerRunning()) { + return; + } + PlayerUtils.closeScreen(); + setState(State.ENDING, FarmHelperConfig.getRandomGUIMacroDelay()); + break; + // this is just here to give a bit extra pause before it stops + case ENDING: + if (isTimerRunning()) { + return; + } + stop(); + break; } - PlayerUtils.closeScreen(); - setState(State.ENDING, FarmHelperConfig.getRandomGUIMacroDelay()); - break; - // this is just here to give a bit extra pause before it stops - case ENDING: - if (isTimerRunning()) return; - stop(); - break; } - } - - private String inventoryName() { - try { - if (mc.currentScreen instanceof GuiChest) { - final ContainerChest chest = (ContainerChest) mc.thePlayer.openContainer; - if (chest == null) { - return ""; + + private String inventoryName() { + try { + if (mc.currentScreen instanceof GuiChest) { + final ContainerChest chest = (ContainerChest) mc.thePlayer.openContainer; + if (chest == null) { + return ""; + } + final IInventory inv = chest.getLowerChestInventory(); + return inv.hasCustomName() ? inv.getName() : ""; + } + return ""; + } catch (Exception e) { + return ""; } - final IInventory inv = chest.getLowerChestInventory(); - return inv.hasCustomName() ? inv.getName() : ""; - } - return ""; - } catch (Exception e) { - return ""; } - } - enum State { - STARTING, OPENING_WD, WD_VERIFY, NAVIGATING, NAVIGATION_VERIFY, CLICKING_SLOT, WAITING, ENDING - } + enum State { + STARTING, OPENING_WD, WD_VERIFY, NAVIGATING, NAVIGATION_VERIFY, CLICKING_SLOT, WAITING, ENDING + } } diff --git a/src/main/java/com/jelly/farmhelperv2/feature/impl/PestFarmer.java b/src/main/java/com/jelly/farmhelperv2/feature/impl/PestFarmer.java index 721d897d..688a751d 100644 --- a/src/main/java/com/jelly/farmhelperv2/feature/impl/PestFarmer.java +++ b/src/main/java/com/jelly/farmhelperv2/feature/impl/PestFarmer.java @@ -19,155 +19,157 @@ public class PestFarmer implements IFeature { - public static PestFarmer instance = new PestFarmer(); - private boolean enabled = false; - private long pestSpawnTime = 0L; - private int swapTo = -1; - private State state = State.SWAPPING; - private boolean pestSpawned = false; - private boolean holdDae = false; - - @Override - public String getName() { - return "PestFarmer"; - } - - @Override - public boolean isRunning() { - return enabled; - } - - @Override - public boolean shouldPauseMacroExecution() { - return true; - } - - @Override - public boolean shouldStartAtMacroStart() { - return false; - } - - @Override - public void resetStatesAfterMacroDisabled() { - state = State.SWAPPING; - pestSpawned = false; - holdDae = false; - swapTo = -1; - } - - @Override - public boolean isToggled() { - return FarmHelperConfig.pestFarming; - } - - @Override - public boolean shouldCheckForFailsafes() { - return false; - } - - @Override - public void start() { - if (enabled) { - return; - } - MacroHandler.getInstance().pauseMacro(); - enabled = true; - } - - @Override - public void stop() { - if (!enabled) { - return; + public static PestFarmer instance = new PestFarmer(); + private boolean enabled = false; + private long pestSpawnTime = 0L; + private int swapTo = -1; + private State state = State.SWAPPING; + private boolean pestSpawned = false; + private boolean holdDae = false; + + @Override + public String getName() { + return "PestFarmer"; } - enabled = false; - state = State.SWAPPING; - if (MacroHandler.getInstance().isMacroToggled()) { - MacroHandler.getInstance().resumeMacro(); + @Override + public boolean isRunning() { + return enabled; } - } - - public boolean holdDaedalus() { - return holdDae && FarmHelperConfig.pestFarming && FarmHelperConfig.pestFarmingHoldDaedalus && AutoWardrobe.activeSlot == FarmHelperConfig.pestFarmingSet1Slot && InventoryUtils.holdItem("Daedalus Axe"); - } - @SubscribeEvent - public void onTick(ClientTickEvent event) { - if (event.phase != Phase.START) { - return; + @Override + public boolean shouldPauseMacroExecution() { + return true; } - if (!this.isToggled() || !MacroHandler.getInstance().isCurrentMacroEnabled() || MacroHandler.getInstance().getCurrentMacro().get().currentState.ordinal() < 4 || enabled) { - return; - } - if (!GameStateHandler.getInstance().inGarden()) { - return; + + @Override + public boolean shouldStartAtMacroStart() { + return false; } - if (GameStateHandler.getInstance().getServerClosingSeconds().isPresent()) { - return; + + @Override + public void resetStatesAfterMacroDisabled() { + state = State.SWAPPING; + pestSpawned = false; + holdDae = false; + swapTo = -1; } - if (!Scheduler.getInstance().isFarming()) { - return; + + @Override + public boolean isToggled() { + return FarmHelperConfig.pestFarming; } - if (FailsafeManager.getInstance().triggeredFailsafe.isPresent()) { - return; + + @Override + public boolean shouldCheckForFailsafes() { + return false; } - if (FeatureManager.getInstance().isAnyOtherFeatureEnabled(this)) { - return; + + @Override + public void start() { + if (enabled) { + return; + } + MacroHandler.getInstance().pauseMacro(); + enabled = true; } - if (pestSpawned) { - long timeDiff = System.currentTimeMillis() - pestSpawnTime; - if (timeDiff >= FarmHelperConfig.pestFarmingWaitTime * 1000L && AutoWardrobe.activeSlot != FarmHelperConfig.pestFarmingSet1Slot) { - LogUtils.sendDebug("Swapping to " + FarmHelperConfig.pestFarmingSet1Slot); - swapTo = FarmHelperConfig.pestFarmingSet1Slot; - pestSpawned = false; - holdDae = true; - start(); - } else if (AutoWardrobe.activeSlot != FarmHelperConfig.pestFarmingSet0Slot) { - LogUtils.sendDebug("Swapping to " + FarmHelperConfig.pestFarmingSet0Slot); - swapTo = FarmHelperConfig.pestFarmingSet0Slot; - holdDae = false; - start(); - } + @Override + public void stop() { + if (!enabled) { + return; + } + + enabled = false; + state = State.SWAPPING; + if (MacroHandler.getInstance().isMacroToggled()) { + MacroHandler.getInstance().resumeMacro(); + } } - } - @SubscribeEvent - public void onChat(ClientChatReceivedEvent event) { - if (event.type != 0) { - return; + public boolean holdDaedalus() { + return holdDae && FarmHelperConfig.pestFarming && FarmHelperConfig.pestFarmingHoldDaedalus + && AutoWardrobe.activeSlot == FarmHelperConfig.pestFarmingSet1Slot && InventoryUtils.holdItem("Daedalus Axe"); } - String message = event.message.getUnformattedText(); - if (message.startsWith("§6§lYUCK!") || message.startsWith("§6§lEWW!") || message.startsWith("§6§lGROSS!")) { - pestSpawnTime = System.currentTimeMillis(); - pestSpawned = true; - LogUtils.sendDebug("[PestFarmer] Pest Spawned."); + + @SubscribeEvent + public void onTick(ClientTickEvent event) { + if (event.phase != Phase.START) { + return; + } + if (!this.isToggled() || !MacroHandler.getInstance().isCurrentMacroEnabled() + || MacroHandler.getInstance().getCurrentMacro().get().currentState.ordinal() < 4 || enabled) { + return; + } + if (!GameStateHandler.getInstance().inGarden()) { + return; + } + if (GameStateHandler.getInstance().getServerClosingSeconds().isPresent()) { + return; + } + if (!Scheduler.getInstance().isFarming()) { + return; + } + if (FailsafeManager.getInstance().triggeredFailsafe.isPresent()) { + return; + } + if (FeatureManager.getInstance().isAnyOtherFeatureEnabled(this)) { + return; + } + + if (pestSpawned) { + long timeDiff = System.currentTimeMillis() - pestSpawnTime; + if (timeDiff >= FarmHelperConfig.pestFarmingWaitTime * 1000L && AutoWardrobe.activeSlot != FarmHelperConfig.pestFarmingSet1Slot) { + LogUtils.sendDebug("Swapping to " + FarmHelperConfig.pestFarmingSet1Slot); + swapTo = FarmHelperConfig.pestFarmingSet1Slot; + pestSpawned = false; + holdDae = true; + start(); + } else if (AutoWardrobe.activeSlot != FarmHelperConfig.pestFarmingSet0Slot) { + LogUtils.sendDebug("Swapping to " + FarmHelperConfig.pestFarmingSet0Slot); + swapTo = FarmHelperConfig.pestFarmingSet0Slot; + holdDae = false; + start(); + } + } } - } - @SubscribeEvent - public void onTickSwap(ClientTickEvent event) { - if (!enabled) { - return; + @SubscribeEvent + public void onChat(ClientChatReceivedEvent event) { + if (event.type != 0) { + return; + } + String message = event.message.getUnformattedText(); + if (message.startsWith("§6§lYUCK!") || message.startsWith("§6§lEWW!") || message.startsWith("§6§lGROSS!")) { + pestSpawnTime = System.currentTimeMillis(); + pestSpawned = true; + LogUtils.sendDebug("[PestFarmer] Pest Spawned."); + } } - switch (state) { - case SWAPPING: - AutoWardrobe.instance.swapTo(swapTo); - state = State.ENDING; - break; - case ENDING: - if (AutoWardrobe.instance.isRunning()) { - return; + @SubscribeEvent + public void onTickSwap(ClientTickEvent event) { + if (!enabled) { + return; + } + + switch (state) { + case SWAPPING: + AutoWardrobe.instance.swapTo(swapTo); + state = State.ENDING; + break; + case ENDING: + if (AutoWardrobe.instance.isRunning()) { + return; + } + stop(); + break; } - stop(); - break; } - } - // bleh, its only for the tracker basically - enum State { - SWAPPING, - ENDING - } + // bleh, its only for the tracker basically + enum State { + SWAPPING, + ENDING + } } diff --git a/src/main/java/com/jelly/farmhelperv2/mixin/client/MixinMinecraft.java b/src/main/java/com/jelly/farmhelperv2/mixin/client/MixinMinecraft.java index 7745d10b..f5a42504 100644 --- a/src/main/java/com/jelly/farmhelperv2/mixin/client/MixinMinecraft.java +++ b/src/main/java/com/jelly/farmhelperv2/mixin/client/MixinMinecraft.java @@ -53,8 +53,6 @@ public class MixinMinecraft { @Shadow public EntityPlayerSP thePlayer; - @Shadow private ServerData currentServerData; - @Inject(method = "sendClickBlockToController", at = @At("RETURN")) private void sendClickBlockToController(CallbackInfo ci) { if (!FarmHelperConfig.fastBreak || !(MacroHandler.getInstance().getCurrentMacro().isPresent() && MacroHandler.getInstance().isMacroToggled())) { From 1c75b4414b2784a62a54c783ecf97159f4e3438e Mon Sep 17 00:00:00 2001 From: Osama Date: Mon, 2 Dec 2024 18:34:04 +0600 Subject: [PATCH 05/10] Shiz --- .../feature/impl/PestsDestroyer.java | 3050 +++++++++-------- 1 file changed, 1529 insertions(+), 1521 deletions(-) diff --git a/src/main/java/com/jelly/farmhelperv2/feature/impl/PestsDestroyer.java b/src/main/java/com/jelly/farmhelperv2/feature/impl/PestsDestroyer.java index 962dcf03..24b4030e 100644 --- a/src/main/java/com/jelly/farmhelperv2/feature/impl/PestsDestroyer.java +++ b/src/main/java/com/jelly/farmhelperv2/feature/impl/PestsDestroyer.java @@ -49,1631 +49,1639 @@ public class PestsDestroyer implements IFeature { - private static PestsDestroyer instance; - private final Minecraft mc = Minecraft.getMinecraft(); - private final List> pests = Arrays.asList( - new Tuple<>("Beetle", - "ewogICJ0aW1lc3RhbXAiIDogMTcyMzE3OTc4OTkzNCwKICAicHJvZmlsZUlkIiA6ICJlMjc5NjliODYyNWY0NDg1YjkyNmM5NTBhMDljMWMwMSIsCiAgInByb2ZpbGVOYW1lIiA6ICJLRVZJTktFTE9LRSIsCiAgInNpZ25hdHVyZVJlcXVpcmVkIiA6IHRydWUsCiAgInRleHR1cmVzIiA6IHsKICAgICJTS0lOIiA6IHsKICAgICAgInVybCIgOiAiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS83MGExZTgzNmJmMTk2OGIyZWFhNDgzNzIyN2ExOTIwNGYxNzI5NWQ4NzBlZTllNzU0YmQ2YjZkNjBkZGJlZDNjIgogICAgfQogIH0KfQ"), - new Tuple<>("Cricket", - "ewogICJ0aW1lc3RhbXAiIDogMTcyMzE3OTgxMTI2NCwKICAicHJvZmlsZUlkIiA6ICJjZjc4YzFkZjE3ZTI0Y2Q5YTIxYmU4NWQ0NDk5ZWE4ZiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNYXR0c0FybW9yU3RhbmRzIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2EyNGM2OWY5NmNlNTU2MjIxZTE5NWM4ZWYyYmZhZDcxZWJmN2Y5NWY1YWU5MTRhNDg0YThkMGVjMjE2NzI2NzQiCiAgICB9CiAgfQp9"), - new Tuple<>("Earthworm", - "ewogICJ0aW1lc3RhbXAiIDogMTY5NzQ3MDQ1OTc0NywKICAicHJvZmlsZUlkIiA6ICIyNTBlNzc5MjZkNDM0ZDIyYWM2MTQ4N2EyY2M3YzAwNCIsCiAgInByb2ZpbGVOYW1lIiA6ICJMdW5hMTIxMDUiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjQwM2JhNDAyN2EzMzNkOGQyZmQzMmFiNTlkMWNmZGJhYTdkOTA4ZDgwZDIzODFkYjJhNjljYmU2NTQ1MGFkOCIKICAgIH0KICB9Cn0"), - new Tuple<>("Fly", - "ewogICJ0aW1lc3RhbXAiIDogMTY5Njk0NTA2MzI4MSwKICAicHJvZmlsZUlkIiA6ICJjN2FmMWNkNjNiNTE0Y2YzOGY4NWQ2ZDUxNzhjYThlNCIsCiAgInByb2ZpbGVOYW1lIiA6ICJtb25zdGVyZ2FtZXIzMTUiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOWQ5MGU3Nzc4MjZhNTI0NjEzNjhlMjZkMWIyZTE5YmZhMWJhNTgyZDYwMjQ4M2U1NDVmNDEyNGQwZjczMTg0MiIKICAgIH0KICB9Cn0"), - new Tuple<>("Locust", - "ewogICJ0aW1lc3RhbXAiIDogMTY5NzU1NzA3NzAzNywKICAicHJvZmlsZUlkIiA6ICI0YjJlMGM1ODliZjU0ZTk1OWM1ZmJlMzg5MjQ1MzQzZSIsCiAgInByb2ZpbGVOYW1lIiA6ICJfTmVvdHJvbl8iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNGIyNGE0ODJhMzJkYjFlYTc4ZmI5ODA2MGIwYzJmYTRhMzczY2JkMThhNjhlZGRkZWI3NDE5NDU1YTU5Y2RhOSIKICAgIH0KICB9Cn0"), - new Tuple<>("Mite", - "ewogICJ0aW1lc3RhbXAiIDogMTY5Njg3MDQxOTcyNSwKICAicHJvZmlsZUlkIiA6ICJkYjYzNWE3MWI4N2U0MzQ5YThhYTgwOTMwOWFhODA3NyIsCiAgInByb2ZpbGVOYW1lIiA6ICJFbmdlbHMxNzQiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYmU2YmFmNjQzMWE5ZGFhMmNhNjA0ZDVhM2MyNmU5YTc2MWQ1OTUyZjA4MTcxNzRhNGZlMGI3NjQ2MTZlMjFmZiIKICAgIH0KICB9Cn0"), - new Tuple<>("Mosquito", - "ewogICJ0aW1lc3RhbXAiIDogMTY5Njk0NTAyOTQ2MSwKICAicHJvZmlsZUlkIiA6ICI3NTE0NDQ4MTkxZTY0NTQ2OGM5NzM5YTZlMzk1N2JlYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJUaGFua3NNb2phbmciLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTJhOWZlMDViYzY2M2VmY2QxMmU1NmEzY2NjNWVjMDM1YmY1NzdiNzg3MDg1NDhiNmY0ZmZjZjFkMzBlY2NmZSIKICAgIH0KICB9Cn0"), - new Tuple<>("Moth", - "ewogICJ0aW1lc3RhbXAiIDogMTY5Njg3MDQwNTk1NCwKICAicHJvZmlsZUlkIiA6ICJiMTUyZDlhZTE1MTM0OWNmOWM2NmI0Y2RjMTA5NTZjOCIsCiAgInByb2ZpbGVOYW1lIiA6ICJNaXNxdW90aCIsCiAgInNpZ25hdHVyZVJlcXVpcmVkIiA6IHRydWUsCiAgInRleHR1cmVzIiA6IHsKICAgICJTS0lOIiA6IHsKICAgICAgInVybCIgOiAiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS82NTQ4NWM0YjM0ZTViNTQ3MGJlOTRkZTEwMGU2MWY3ODE2ZjgxYmM1YTExZGZkZjBlY2NmODkwMTcyZGE1ZDBhIgogICAgfQogIH0KfQ"), - new Tuple<>("Rat", - "ewogICJ0aW1lc3RhbXAiIDogMTYxODQxOTcwMTc1MywKICAicHJvZmlsZUlkIiA6ICI3MzgyZGRmYmU0ODU0NTVjODI1ZjkwMGY4OGZkMzJmOCIsCiAgInByb2ZpbGVOYW1lIiA6ICJCdUlJZXQiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYThhYmI0NzFkYjBhYjc4NzAzMDExOTc5ZGM4YjQwNzk4YTk0MWYzYTRkZWMzZWM2MWNiZWVjMmFmOGNmZmU4IiwKICAgICAgIm1ldGFkYXRhIiA6IHsKICAgICAgICAibW9kZWwiIDogInNsaW0iCiAgICAgIH0KICAgIH0KICB9Cn0="), - new Tuple<>("Slug", - "ewogICJ0aW1lc3RhbXAiIDogMTY5NzQ3MDQ0MzA4MiwKICAicHJvZmlsZUlkIiA6ICJkOGNkMTNjZGRmNGU0Y2IzODJmYWZiYWIwOGIyNzQ4OSIsCiAgInByb2ZpbGVOYW1lIiA6ICJaYWNoeVphY2giLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvN2E3OWQwZmQ2NzdiNTQ1MzA5NjExMTdlZjg0YWRjMjA2ZTJjYzUwNDVjMTM0NGQ2MWQ3NzZiZjhhYzJmZTFiYSIKICAgIH0KICB9Cn0") - ); - private Optional closestPlot = Optional.empty(); - @Getter - private final ArrayList pestsLocations = new ArrayList<>(); - private final List killedEntities = new ArrayList<>(); - @Getter - private final Clock stuckClock = new Clock(); - @Getter - private final Clock delayClock = new Clock(); - private final Clock delayBetweenBackTaps = new Clock(); - private final Clock delayBetweenFireworks = new Clock(); - @Getter - private Optional currentEntityTarget = Optional.empty(); - private boolean enabled = false; - private boolean preparing = false; - @Setter - @Getter - public int cantReachPest = 0; - @Getter - @Setter - private States state = States.IDLE; - @Getter - private EscapeState escapeState = EscapeState.NONE; - private Optional preTpBlockPos = Optional.empty(); - private long lastFireworkTime = 0; - private int getLocationTries = 0; - private int flyPathfinderTries = 0; - private RotationState rotationState = RotationState.NONE; - private boolean needToUpdatePlots = false; - private final HashMap vacuumRange = new HashMap() {{ - put("Skymart Vacuum", 5F); - put("Turbo Vacuum", 7.5F); - put("Hyper Vacuum", 10F); - put("InfiniVacuum™ Hooverius", 15F); - put("InfiniVacuum", 12.5F); - }}; - @Getter - private float currentVacuumRange = -1; - - private boolean gotRangeOfVacuum = false; - private boolean isPlotObstructed = false; - private long lastKillTimestamp = 0; - private int previousCurrentPlotPestsCount = 0; - private int currentSlot = -1; - private boolean finishing = false; - - private final List killedPestsFrom = new ArrayList<>(); - - public static PestsDestroyer getInstance() { - if (instance == null) { - instance = new PestsDestroyer(); - } - return instance; - } - - @Override - public String getName() { - return "Pests Destroyer"; - } - - @Override - public boolean isRunning() { - return enabled || preparing; - } - - @Override - public boolean shouldPauseMacroExecution() { - return true; - } - - @Override - public boolean shouldStartAtMacroStart() { - return false; - } - - @Override - public void start() { - if (enabled) { - return; - } - gotRangeOfVacuum = false; - isPlotObstructed = false; - preparing = true; - lastKillTimestamp = 0; - if (MacroHandler.getInstance().isMacroToggled()) { - MacroHandler.getInstance().pauseMacro(); - MacroHandler.getInstance().getCurrentMacro().ifPresent(am -> am.setSavedState(Optional.empty())); - KeyBindUtils.stopMovement(); - } - escapeState = EscapeState.NONE; - rotationState = RotationState.NONE; - state = States.IDLE; - killedEntities.clear(); - killedPestsFrom.clear(); - Multithreading.schedule(() -> { - if (!preparing) { - return; - } - enabled = true; - preparing = false; - LogUtils.sendWarning("[Pests Destroyer] Starting killing shitters!"); - if (FarmHelperConfig.sendWebhookLogWhenPestDestroyerStartsStops) { - LogUtils.webhookLog("[Pests Destroyer]\\nStarting killing shitters!"); - } - }, MacroHandler.getInstance().isMacroToggled() ? (800 + (long) (Math.random() * 500)) : 0, TimeUnit.MILLISECONDS); - IFeature.super.start(); - } - - @Override - public void stop() { - if (enabled || preparing) { - LogUtils.sendWarning("[Pests Destroyer] Stopping!"); - if (FarmHelperConfig.sendWebhookLogWhenPestDestroyerStartsStops) { - LogUtils.webhookLog("[Pests Destroyer]\\nStopping!"); - } - if (GameStateHandler.getInstance().getPestsCount() == 0) { - pestsLocations.clear(); - } - } - PlayerUtils.closeScreen(); - currentEntityTarget = Optional.empty(); - resetFireworkInfo(); - preTpBlockPos = Optional.empty(); - delayBetweenBackTaps.reset(); - delayBetweenFireworks.reset(); - delayClock.reset(); - stuckClock.reset(); - preparing = false; - enabled = false; - isPlotObstructed = false; - lastFireworkTime = 0; - getLocationTries = 0; - flyPathfinderTries = 0; - state = States.IDLE; - FlyPathFinderExecutor.getInstance().stop(); - KeyBindUtils.stopMovement(); - finishing = false; - currentSlot = -1; - IFeature.super.stop(); - } - - @Override - public void resetStatesAfterMacroDisabled() { - stop(); - gotRangeOfVacuum = false; - if (!FarmHelperConfig.pestsDestroyerAfkInfiniteMode) { - return; - } - FarmHelperConfig.pestsDestroyerAfkInfiniteMode = false; - LogUtils.sendWarning("[Pests Destroyer] AFK Mode has been disabled"); - } - - @Override - public boolean isToggled() { - return FarmHelperConfig.enablePestsDestroyer; - } - - @Override - public boolean shouldCheckForFailsafes() { - return escapeState == EscapeState.NONE && - state != States.TELEPORT_TO_PLOT && - state != States.WAIT_FOR_TP && - state != States.CHECKING_PLOT && - state != States.CHECKING_SPAWN && - state != States.GET_LOCATION; - } - - @SubscribeEvent - public void onKeyInput(InputEvent.KeyInputEvent event) { - if (!FarmHelperConfig.pestsDestroyerAfkInfiniteMode) { - return; - } - if (Keyboard.getEventKeyState() && Keyboard.getEventKey() == Keyboard.KEY_ESCAPE) { - LogUtils.sendWarning("[Pests Destroyer] Disabling Pests Destroyer AFK Infinite Mode!"); - stop(); - FarmHelperConfig.pestsDestroyerAfkInfiniteMode = false; + private static PestsDestroyer instance; + private final Minecraft mc = Minecraft.getMinecraft(); + private final List> pests = Arrays.asList( + new Tuple<>("Beetle", + "ewogICJ0aW1lc3RhbXAiIDogMTcyMzE3OTc4OTkzNCwKICAicHJvZmlsZUlkIiA6ICJlMjc5NjliODYyNWY0NDg1YjkyNmM5NTBhMDljMWMwMSIsCiAgInByb2ZpbGVOYW1lIiA6ICJLRVZJTktFTE9LRSIsCiAgInNpZ25hdHVyZVJlcXVpcmVkIiA6IHRydWUsCiAgInRleHR1cmVzIiA6IHsKICAgICJTS0lOIiA6IHsKICAgICAgInVybCIgOiAiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS83MGExZTgzNmJmMTk2OGIyZWFhNDgzNzIyN2ExOTIwNGYxNzI5NWQ4NzBlZTllNzU0YmQ2YjZkNjBkZGJlZDNjIgogICAgfQogIH0KfQ"), + new Tuple<>("Cricket", + "ewogICJ0aW1lc3RhbXAiIDogMTcyMzE3OTgxMTI2NCwKICAicHJvZmlsZUlkIiA6ICJjZjc4YzFkZjE3ZTI0Y2Q5YTIxYmU4NWQ0NDk5ZWE4ZiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNYXR0c0FybW9yU3RhbmRzIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2EyNGM2OWY5NmNlNTU2MjIxZTE5NWM4ZWYyYmZhZDcxZWJmN2Y5NWY1YWU5MTRhNDg0YThkMGVjMjE2NzI2NzQiCiAgICB9CiAgfQp9"), + new Tuple<>("Earthworm", + "ewogICJ0aW1lc3RhbXAiIDogMTY5NzQ3MDQ1OTc0NywKICAicHJvZmlsZUlkIiA6ICIyNTBlNzc5MjZkNDM0ZDIyYWM2MTQ4N2EyY2M3YzAwNCIsCiAgInByb2ZpbGVOYW1lIiA6ICJMdW5hMTIxMDUiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjQwM2JhNDAyN2EzMzNkOGQyZmQzMmFiNTlkMWNmZGJhYTdkOTA4ZDgwZDIzODFkYjJhNjljYmU2NTQ1MGFkOCIKICAgIH0KICB9Cn0"), + new Tuple<>("Fly", + "ewogICJ0aW1lc3RhbXAiIDogMTY5Njk0NTA2MzI4MSwKICAicHJvZmlsZUlkIiA6ICJjN2FmMWNkNjNiNTE0Y2YzOGY4NWQ2ZDUxNzhjYThlNCIsCiAgInByb2ZpbGVOYW1lIiA6ICJtb25zdGVyZ2FtZXIzMTUiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOWQ5MGU3Nzc4MjZhNTI0NjEzNjhlMjZkMWIyZTE5YmZhMWJhNTgyZDYwMjQ4M2U1NDVmNDEyNGQwZjczMTg0MiIKICAgIH0KICB9Cn0"), + new Tuple<>("Locust", + "ewogICJ0aW1lc3RhbXAiIDogMTY5NzU1NzA3NzAzNywKICAicHJvZmlsZUlkIiA6ICI0YjJlMGM1ODliZjU0ZTk1OWM1ZmJlMzg5MjQ1MzQzZSIsCiAgInByb2ZpbGVOYW1lIiA6ICJfTmVvdHJvbl8iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNGIyNGE0ODJhMzJkYjFlYTc4ZmI5ODA2MGIwYzJmYTRhMzczY2JkMThhNjhlZGRkZWI3NDE5NDU1YTU5Y2RhOSIKICAgIH0KICB9Cn0"), + new Tuple<>("Mite", + "ewogICJ0aW1lc3RhbXAiIDogMTY5Njg3MDQxOTcyNSwKICAicHJvZmlsZUlkIiA6ICJkYjYzNWE3MWI4N2U0MzQ5YThhYTgwOTMwOWFhODA3NyIsCiAgInByb2ZpbGVOYW1lIiA6ICJFbmdlbHMxNzQiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYmU2YmFmNjQzMWE5ZGFhMmNhNjA0ZDVhM2MyNmU5YTc2MWQ1OTUyZjA4MTcxNzRhNGZlMGI3NjQ2MTZlMjFmZiIKICAgIH0KICB9Cn0"), + new Tuple<>("Mosquito", + "ewogICJ0aW1lc3RhbXAiIDogMTY5Njk0NTAyOTQ2MSwKICAicHJvZmlsZUlkIiA6ICI3NTE0NDQ4MTkxZTY0NTQ2OGM5NzM5YTZlMzk1N2JlYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJUaGFua3NNb2phbmciLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTJhOWZlMDViYzY2M2VmY2QxMmU1NmEzY2NjNWVjMDM1YmY1NzdiNzg3MDg1NDhiNmY0ZmZjZjFkMzBlY2NmZSIKICAgIH0KICB9Cn0"), + new Tuple<>("Moth", + "ewogICJ0aW1lc3RhbXAiIDogMTY5Njg3MDQwNTk1NCwKICAicHJvZmlsZUlkIiA6ICJiMTUyZDlhZTE1MTM0OWNmOWM2NmI0Y2RjMTA5NTZjOCIsCiAgInByb2ZpbGVOYW1lIiA6ICJNaXNxdW90aCIsCiAgInNpZ25hdHVyZVJlcXVpcmVkIiA6IHRydWUsCiAgInRleHR1cmVzIiA6IHsKICAgICJTS0lOIiA6IHsKICAgICAgInVybCIgOiAiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS82NTQ4NWM0YjM0ZTViNTQ3MGJlOTRkZTEwMGU2MWY3ODE2ZjgxYmM1YTExZGZkZjBlY2NmODkwMTcyZGE1ZDBhIgogICAgfQogIH0KfQ"), + new Tuple<>("Rat", + "ewogICJ0aW1lc3RhbXAiIDogMTYxODQxOTcwMTc1MywKICAicHJvZmlsZUlkIiA6ICI3MzgyZGRmYmU0ODU0NTVjODI1ZjkwMGY4OGZkMzJmOCIsCiAgInByb2ZpbGVOYW1lIiA6ICJCdUlJZXQiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYThhYmI0NzFkYjBhYjc4NzAzMDExOTc5ZGM4YjQwNzk4YTk0MWYzYTRkZWMzZWM2MWNiZWVjMmFmOGNmZmU4IiwKICAgICAgIm1ldGFkYXRhIiA6IHsKICAgICAgICAibW9kZWwiIDogInNsaW0iCiAgICAgIH0KICAgIH0KICB9Cn0="), + new Tuple<>("Slug", + "ewogICJ0aW1lc3RhbXAiIDogMTY5NzQ3MDQ0MzA4MiwKICAicHJvZmlsZUlkIiA6ICJkOGNkMTNjZGRmNGU0Y2IzODJmYWZiYWIwOGIyNzQ4OSIsCiAgInByb2ZpbGVOYW1lIiA6ICJaYWNoeVphY2giLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvN2E3OWQwZmQ2NzdiNTQ1MzA5NjExMTdlZjg0YWRjMjA2ZTJjYzUwNDVjMTM0NGQ2MWQ3NzZiZjhhYzJmZTFiYSIKICAgIH0KICB9Cn0") + ); + private Optional closestPlot = Optional.empty(); + @Getter + private final ArrayList pestsLocations = new ArrayList<>(); + private final List killedEntities = new ArrayList<>(); + @Getter + private final Clock stuckClock = new Clock(); + @Getter + private final Clock delayClock = new Clock(); + private final Clock delayBetweenBackTaps = new Clock(); + private final Clock delayBetweenFireworks = new Clock(); + @Getter + private Optional currentEntityTarget = Optional.empty(); + private boolean enabled = false; + private boolean preparing = false; + @Setter + @Getter + public int cantReachPest = 0; + @Getter + @Setter + private States state = States.IDLE; + @Getter + private EscapeState escapeState = EscapeState.NONE; + private Optional preTpBlockPos = Optional.empty(); + private long lastFireworkTime = 0; + private int getLocationTries = 0; + private int flyPathfinderTries = 0; + private RotationState rotationState = RotationState.NONE; + private boolean needToUpdatePlots = false; + private final HashMap vacuumRange = new HashMap() {{ + put("Skymart Vacuum", 5F); + put("Turbo Vacuum", 7.5F); + put("Hyper Vacuum", 10F); + put("InfiniVacuum™ Hooverius", 15F); + put("InfiniVacuum", 12.5F); + }}; + @Getter + private float currentVacuumRange = -1; + + private boolean gotRangeOfVacuum = false; + private boolean isPlotObstructed = false; + private long lastKillTimestamp = 0; + private int previousCurrentPlotPestsCount = 0; + private int currentSlot = -1; + private boolean finishing = false; + + private final List killedPestsFrom = new ArrayList<>(); + + public static PestsDestroyer getInstance() { + if (instance == null) { + instance = new PestsDestroyer(); + } + return instance; + } + + @Override + public String getName() { + return "Pests Destroyer"; + } + + @Override + public boolean isRunning() { + return enabled || preparing; + } + + @Override + public boolean shouldPauseMacroExecution() { + return true; } - } - @SubscribeEvent - public void onTickAFKMode(TickEvent.ClientTickEvent event) { - if (event.phase == TickEvent.Phase.END) { - return; - } - if (mc.thePlayer == null || mc.theWorld == null) { - return; - } - if (!FarmHelperConfig.pestsDestroyerAfkInfiniteMode) { - return; - } - if (MacroHandler.getInstance().isMacroToggled()) { - return; - } - if (!isToggled()) { - return; - } - if (isRunning()) { - return; + @Override + public boolean shouldStartAtMacroStart() { + return false; } - if (canEnableMacro(true)) { - start(); + @Override + public void start() { + if (enabled) { + return; + } + gotRangeOfVacuum = false; + isPlotObstructed = false; + preparing = true; + lastKillTimestamp = 0; + if (MacroHandler.getInstance().isMacroToggled()) { + MacroHandler.getInstance().pauseMacro(); + MacroHandler.getInstance().getCurrentMacro().ifPresent(am -> am.setSavedState(Optional.empty())); + KeyBindUtils.stopMovement(); + } + escapeState = EscapeState.NONE; + rotationState = RotationState.NONE; + state = States.IDLE; + killedEntities.clear(); + killedPestsFrom.clear(); + Multithreading.schedule(() -> { + if (!preparing) { + return; + } + enabled = true; + preparing = false; + LogUtils.sendWarning("[Pests Destroyer] Starting killing shitters!"); + if (FarmHelperConfig.sendWebhookLogWhenPestDestroyerStartsStops) { + LogUtils.webhookLog("[Pests Destroyer]\\nStarting killing shitters!"); + } + }, MacroHandler.getInstance().isMacroToggled() ? (800 + (long) (Math.random() * 500)) : 0, TimeUnit.MILLISECONDS); + IFeature.super.start(); } - } - public boolean canEnableMacro() { - return canEnableMacro(false); - } - - public boolean canEnableMacro(boolean manually) { - if (!isToggled()) { - return false; - } - if (isRunning()) { - return false; - } - if (!GameStateHandler.getInstance().inGarden()) { - return false; - } - if (!MacroHandler.getInstance().isMacroToggled() && !manually) { - return false; - } - if (!FailsafeManager.getInstance().getEmergencyQueue().isEmpty()) { - return false; - } - if (FailsafeManager.getInstance().triggeredFailsafe.isPresent()) { - return false; - } - if (enabled || preparing) { - return false; - } - if (GameStateHandler.getInstance().getPestsCount() < FarmHelperConfig.startKillingPestsAt && !manually || (manually - && GameStateHandler.getInstance().getPestsCount() == 0)) { - return false; - } - if (!manually && FarmHelperConfig.pausePestsDestroyerDuringJacobsContest && GameStateHandler.getInstance().inJacobContest()) { - LogUtils.sendError("[Pests Destroyer] Pests Destroyer won't activate during Jacob's Contest!"); - return false; - } - if (!mc.thePlayer.capabilities.allowFlying) { - LogUtils.sendError("[Pests Destroyer] You need to be able to fly!"); - if (FarmHelperConfig.pestsDestroyerAfkInfiniteMode) { - LogUtils.sendWarning("[Pests Destroyer] Disabling Pests Destroyer AFK Infinite Mode!"); - FarmHelperConfig.pestsDestroyerAfkInfiniteMode = false; - } - return false; + @Override + public void stop() { + if (enabled || preparing) { + LogUtils.sendWarning("[Pests Destroyer] Stopping!"); + if (FarmHelperConfig.sendWebhookLogWhenPestDestroyerStartsStops) { + LogUtils.webhookLog("[Pests Destroyer]\\nStopping!"); + } + if (GameStateHandler.getInstance().getPestsCount() == 0) { + pestsLocations.clear(); + } + } + PlayerUtils.closeScreen(); + currentEntityTarget = Optional.empty(); + resetFireworkInfo(); + preTpBlockPos = Optional.empty(); + delayBetweenBackTaps.reset(); + delayBetweenFireworks.reset(); + delayClock.reset(); + stuckClock.reset(); + preparing = false; + enabled = false; + isPlotObstructed = false; + lastFireworkTime = 0; + getLocationTries = 0; + flyPathfinderTries = 0; + state = States.IDLE; + FlyPathFinderExecutor.getInstance().stop(); + KeyBindUtils.stopMovement(); + finishing = false; + currentSlot = -1; + IFeature.super.stop(); } - return true; - } - @SubscribeEvent - public void onTickExecute(TickEvent.ClientTickEvent event) { - if (mc.thePlayer == null || mc.theWorld == null) { - return; - } - if (mc.currentScreen == null && checkedThisGui) { - checkedThisGui = false; - } - if (!gotRangeOfVacuum && (isToggled() || PestsDestroyerOnTheTrack.getInstance().isToggled())) { - Slot vacuumSlot = InventoryUtils.getSlotOfItemInInventory("Vacuum"); - if (vacuumSlot != null) { - ItemStack vacuumItem = vacuumSlot.getStack(); - for (Map.Entry vacuumRange : this.vacuumRange.entrySet()) { - if (vacuumItem.getDisplayName().contains(vacuumRange.getKey())) { - currentVacuumRange = vacuumRange.getValue(); - gotRangeOfVacuum = true; - LogUtils.sendDebug("[Pests Destroyer] Found vacuum range: " + currentVacuumRange); - break; - } - } - } - } - if (!isToggled()) { - return; - } - if (event.phase != TickEvent.Phase.END) { - return; - } - if (!GameStateHandler.getInstance().inGarden() && escapeState == EscapeState.NONE) { - return; - } - if (!enabled) { - return; - } - if (!FailsafeManager.getInstance().getEmergencyQueue().isEmpty()) { - return; - } - if (FailsafeManager.getInstance().triggeredFailsafe.isPresent()) { - stop(); - return; + @Override + public void resetStatesAfterMacroDisabled() { + stop(); + gotRangeOfVacuum = false; + if (!FarmHelperConfig.pestsDestroyerAfkInfiniteMode) { + return; + } + FarmHelperConfig.pestsDestroyerAfkInfiniteMode = false; + LogUtils.sendWarning("[Pests Destroyer] AFK Mode has been disabled"); } - if (stuckClock.isScheduled() && stuckClock.passed()) { - LogUtils.sendWarning( - "[Pests Destroyer] The player is struggling killing pest for 5 minutes, will do a quick Garden -> Hub -> Garden teleport."); - LogUtils.sendFailsafeMessage("[Pests Destroyer] Couldn't kill pest for 5 minutes, will do a quick Garden -> Hub -> Garden teleport.", true); - escapeState = EscapeState.GO_TO_HUB; - KeyBindUtils.stopMovement(); - delayClock.schedule(300); - stuckClock.reset(); - return; + @Override + public boolean isToggled() { + return FarmHelperConfig.enablePestsDestroyer; } - if (delayClock.isScheduled() && !delayClock.passed()) { - return; + @Override + public boolean shouldCheckForFailsafes() { + return escapeState == EscapeState.NONE && + state != States.TELEPORT_TO_PLOT && + state != States.WAIT_FOR_TP && + state != States.CHECKING_PLOT && + state != States.CHECKING_SPAWN && + state != States.GET_LOCATION; } - LogUtils.sendDebug("[Pests Destroyer] State: " + state); - - if (escapeState != EscapeState.NONE) { - if (stuckClock.isScheduled()) { - stuckClock.reset(); - } - if (RotationHandler.getInstance().isRotating()) { - RotationHandler.getInstance().reset(); - } - KeyBindUtils.stopMovement(); - switch (escapeState) { - case GO_TO_HUB: - if (isInventoryOpen()) { - break; - } - if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.HUB) { - escapeState = EscapeState.GO_TO_GARDEN; - delayClock.schedule((long) (5_500 + Math.random() * 3_500)); - break; - } - if (GameStateHandler.getInstance().inGarden()) { - mc.thePlayer.sendChatMessage("/hub"); - escapeState = EscapeState.GO_TO_GARDEN; - delayClock.schedule((long) (1_800 + Math.random() * 1_000)); - } - if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.TELEPORTING) { - delayClock.schedule((long) (500 + Math.random() * 500)); - break; - } - if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.LOBBY) { - escapeState = EscapeState.GO_TO_HUB; - mc.thePlayer.sendChatMessage("/skyblock"); - delayClock.schedule((long) (5_000 + Math.random() * 1_500)); - break; - } - break; - case GO_TO_GARDEN: - if (isInventoryOpen()) { - break; - } - if (GameStateHandler.getInstance().inGarden()) { - escapeState = EscapeState.GO_TO_HUB; - delayClock.schedule((long) (2_500 + Math.random() * 1_500)); - break; - } - if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.HUB) { - escapeState = EscapeState.RESUME_MACRO; - MacroHandler.getInstance().triggerWarpGarden(true, false); - delayClock.schedule((long) (2_500 + Math.random() * 1_500)); - break; - } - if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.TELEPORTING) { - delayClock.schedule((long) (500 + Math.random() * 500)); - break; - } - if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.LOBBY) { - escapeState = EscapeState.GO_TO_HUB; - mc.thePlayer.sendChatMessage("/skyblock"); - delayClock.schedule((long) (5_000 + Math.random() * 1_500)); - break; - } - break; - case RESUME_MACRO: - if (isInventoryOpen()) { - break; - } - if (GameStateHandler.getInstance().inGarden()) { - escapeState = EscapeState.NONE; - state = States.IDLE; - cantReachPest = 0; - delayClock.schedule((long) (1_000 + Math.random() * 500)); - LogUtils.sendDebug("[Pests Destroyer] Came back to Garden!"); - break; - } - if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.HUB) { - escapeState = EscapeState.RESUME_MACRO; - MacroHandler.getInstance().triggerWarpGarden(true, false); - delayClock.schedule((long) (2_500 + Math.random() * 1_500)); - break; - } - if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.TELEPORTING) { - delayClock.schedule((long) (500 + Math.random() * 500)); - break; - } - if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.LOBBY) { - escapeState = EscapeState.GO_TO_HUB; - mc.thePlayer.sendChatMessage("/skyblock"); - delayClock.schedule((long) (5_000 + Math.random() * 1_500)); - break; - } - break; - } - return; + @SubscribeEvent + public void onKeyInput(InputEvent.KeyInputEvent event) { + if (!FarmHelperConfig.pestsDestroyerAfkInfiniteMode) { + return; + } + if (Keyboard.getEventKeyState() && Keyboard.getEventKey() == Keyboard.KEY_ESCAPE) { + LogUtils.sendWarning("[Pests Destroyer] Disabling Pests Destroyer AFK Infinite Mode!"); + stop(); + FarmHelperConfig.pestsDestroyerAfkInfiniteMode = false; + } } - switch (state) { - case IDLE: - ItemStack currentItem = mc.thePlayer.getHeldItem(); - if (GameStateHandler.getInstance().getPestsCount() == 0) { - if (isInventoryOpen()) { + @SubscribeEvent + public void onTickAFKMode(TickEvent.ClientTickEvent event) { + if (event.phase == TickEvent.Phase.END) { return; - } -// finishMacro(); - state = States.FINISH; - return; - } - if (getVacuum(currentItem)) { - return; - } - state = States.SWAP_ARMOR; - delayClock.schedule((long) (200 + Math.random() * 200)); - break; - case SWAP_ARMOR: - if (FarmHelperConfig.pestSwapArmorBefore) { - currentSlot = FarmHelperConfig.pestArmorSlot0; - if (finishing) { - currentSlot = FarmHelperConfig.pestArmorSlot1; - } - if (AutoWardrobe.activeSlot != currentSlot) { - AutoWardrobe.instance.swapTo(currentSlot); - } - } - state = States.ARMOR_SWAP_VERIFY; - break; - case ARMOR_SWAP_VERIFY: - if (AutoWardrobe.instance.isRunning()) { - return; - } - if (finishing) { - state = States.FINISH; - } else { - if (needToUpdatePlots || PlotUtils.needToUpdatePlots()) { - state = States.OPEN_DESK; - } else { - if (FarmHelperConfig.dontTeleportToPlots) { - state = States.GET_CLOSEST_PLOT; - } else { - state = States.TELEPORT_TO_PLOT; - } - } } - break; - case OPEN_DESK: - if (isInventoryOpen()) { - break; - } - mc.thePlayer.sendChatMessage("/desk"); - state = States.OPEN_PLOTS; - delayClock.schedule((long) (FarmHelperConfig.pestAdditionalGUIDelay + 500 + Math.random() * 500)); - break; - case OPEN_PLOTS: - String chestName = InventoryUtils.getInventoryName(); - if (mc.currentScreen == null) { - delayClock.schedule((long) (FarmHelperConfig.pestAdditionalGUIDelay + 300 + Math.random() * 300)); - break; + if (mc.thePlayer == null || mc.theWorld == null) { + return; } - if (!InventoryUtils.isInventoryLoaded()) { - break; - } - if (chestName == null || !chestName.equals("Desk")) { - break; - } - Slot configurePlots = InventoryUtils.getSlotOfItemInContainer("Configure Plots"); - if (configurePlots == null) { - break; - } - state = States.WAIT_FOR_INFO; - InventoryUtils.clickContainerSlot(configurePlots.slotNumber, InventoryUtils.ClickType.LEFT, InventoryUtils.ClickMode.PICKUP); - delayClock.schedule((long) (FarmHelperConfig.pestAdditionalGUIDelay + 500 + Math.random() * 500)); - break; - case WAIT_FOR_INFO: - break; - case TELEPORT_TO_PLOT: - PlotUtils.Plot plot; - if (FarmHelperConfig.dontTeleportToPlots) { - delayClock.schedule(1_000 + Math.random() * 500); - MacroHandler.getInstance().triggerWarpGarden(true, false); - state = States.CHECKING_SPAWN; - return; - } else { - plot = getClosestPlot(); + if (!FarmHelperConfig.pestsDestroyerAfkInfiniteMode) { + return; } - if (plot == null) { - state = States.GO_BACK; - delayClock.schedule((long) (500 + Math.random() * 500)); - return; - } - if (GameStateHandler.getInstance().getCurrentPlot() == plot.number && BlockUtils.canFlyHigher(8)) { - state = States.GET_LOCATION; - break; - } - String plotNumber = plot.name; - preTpBlockPos = Optional.of(mc.thePlayer.getPosition()); - mc.thePlayer.sendChatMessage("/tptoplot " + plotNumber); - state = States.WAIT_FOR_TP; - delayClock.schedule((long) (900 + Math.random() * 500)); - break; - case WAIT_FOR_TP: - if (!preTpBlockPos.isPresent()) { - state = States.IDLE; - break; - } - if (mc.thePlayer.getPosition().equals(preTpBlockPos.get())) { - break; - } - state = States.CHECKING_PLOT; - delayClock.schedule((long) (200 + Math.random() * 200)); - break; - case CHECKING_PLOT: - if (isInventoryOpenDelayed()) { - break; + if (MacroHandler.getInstance().isMacroToggled()) { + return; } - KeyBindUtils.stopMovement(); - - if (PlayerUtils.isPlayerSuffocating() || !BlockUtils.canFlyHigher(5)) { - LogUtils.sendWarning("[Pests Destroyer] The player is suffocating and/or it can't fly higher. Going back to spawnpoint."); - delayClock.schedule(1_000 + Math.random() * 500); - MacroHandler.getInstance().triggerWarpGarden(true, false); - isPlotObstructed = true; - state = States.CHECKING_SPAWN; - return; - } - state = States.GET_LOCATION; - break; - case CHECKING_SPAWN: - if (MacroHandler.getInstance().isTeleporting()) { - return; - } - - if (PlayerUtils.isPlayerSuffocating() || !BlockUtils.canFlyHigher(5)) { - LogUtils.sendError( - "[Pests Destroyer] Your spawnpoint is obstructed! Make sure there is no block above your spawnpoint! Disabling Pests Destroyer!"); - stop(); - FarmHelperConfig.enablePestsDestroyer = false; -// finishMacro(); - state = States.FINISH; - } else { - state = States.GET_CLOSEST_PLOT; - LogUtils.sendDebug("[Pests Destroyer] Spawnpoint is not obstructed"); + if (!isToggled()) { + return; } - break; - case GET_CLOSEST_PLOT: - if (isInventoryOpenDelayed()) { - break; + if (isRunning()) { + return; } - PlotUtils.Plot closestPlot = getClosestPlot(); - - if (closestPlot == null) { - LogUtils.sendError("[Pests Destroyer] Couldn't find closest plot!"); - state = States.GET_LOCATION; - return; + if (canEnableMacro(true)) { + start(); } + } - double distance = Math.sqrt(mc.thePlayer.getDistanceSq(PlotUtils.getPlotCenter(closestPlot.number))); - - this.closestPlot = Optional.of(closestPlot); - - if (FarmHelperConfig.dontTeleportToPlots) { - if (PlayerUtils.isPlayerSuffocating() || !BlockUtils.canFlyHigher(3)) { - state = States.TELEPORT_TO_PLOT; - LogUtils.sendWarning("[Pests Destroyer] The player is suffocating and/or it can't fly higher. Forcing going back to spawnpoint."); - } else { - state = States.FLY_TO_THE_CLOSEST_PLOT; - } - break; - } + public boolean canEnableMacro() { + return canEnableMacro(false); + } - if (distance > 150 && !isPlotObstructed) { - state = States.TELEPORT_TO_PLOT; - } else { - state = States.FLY_TO_THE_CLOSEST_PLOT; - } - delayClock.schedule((long) (500 + Math.random() * 500)); - break; - case FLY_TO_THE_CLOSEST_PLOT: - if (MacroHandler.getInstance().isTeleporting()) { - return; + public boolean canEnableMacro(boolean manually) { + if (!isToggled()) { + return false; } - if (isInventoryOpenDelayed()) { - break; + if (isRunning()) { + return false; } - - if (!this.closestPlot.isPresent()) { - LogUtils.sendError("[Pests Destroyer] Couldn't find closest plot!"); - state = States.GET_LOCATION; - return; + if (!GameStateHandler.getInstance().inGarden()) { + return false; } - - BlockPos plotCenter = PlotUtils.getPlotCenter(this.closestPlot.get().number); - - if (getClosestPest() != null) { - KeyBindUtils.stopMovement(); - state = States.FIND_PEST; - break; + if (!MacroHandler.getInstance().isMacroToggled() && !manually) { + return false; } - - if ((mc.thePlayer.onGround || !flyDelay.passed()) && mc.thePlayer.capabilities.allowFlying && !mc.thePlayer.capabilities.isFlying) { - fly(); - break; + if (!FailsafeManager.getInstance().getEmergencyQueue().isEmpty()) { + return false; } - - if (mc.thePlayer.getDistance(plotCenter.getX(), mc.thePlayer.posY, plotCenter.getZ()) < 15) { - state = States.GET_LOCATION; - KeyBindUtils.stopMovement(); - FlyPathFinderExecutor.getInstance().stop(); - break; + if (FailsafeManager.getInstance().triggeredFailsafe.isPresent()) { + return false; } - - if (!FlyPathFinderExecutor.getInstance().isRunning()) { - FlyPathFinderExecutor.getInstance().setSprinting(true); - FlyPathFinderExecutor.getInstance().setDontRotate(false); - FlyPathFinderExecutor.getInstance().setUseAOTV(InventoryUtils.hasItemInHotbar("Aspect of the Void", "Aspect of the End")); - FlyPathFinderExecutor.getInstance().findPath(new Vec3(plotCenter.getX(), 80, plotCenter.getZ()), true, true); + if (enabled || preparing) { + return false; } - break; - case GET_LOCATION: - if (GameStateHandler.getInstance().getPestsCount() == 0) { - state = States.GO_BACK; - return; + if (GameStateHandler.getInstance().getPestsCount() < FarmHelperConfig.startKillingPestsAt && !manually || (manually + && GameStateHandler.getInstance().getPestsCount() == 0)) { + return false; } - if (isInventoryOpenDelayed()) { - break; + if (!manually && FarmHelperConfig.pausePestsDestroyerDuringJacobsContest && GameStateHandler.getInstance().inJacobContest()) { + LogUtils.sendError("[Pests Destroyer] Pests Destroyer won't activate during Jacob's Contest!"); + return false; } - ItemStack currentItem2 = mc.thePlayer.getHeldItem(); - if (getVacuum(currentItem2)) { - return; + if (!mc.thePlayer.capabilities.allowFlying) { + LogUtils.sendError("[Pests Destroyer] You need to be able to fly!"); + if (FarmHelperConfig.pestsDestroyerAfkInfiniteMode) { + LogUtils.sendWarning("[Pests Destroyer] Disabling Pests Destroyer AFK Infinite Mode!"); + FarmHelperConfig.pestsDestroyerAfkInfiniteMode = false; + } + return false; } + return true; + } - if (getClosestPest() != null) { - FlyPathFinderExecutor.getInstance().stop(); - state = States.FIND_PEST; - break; + @SubscribeEvent + public void onTickExecute(TickEvent.ClientTickEvent event) { + if (mc.thePlayer == null || mc.theWorld == null) { + return; } - - if (FlyPathFinderExecutor.getInstance().isRunning()) { - return; + if (mc.currentScreen == null && checkedThisGui) { + checkedThisGui = false; + } + if (!gotRangeOfVacuum && (isToggled() || PestsDestroyerOnTheTrack.getInstance().isToggled())) { + Slot vacuumSlot = InventoryUtils.getSlotOfItemInInventory("Vacuum"); + if (vacuumSlot != null) { + ItemStack vacuumItem = vacuumSlot.getStack(); + for (Map.Entry vacuumRange : this.vacuumRange.entrySet()) { + if (vacuumItem.getDisplayName().contains(vacuumRange.getKey())) { + currentVacuumRange = vacuumRange.getValue(); + gotRangeOfVacuum = true; + LogUtils.sendDebug("[Pests Destroyer] Found vacuum range: " + currentVacuumRange); + break; + } + } + } } - - if (!mc.thePlayer.capabilities.isFlying) { - fly(); - break; + if (!isToggled()) { + return; } - if (hasBlocksAround()) { - KeyBindUtils.holdThese(mc.gameSettings.keyBindJump); - break; - } else { - if (mc.gameSettings.keyBindJump.isKeyDown()) { - KeyBindUtils.stopMovement(); - } + if (event.phase != TickEvent.Phase.END) { + return; } - - if (getLocationTries > 2) { - PlotUtils.Plot currentPlot = getClosestPlot(); - - if (!isNearPlotCenter()) { - if (currentPlot != null) { - BlockPos plotCenter2 = PlotUtils.getPlotCenter(currentPlot.number); - FlyPathFinderExecutor.getInstance().setSprinting(FarmHelperConfig.sprintWhileFlying); - FlyPathFinderExecutor.getInstance().setDontRotate(false); - FlyPathFinderExecutor.getInstance().setUseAOTV(InventoryUtils.hasItemInHotbar("Aspect of the Void", "Aspect of the End")); - FlyPathFinderExecutor.getInstance().findPath(new Vec3(plotCenter2.getX(), 80, plotCenter2.getZ()), true, true); - LogUtils.sendDebug("[Pests Destroyer] Flying to plot center"); - } else { - LogUtils.sendWarning("[Pests Destroyer] Couldn't find closest plot!"); - state = States.GO_BACK; - } - break; - } + if (!GameStateHandler.getInstance().inGarden() && escapeState == EscapeState.NONE) { + return; } - - resetFireworkInfo(); - lastFireworkTime = System.currentTimeMillis(); - MovingObjectPosition mop = mc.objectMouseOver; - if (RotationHandler.getInstance().isRotating()) { - break; + if (!enabled) { + return; } - float yaw = -1; - Vec3 playerPos = mc.thePlayer.getPositionEyes(1); - for (float i = 0; i < 360; i += 10) { - Vec3 testRotation = AngleUtils.getVectorForRotation(0, i); - Vec3 lookVector = playerPos.addVector(testRotation.xCoord * 5, testRotation.yCoord * 5, testRotation.zCoord * 5); - MovingObjectPosition mop2 = mc.theWorld.rayTraceBlocks(playerPos, lookVector, false, true, false); - if (mop2 == null || mop2.typeOfHit != MovingObjectPosition.MovingObjectType.BLOCK) { - yaw = i; - break; - } - } - Rotation upRotation = new Rotation((float) (yaw + (Math.random() * 5 - 2.5)), (float) (-20 + (Math.random() * 6 - 4))); - if (mop != null && mop.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK && RotationHandler.getInstance() - .shouldRotate(upRotation, 10)) { - RotationHandler.getInstance().easeTo(new RotationConfiguration( - upRotation, - FarmHelperConfig.getRandomRotationTime(), - null - ).easeOutBack(true)); - delayClock.schedule(300); - break; - } - state = States.WAIT_FOR_LOCATION; - if (getLocationTries > 4) { - LogUtils.sendWarning("[Pests Destroyer] Couldn't find any firework location. Trying to fix it by sending /pq low."); - mc.thePlayer.sendChatMessage("/pq low"); - getLocationTries = 0; - } - KeyBindUtils.leftClick(); - getLocationTries++; - if (!stuckClock.isScheduled()) { - stuckClock.schedule(1_000 * 60 * FarmHelperConfig.pestsKillerStuckTime); - } - delayClock.schedule(300); - break; - case WAIT_FOR_LOCATION: - if (isInventoryOpenDelayed()) { - break; - } - - if (RotationHandler.getInstance().isRotating()) { - return; - } - - if (getClosestPest() != null) { - state = States.FIND_PEST; - break; - } - - if (lastLocation != null && lastFireworkTime + 250 < System.currentTimeMillis()) { - Vec3 firework = calculateWaypoint(); - if (firework == null) { - LogUtils.sendDebug("[Pests Destroyer] Couldn't find any firework location. Looking for a firework."); - state = States.GET_LOCATION; - break; - } - if (mc.thePlayer.getDistance(firework.xCoord, firework.yCoord, firework.zCoord) < 2) { - int y = 150; - Block block = mc.theWorld.getBlockState(new BlockPos(firework.xCoord, y, firework.zCoord)).getBlock(); - Block[] blocksAround = new Block[]{ - mc.theWorld.getBlockState(new BlockPos(firework.xCoord + 1, y, firework.zCoord)).getBlock(), - mc.theWorld.getBlockState(new BlockPos(firework.xCoord - 1, y, firework.zCoord)).getBlock(), - mc.theWorld.getBlockState(new BlockPos(firework.xCoord, y, firework.zCoord + 1)).getBlock(), - mc.theWorld.getBlockState(new BlockPos(firework.xCoord, y, firework.zCoord - 1)).getBlock(), - block - }; - while (y > 90 && Arrays.stream(blocksAround).allMatch(b -> b.equals(Blocks.air))) { - y--; - } - y += 3; - FlyPathFinderExecutor.getInstance().setSprinting(false); - FlyPathFinderExecutor.getInstance().setDontRotate(true); - FlyPathFinderExecutor.getInstance().findPath(new Vec3(firework.xCoord, y, firework.zCoord), true, true); - LogUtils.sendWarning( - "[Pests Destroyer] Firework is too close to player. Flying to x: " + firework.xCoord + " y: " + y + " z: " + firework.zCoord); - break; - } - RotationHandler.getInstance().reset(); - state = States.FIND_PEST; - delayBetweenFireworks.schedule(3_000); - delayClock.schedule(300); - break; - } - if (System.currentTimeMillis() - lastFireworkTime > 6_000) { - state = States.GET_LOCATION; - break; - } - break; - case FIND_PEST: - if (isInventoryOpenDelayed()) { - break; + if (!FailsafeManager.getInstance().getEmergencyQueue().isEmpty()) { + return; } - getLocationTries = 0; - if (GameStateHandler.getInstance().getPestsCount() == 0) { - RotationHandler.getInstance().reset(); - state = States.CHECK_ANOTHER_PEST; - return; + if (FailsafeManager.getInstance().triggeredFailsafe.isPresent()) { + stop(); + return; } - Entity closestPest = getClosestPest(); - - if (closestPest == null) { - if (lastLocation == null) { - LogUtils.sendDebug("[Pests Destroyer] No firework location found. Looking for a firework."); - state = States.GET_LOCATION; - break; - } - - if (!FlyPathFinderExecutor.getInstance().isRunning()) { - Vec3 firework = calculateWaypoint(); - if (firework == null) { - LogUtils.sendDebug("[Pests Destroyer] Couldn't find any firework location. Looking for a firework."); - state = States.GET_LOCATION; - break; - } - if (mc.thePlayer.getDistance(firework.xCoord, firework.yCoord, firework.zCoord) < 2) { - state = States.GET_LOCATION; - break; - } - FlyPathFinderExecutor.getInstance().setSprinting(true); - FlyPathFinderExecutor.getInstance().setDontRotate(false); - FlyPathFinderExecutor.getInstance().setUseAOTV(InventoryUtils.hasItemInHotbar("Aspect of the Void", "Aspect of the End")); - FlyPathFinderExecutor.getInstance().findPath(firework, true, true); - } - break; - } - if (closestPest instanceof EntityArmorStand) { - Entity realEntity = PlayerUtils.getEntityCuttingOtherEntity(closestPest, (e) -> e instanceof EntityBat || e instanceof EntitySilverfish); - if (realEntity != null) { - closestPest = realEntity; - } + if (stuckClock.isScheduled() && stuckClock.passed()) { + LogUtils.sendWarning( + "[Pests Destroyer] The player is struggling killing pest for 5 minutes, will do a quick Garden -> Hub -> Garden teleport."); + LogUtils.sendFailsafeMessage("[Pests Destroyer] Couldn't kill pest for 5 minutes, will do a quick Garden -> Hub -> Garden teleport.", + true); + escapeState = EscapeState.GO_TO_HUB; + KeyBindUtils.stopMovement(); + delayClock.schedule(300); + stuckClock.reset(); + return; } - if (FlyPathFinderExecutor.getInstance().isRunning()) { - FlyPathFinderExecutor.getInstance().stop(); + + if (delayClock.isScheduled() && !delayClock.passed()) { + return; } - currentEntityTarget = Optional.of(closestPest); + LogUtils.sendDebug("[Pests Destroyer] State: " + state); - state = States.KILL_PEST; - cantReachPest = 0; - KeyBindUtils.stopMovement(); - if (!stuckClock.isScheduled()) { - stuckClock.schedule(1_000 * 60 * FarmHelperConfig.pestsKillerStuckTime); - } - delayClock.schedule(300); - break; - case KILL_PEST: - if (isInventoryOpenDelayed()) { - break; - } - if (mc.thePlayer.posY < 67 && FlyPathFinderExecutor.getInstance().isRunning()) { - FlyPathFinderExecutor.getInstance().stop(); - RotationHandler.getInstance().reset(); - state = States.GET_LOCATION; - return; - } - if (!currentEntityTarget.isPresent()) { - FlyPathFinderExecutor.getInstance().stop(); - RotationHandler.getInstance().reset(); - state = States.CHECK_ANOTHER_PEST; - return; - } - Entity entity = currentEntityTarget.get(); - if (entity.isDead || killedEntities.contains(entity) || !mc.theWorld.loadedEntityList.contains(entity)) { - RotationHandler.getInstance().reset(); - state = States.CHECK_ANOTHER_PEST; - FlyPathFinderExecutor.getInstance().stop(); - return; - } - - double distance2 = mc.thePlayer.getDistance(entity.posX, entity.posY + entity.getEyeHeight(), entity.posZ); - double distanceXZ = mc.thePlayer.getDistance(entity.posX, mc.thePlayer.posY, entity.posZ); - - float vacuumMinRange = Math.max(currentVacuumRange - 2, 3); - if (FarmHelperConfig.pestsKillerTicksOfNotSeeingPestWhileAttacking > 0 - && (distanceXZ < 1.5 || distance2 <= Math.max(vacuumMinRange - 2, 10)) - && Math.abs(mc.thePlayer.motionX) < 0.1 - && Math.abs(mc.thePlayer.motionZ) < 0.1 - && !canEntityBeSeenIgnoreNonCollidable(entity)) { - cantReachPest++; - } - - if (cantReachPest >= FarmHelperConfig.pestsKillerTicksOfNotSeeingPestWhileAttacking) { - LogUtils.sendWarning("[Pests Destroyer] Can't reach the pest, will do a quick Garden -> Hub -> Garden teleport."); - escapeState = EscapeState.GO_TO_HUB; - KeyBindUtils.stopMovement(); - delayClock.schedule(300); - return; - } - - if (distance2 < vacuumMinRange) { - float targetVelocity = (float) (Math.abs(entity.motionX) + Math.abs(entity.motionZ)); - if (vacuumMinRange > 8 || targetVelocity < 0.15) { - if (FlyPathFinderExecutor.getInstance().isRunning()) { - FlyPathFinderExecutor.getInstance().stop(); - LogUtils.sendDebug("[Pests Destroyer] Stopping pathfinder because the pest is close enough"); - float playerVelocity = (float) (Math.abs(mc.thePlayer.motionX) + Math.abs(mc.thePlayer.motionZ)); - if (playerVelocity > 0.9) { - KeyBindUtils.onTick(mc.gameSettings.keyBindBack); - } - } else { - float playerVelocity = (float) (Math.abs(mc.thePlayer.motionX) + Math.abs(mc.thePlayer.motionZ)); - if (playerVelocity > 0.15 && distanceXZ < 3) { - KeyBindUtils.onTick(mc.gameSettings.keyBindBack); - } + if (escapeState != EscapeState.NONE) { + if (stuckClock.isScheduled()) { + stuckClock.reset(); + } + if (RotationHandler.getInstance().isRotating()) { + RotationHandler.getInstance().reset(); } - } - if (rotationState != RotationState.CLOSE) { - rotationState = RotationState.CLOSE; - RotationHandler.getInstance().reset(); - } - if (!RotationHandler.getInstance().isRotating()) { - RotationHandler.getInstance().easeTo(new RotationConfiguration( - new Target(entity), - (long) (400 + Math.random() * 200), - null - ).followTarget(true)); - } - FlyPathFinderExecutor.getInstance().setUseAOTV(false); - ItemStack currentItem3 = mc.thePlayer.getHeldItem(); - if (getVacuum(currentItem3)) { - break; - } - KeyBindUtils.setKeyBindState(mc.gameSettings.keyBindUseItem, true); - } else { - if (rotationState != RotationState.FAR) { - FlyPathFinderExecutor.getInstance().stop(); - rotationState = RotationState.FAR; - RotationHandler.getInstance().reset(); - } - if (!FlyPathFinderExecutor.getInstance().isRunning()) { - double yAddition = Math.max(2.75, Math.min(currentVacuumRange - 5, 10)); - LogUtils.sendDebug("Should pathfind to: " + entity.posX + " " + yAddition + " " + entity.posZ); - FlyPathFinderExecutor.getInstance().setSprinting(FarmHelperConfig.sprintWhileFlying); - FlyPathFinderExecutor.getInstance().setUseAOTV(InventoryUtils.hasItemInHotbar("Aspect of the Void", "Aspect of the End")); - FlyPathFinderExecutor.getInstance().findPath(entity, true, true, (float) yAddition, true); - } - if (FlyPathFinderExecutor.getInstance().getState() == FlyPathFinderExecutor.State.FAILED - && mc.thePlayer.motionX == 0 && mc.thePlayer.motionZ == 0) { - flyPathfinderTries++; - } else { - flyPathfinderTries = 0; - } - if (flyPathfinderTries > 5) { - LogUtils.sendWarning("[Pests Destroyer] Couldn't pathfind to the pest. Flying from the spawnpoint."); - flyPathfinderTries = 0; KeyBindUtils.stopMovement(); - delayClock.schedule(1_000 + Math.random() * 500); - MacroHandler.getInstance().triggerWarpGarden(true, false); - state = States.CHECKING_SPAWN; - return; - } - if (!RotationHandler.getInstance().isRotating()) { - RotationHandler.getInstance().easeTo(new RotationConfiguration( - new Target(entity).additionalY(-0.3f), - (long) (400 + Math.random() * 200), - null - )); - } - FlyPathFinderExecutor.getInstance() - .setUseAOTV(distanceXZ > vacuumMinRange && InventoryUtils.hasItemInHotbar("Aspect of the Void", "Aspect of the End")); - if (distance2 < currentVacuumRange && getVacuum(mc.thePlayer.getHeldItem())) { - break; - } - KeyBindUtils.setKeyBindState(mc.gameSettings.keyBindUseItem, distance2 < currentVacuumRange); - } - break; - case CHECK_ANOTHER_PEST: - if (previousCurrentPlotPestsCount == GameStateHandler.getInstance().getCurrentPlotPestsCount() - && System.currentTimeMillis() - lastKillTimestamp < 2_000) { - return; - } - - LogUtils.sendDebug( - GameStateHandler.getInstance().getPestsCount() + " pest" + (GameStateHandler.getInstance().getPestsCount() == 1 ? "" : "s") + " left"); - if (GameStateHandler.getInstance().getPestsCount() == 0) { - state = States.GO_BACK; - delayClock.schedule((long) (500 + Math.random() * 500)); - break; - } - System.out.println("Curr plot pests: " + GameStateHandler.getInstance().getCurrentPlotPestsCount()); - isPlotObstructed = false; - Entity closestPest2 = getClosestPest(); - KeyBindUtils.stopMovement(); - if (closestPest2 != null) { - LogUtils.sendDebug("Found another pest"); - state = States.KILL_PEST; - currentEntityTarget = Optional.of(closestPest2); - delayClock.schedule(50 + (long) (Math.random() * 100)); - } else { - PlotUtils.Plot plotOpt = getClosestPlot(); - if (plotOpt != null) { - double distanceToPlot = Math.sqrt(mc.thePlayer.getDistanceSqToCenter(PlotUtils.getPlotCenter(plotOpt.number))); - LogUtils.sendDebug("Distance to plot: " + distanceToPlot); - if (distanceToPlot < 150 || FarmHelperConfig.dontTeleportToPlots) { - LogUtils.sendDebug("Going manually to another plot"); - state = States.GET_CLOSEST_PLOT; - delayClock.schedule(100 + (long) (Math.random() * 150)); - break; - } else { - LogUtils.sendDebug("Teleporting to plot"); - state = States.TELEPORT_TO_PLOT; - delayClock.schedule(400 + (long) (Math.random() * 400)); + switch (escapeState) { + case GO_TO_HUB: + if (isInventoryOpen()) { + break; + } + if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.HUB) { + escapeState = EscapeState.GO_TO_GARDEN; + delayClock.schedule((long) (5_500 + Math.random() * 3_500)); + break; + } + if (GameStateHandler.getInstance().inGarden()) { + mc.thePlayer.sendChatMessage("/hub"); + escapeState = EscapeState.GO_TO_GARDEN; + delayClock.schedule((long) (1_800 + Math.random() * 1_000)); + } + if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.TELEPORTING) { + delayClock.schedule((long) (500 + Math.random() * 500)); + break; + } + if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.LOBBY) { + escapeState = EscapeState.GO_TO_HUB; + mc.thePlayer.sendChatMessage("/skyblock"); + delayClock.schedule((long) (5_000 + Math.random() * 1_500)); + break; + } + break; + case GO_TO_GARDEN: + if (isInventoryOpen()) { + break; + } + if (GameStateHandler.getInstance().inGarden()) { + escapeState = EscapeState.GO_TO_HUB; + delayClock.schedule((long) (2_500 + Math.random() * 1_500)); + break; + } + if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.HUB) { + escapeState = EscapeState.RESUME_MACRO; + MacroHandler.getInstance().triggerWarpGarden(true, false); + delayClock.schedule((long) (2_500 + Math.random() * 1_500)); + break; + } + if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.TELEPORTING) { + delayClock.schedule((long) (500 + Math.random() * 500)); + break; + } + if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.LOBBY) { + escapeState = EscapeState.GO_TO_HUB; + mc.thePlayer.sendChatMessage("/skyblock"); + delayClock.schedule((long) (5_000 + Math.random() * 1_500)); + break; + } + break; + case RESUME_MACRO: + if (isInventoryOpen()) { + break; + } + if (GameStateHandler.getInstance().inGarden()) { + escapeState = EscapeState.NONE; + state = States.IDLE; + cantReachPest = 0; + delayClock.schedule((long) (1_000 + Math.random() * 500)); + LogUtils.sendDebug("[Pests Destroyer] Came back to Garden!"); + break; + } + if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.HUB) { + escapeState = EscapeState.RESUME_MACRO; + MacroHandler.getInstance().triggerWarpGarden(true, false); + delayClock.schedule((long) (2_500 + Math.random() * 1_500)); + break; + } + if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.TELEPORTING) { + delayClock.schedule((long) (500 + Math.random() * 500)); + break; + } + if (GameStateHandler.getInstance().getLocation() == GameStateHandler.Location.LOBBY) { + escapeState = EscapeState.GO_TO_HUB; + mc.thePlayer.sendChatMessage("/skyblock"); + delayClock.schedule((long) (5_000 + Math.random() * 1_500)); + break; + } + break; } - } else { - state = States.GO_BACK; - delayClock.schedule(300 + (long) (Math.random() * 300)); - } - } - break; - case GO_BACK: - state = States.FINISH; - break; - case FINISH: - finishing = true; - if (FarmHelperConfig.pestSwapArmorAfter && currentSlot != FarmHelperConfig.pestArmorSlot1) { - state = States.SWAP_ARMOR; - return; - } - finishMacro(); + return; + } + + switch (state) { + case IDLE: + ItemStack currentItem = mc.thePlayer.getHeldItem(); + if (GameStateHandler.getInstance().getPestsCount() == 0) { + if (isInventoryOpen()) { + return; + } +// finishMacro(); + state = States.FINISH; + return; + } + if (getVacuum(currentItem)) { + return; + } + state = States.SWAP_ARMOR; + delayClock.schedule((long) (200 + Math.random() * 200)); + break; + case SWAP_ARMOR: + if (FarmHelperConfig.pestSwapArmorBefore) { + currentSlot = FarmHelperConfig.pestArmorSlot0; + if (finishing) { + currentSlot = FarmHelperConfig.pestArmorSlot1; + } + if (AutoWardrobe.activeSlot != currentSlot) { + AutoWardrobe.instance.swapTo(currentSlot); + } + } + state = States.ARMOR_SWAP_VERIFY; + break; + case ARMOR_SWAP_VERIFY: + if (AutoWardrobe.instance.isRunning()) { + return; + } + if (finishing) { + state = States.FINISH; + } else { + if (needToUpdatePlots || PlotUtils.needToUpdatePlots()) { + state = States.OPEN_DESK; + } else { + if (FarmHelperConfig.dontTeleportToPlots) { + state = States.GET_CLOSEST_PLOT; + } else { + state = States.TELEPORT_TO_PLOT; + } + } + } + break; + case OPEN_DESK: + if (isInventoryOpen()) { + break; + } + mc.thePlayer.sendChatMessage("/desk"); + state = States.OPEN_PLOTS; + delayClock.schedule((long) (FarmHelperConfig.pestAdditionalGUIDelay + 500 + Math.random() * 500)); + break; + case OPEN_PLOTS: + String chestName = InventoryUtils.getInventoryName(); + if (mc.currentScreen == null) { + delayClock.schedule((long) (FarmHelperConfig.pestAdditionalGUIDelay + 300 + Math.random() * 300)); + break; + } + if (!InventoryUtils.isInventoryLoaded()) { + break; + } + if (chestName == null || !chestName.equals("Desk")) { + break; + } + Slot configurePlots = InventoryUtils.getSlotOfItemInContainer("Configure Plots"); + if (configurePlots == null) { + break; + } + state = States.WAIT_FOR_INFO; + InventoryUtils.clickContainerSlot(configurePlots.slotNumber, InventoryUtils.ClickType.LEFT, InventoryUtils.ClickMode.PICKUP); + delayClock.schedule((long) (FarmHelperConfig.pestAdditionalGUIDelay + 500 + Math.random() * 500)); + break; + case WAIT_FOR_INFO: + break; + case TELEPORT_TO_PLOT: + PlotUtils.Plot plot; + if (FarmHelperConfig.dontTeleportToPlots) { + delayClock.schedule(1_000 + Math.random() * 500); + MacroHandler.getInstance().triggerWarpGarden(true, false); + state = States.CHECKING_SPAWN; + return; + } else { + plot = getClosestPlot(); + } + if (plot == null) { + state = States.GO_BACK; + delayClock.schedule((long) (500 + Math.random() * 500)); + return; + } + if (GameStateHandler.getInstance().getCurrentPlot() == plot.number && BlockUtils.canFlyHigher(8)) { + state = States.GET_LOCATION; + break; + } + String plotNumber = plot.name; + preTpBlockPos = Optional.of(mc.thePlayer.getPosition()); + mc.thePlayer.sendChatMessage("/tptoplot " + plotNumber); + state = States.WAIT_FOR_TP; + delayClock.schedule((long) (900 + Math.random() * 500)); + break; + case WAIT_FOR_TP: + if (!preTpBlockPos.isPresent()) { + state = States.IDLE; + break; + } + if (mc.thePlayer.getPosition().equals(preTpBlockPos.get())) { + break; + } + state = States.CHECKING_PLOT; + delayClock.schedule((long) (200 + Math.random() * 200)); + break; + case CHECKING_PLOT: + if (isInventoryOpenDelayed()) { + break; + } + KeyBindUtils.stopMovement(); + + if (PlayerUtils.isPlayerSuffocating() || !BlockUtils.canFlyHigher(5)) { + LogUtils.sendWarning("[Pests Destroyer] The player is suffocating and/or it can't fly higher. Going back to spawnpoint."); + delayClock.schedule(1_000 + Math.random() * 500); + MacroHandler.getInstance().triggerWarpGarden(true, false); + isPlotObstructed = true; + state = States.CHECKING_SPAWN; + return; + } + state = States.GET_LOCATION; + break; + case CHECKING_SPAWN: + if (MacroHandler.getInstance().isTeleporting()) { + return; + } + + if (PlayerUtils.isPlayerSuffocating() || !BlockUtils.canFlyHigher(5)) { + LogUtils.sendError( + "[Pests Destroyer] Your spawnpoint is obstructed! Make sure there is no block above your spawnpoint! Disabling Pests Destroyer!"); + stop(); + FarmHelperConfig.enablePestsDestroyer = false; +// finishMacro(); + state = States.FINISH; + } else { + state = States.GET_CLOSEST_PLOT; + LogUtils.sendDebug("[Pests Destroyer] Spawnpoint is not obstructed"); + } + break; + case GET_CLOSEST_PLOT: + if (isInventoryOpenDelayed()) { + break; + } + + PlotUtils.Plot closestPlot = getClosestPlot(); + + if (closestPlot == null) { + LogUtils.sendError("[Pests Destroyer] Couldn't find closest plot!"); + state = States.GET_LOCATION; + return; + } + + double distance = Math.sqrt(mc.thePlayer.getDistanceSq(PlotUtils.getPlotCenter(closestPlot.number))); + + this.closestPlot = Optional.of(closestPlot); + + if (FarmHelperConfig.dontTeleportToPlots) { + if (PlayerUtils.isPlayerSuffocating() || !BlockUtils.canFlyHigher(3)) { + state = States.TELEPORT_TO_PLOT; + LogUtils.sendWarning( + "[Pests Destroyer] The player is suffocating and/or it can't fly higher. Forcing going back to spawnpoint."); + } else { + state = States.FLY_TO_THE_CLOSEST_PLOT; + } + break; + } + + if (distance > 150 && !isPlotObstructed) { + state = States.TELEPORT_TO_PLOT; + } else { + state = States.FLY_TO_THE_CLOSEST_PLOT; + } + delayClock.schedule((long) (500 + Math.random() * 500)); + break; + case FLY_TO_THE_CLOSEST_PLOT: + if (MacroHandler.getInstance().isTeleporting()) { + return; + } + if (isInventoryOpenDelayed()) { + break; + } + + if (!this.closestPlot.isPresent()) { + LogUtils.sendError("[Pests Destroyer] Couldn't find closest plot!"); + state = States.GET_LOCATION; + return; + } + + BlockPos plotCenter = PlotUtils.getPlotCenter(this.closestPlot.get().number); + + if (getClosestPest() != null) { + KeyBindUtils.stopMovement(); + state = States.FIND_PEST; + break; + } + + if ((mc.thePlayer.onGround || !flyDelay.passed()) && mc.thePlayer.capabilities.allowFlying && !mc.thePlayer.capabilities.isFlying) { + fly(); + break; + } + + if (mc.thePlayer.getDistance(plotCenter.getX(), mc.thePlayer.posY, plotCenter.getZ()) < 15) { + state = States.GET_LOCATION; + KeyBindUtils.stopMovement(); + FlyPathFinderExecutor.getInstance().stop(); + break; + } + + if (!FlyPathFinderExecutor.getInstance().isRunning()) { + FlyPathFinderExecutor.getInstance().setSprinting(true); + FlyPathFinderExecutor.getInstance().setDontRotate(false); + FlyPathFinderExecutor.getInstance().setUseAOTV(InventoryUtils.hasItemInHotbar("Aspect of the Void", "Aspect of the End")); + FlyPathFinderExecutor.getInstance().findPath(new Vec3(plotCenter.getX(), 80, plotCenter.getZ()), true, true); + } + break; + case GET_LOCATION: + if (GameStateHandler.getInstance().getPestsCount() == 0) { + state = States.GO_BACK; + return; + } + if (isInventoryOpenDelayed()) { + break; + } + ItemStack currentItem2 = mc.thePlayer.getHeldItem(); + if (getVacuum(currentItem2)) { + return; + } + + if (getClosestPest() != null) { + FlyPathFinderExecutor.getInstance().stop(); + state = States.FIND_PEST; + break; + } + + if (FlyPathFinderExecutor.getInstance().isRunning()) { + return; + } + + if (!mc.thePlayer.capabilities.isFlying) { + fly(); + break; + } + if (hasBlocksAround()) { + KeyBindUtils.holdThese(mc.gameSettings.keyBindJump); + break; + } else { + if (mc.gameSettings.keyBindJump.isKeyDown()) { + KeyBindUtils.stopMovement(); + } + } + + if (getLocationTries > 2) { + PlotUtils.Plot currentPlot = getClosestPlot(); + + if (!isNearPlotCenter()) { + if (currentPlot != null) { + BlockPos plotCenter2 = PlotUtils.getPlotCenter(currentPlot.number); + FlyPathFinderExecutor.getInstance().setSprinting(FarmHelperConfig.sprintWhileFlying); + FlyPathFinderExecutor.getInstance().setDontRotate(false); + FlyPathFinderExecutor.getInstance().setUseAOTV(InventoryUtils.hasItemInHotbar("Aspect of the Void", "Aspect of the End")); + FlyPathFinderExecutor.getInstance().findPath(new Vec3(plotCenter2.getX(), 80, plotCenter2.getZ()), true, true); + LogUtils.sendDebug("[Pests Destroyer] Flying to plot center"); + } else { + LogUtils.sendWarning("[Pests Destroyer] Couldn't find closest plot!"); + state = States.GO_BACK; + } + break; + } + } + + resetFireworkInfo(); + lastFireworkTime = System.currentTimeMillis(); + MovingObjectPosition mop = mc.objectMouseOver; + if (RotationHandler.getInstance().isRotating()) { + break; + } + float yaw = -1; + Vec3 playerPos = mc.thePlayer.getPositionEyes(1); + for (float i = 0; i < 360; i += 10) { + Vec3 testRotation = AngleUtils.getVectorForRotation(0, i); + Vec3 lookVector = playerPos.addVector(testRotation.xCoord * 5, testRotation.yCoord * 5, testRotation.zCoord * 5); + MovingObjectPosition mop2 = mc.theWorld.rayTraceBlocks(playerPos, lookVector, false, true, false); + if (mop2 == null || mop2.typeOfHit != MovingObjectPosition.MovingObjectType.BLOCK) { + yaw = i; + break; + } + } + Rotation upRotation = new Rotation((float) (yaw + (Math.random() * 5 - 2.5)), (float) (-20 + (Math.random() * 6 - 4))); + if (mop != null && mop.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK && RotationHandler.getInstance() + .shouldRotate(upRotation, 10)) { + RotationHandler.getInstance().easeTo(new RotationConfiguration( + upRotation, + FarmHelperConfig.getRandomRotationTime(), + null + ).easeOutBack(true)); + delayClock.schedule(300); + break; + } + state = States.WAIT_FOR_LOCATION; + if (getLocationTries > 4) { + LogUtils.sendWarning("[Pests Destroyer] Couldn't find any firework location. Trying to fix it by sending /pq low."); + mc.thePlayer.sendChatMessage("/pq low"); + getLocationTries = 0; + } + KeyBindUtils.leftClick(); + getLocationTries++; + if (!stuckClock.isScheduled()) { + stuckClock.schedule(1_000 * 60 * FarmHelperConfig.pestsKillerStuckTime); + } + delayClock.schedule(300); + break; + case WAIT_FOR_LOCATION: + if (isInventoryOpenDelayed()) { + break; + } + + if (RotationHandler.getInstance().isRotating()) { + return; + } + + if (getClosestPest() != null) { + state = States.FIND_PEST; + break; + } + + if (lastLocation != null && lastFireworkTime + 250 < System.currentTimeMillis()) { + Vec3 firework = calculateWaypoint(); + if (firework == null) { + LogUtils.sendDebug("[Pests Destroyer] Couldn't find any firework location. Looking for a firework."); + state = States.GET_LOCATION; + break; + } + if (mc.thePlayer.getDistance(firework.xCoord, firework.yCoord, firework.zCoord) < 2) { + int y = 150; + Block block = mc.theWorld.getBlockState(new BlockPos(firework.xCoord, y, firework.zCoord)).getBlock(); + Block[] blocksAround = new Block[]{ + mc.theWorld.getBlockState(new BlockPos(firework.xCoord + 1, y, firework.zCoord)).getBlock(), + mc.theWorld.getBlockState(new BlockPos(firework.xCoord - 1, y, firework.zCoord)).getBlock(), + mc.theWorld.getBlockState(new BlockPos(firework.xCoord, y, firework.zCoord + 1)).getBlock(), + mc.theWorld.getBlockState(new BlockPos(firework.xCoord, y, firework.zCoord - 1)).getBlock(), + block + }; + while (y > 90 && Arrays.stream(blocksAround).allMatch(b -> b.equals(Blocks.air))) { + y--; + } + y += 3; + FlyPathFinderExecutor.getInstance().setSprinting(false); + FlyPathFinderExecutor.getInstance().setDontRotate(true); + FlyPathFinderExecutor.getInstance().findPath(new Vec3(firework.xCoord, y, firework.zCoord), true, true); + LogUtils.sendWarning( + "[Pests Destroyer] Firework is too close to player. Flying to x: " + firework.xCoord + " y: " + y + " z: " + + firework.zCoord); + break; + } + RotationHandler.getInstance().reset(); + state = States.FIND_PEST; + delayBetweenFireworks.schedule(3_000); + delayClock.schedule(300); + break; + } + if (System.currentTimeMillis() - lastFireworkTime > 6_000) { + state = States.GET_LOCATION; + break; + } + break; + case FIND_PEST: + if (isInventoryOpenDelayed()) { + break; + } + getLocationTries = 0; + if (GameStateHandler.getInstance().getPestsCount() == 0) { + RotationHandler.getInstance().reset(); + state = States.CHECK_ANOTHER_PEST; + return; + } + + Entity closestPest = getClosestPest(); + + if (closestPest == null) { + if (lastLocation == null) { + LogUtils.sendDebug("[Pests Destroyer] No firework location found. Looking for a firework."); + state = States.GET_LOCATION; + break; + } + + if (!FlyPathFinderExecutor.getInstance().isRunning()) { + Vec3 firework = calculateWaypoint(); + if (firework == null) { + LogUtils.sendDebug("[Pests Destroyer] Couldn't find any firework location. Looking for a firework."); + state = States.GET_LOCATION; + break; + } + if (mc.thePlayer.getDistance(firework.xCoord, firework.yCoord, firework.zCoord) < 2) { + state = States.GET_LOCATION; + break; + } + FlyPathFinderExecutor.getInstance().setSprinting(true); + FlyPathFinderExecutor.getInstance().setDontRotate(false); + FlyPathFinderExecutor.getInstance().setUseAOTV(InventoryUtils.hasItemInHotbar("Aspect of the Void", "Aspect of the End")); + FlyPathFinderExecutor.getInstance().findPath(firework, true, true); + } + break; + } + if (closestPest instanceof EntityArmorStand) { + Entity realEntity = PlayerUtils.getEntityCuttingOtherEntity(closestPest, + (e) -> e instanceof EntityBat || e instanceof EntitySilverfish); + if (realEntity != null) { + closestPest = realEntity; + } + } + if (FlyPathFinderExecutor.getInstance().isRunning()) { + FlyPathFinderExecutor.getInstance().stop(); + } + + currentEntityTarget = Optional.of(closestPest); + + state = States.KILL_PEST; + cantReachPest = 0; + KeyBindUtils.stopMovement(); + if (!stuckClock.isScheduled()) { + stuckClock.schedule(1_000 * 60 * FarmHelperConfig.pestsKillerStuckTime); + } + delayClock.schedule(300); + break; + case KILL_PEST: + if (isInventoryOpenDelayed()) { + break; + } + if (mc.thePlayer.posY < 67 && FlyPathFinderExecutor.getInstance().isRunning()) { + FlyPathFinderExecutor.getInstance().stop(); + RotationHandler.getInstance().reset(); + state = States.GET_LOCATION; + return; + } + if (!currentEntityTarget.isPresent()) { + FlyPathFinderExecutor.getInstance().stop(); + RotationHandler.getInstance().reset(); + state = States.CHECK_ANOTHER_PEST; + return; + } + Entity entity = currentEntityTarget.get(); + if (entity.isDead || killedEntities.contains(entity) || !mc.theWorld.loadedEntityList.contains(entity)) { + RotationHandler.getInstance().reset(); + state = States.CHECK_ANOTHER_PEST; + FlyPathFinderExecutor.getInstance().stop(); + return; + } + + double distance2 = mc.thePlayer.getDistance(entity.posX, entity.posY + entity.getEyeHeight(), entity.posZ); + double distanceXZ = mc.thePlayer.getDistance(entity.posX, mc.thePlayer.posY, entity.posZ); + + float vacuumMinRange = Math.max(currentVacuumRange - 2, 3); + if (FarmHelperConfig.pestsKillerTicksOfNotSeeingPestWhileAttacking > 0 + && (distanceXZ < 1.5 || distance2 <= Math.max(vacuumMinRange - 2, 10)) + && Math.abs(mc.thePlayer.motionX) < 0.1 + && Math.abs(mc.thePlayer.motionZ) < 0.1 + && !canEntityBeSeenIgnoreNonCollidable(entity)) { + cantReachPest++; + } + + if (cantReachPest >= FarmHelperConfig.pestsKillerTicksOfNotSeeingPestWhileAttacking) { + LogUtils.sendWarning("[Pests Destroyer] Can't reach the pest, will do a quick Garden -> Hub -> Garden teleport."); + escapeState = EscapeState.GO_TO_HUB; + KeyBindUtils.stopMovement(); + delayClock.schedule(300); + return; + } + + if (distance2 < vacuumMinRange) { + float targetVelocity = (float) (Math.abs(entity.motionX) + Math.abs(entity.motionZ)); + if (vacuumMinRange > 8 || targetVelocity < 0.15) { + if (FlyPathFinderExecutor.getInstance().isRunning()) { + FlyPathFinderExecutor.getInstance().stop(); + LogUtils.sendDebug("[Pests Destroyer] Stopping pathfinder because the pest is close enough"); + float playerVelocity = (float) (Math.abs(mc.thePlayer.motionX) + Math.abs(mc.thePlayer.motionZ)); + if (playerVelocity > 0.9) { + KeyBindUtils.onTick(mc.gameSettings.keyBindBack); + } + } else { + float playerVelocity = (float) (Math.abs(mc.thePlayer.motionX) + Math.abs(mc.thePlayer.motionZ)); + if (playerVelocity > 0.15 && distanceXZ < 3) { + KeyBindUtils.onTick(mc.gameSettings.keyBindBack); + } + } + } + if (rotationState != RotationState.CLOSE) { + rotationState = RotationState.CLOSE; + RotationHandler.getInstance().reset(); + } + if (!RotationHandler.getInstance().isRotating()) { + RotationHandler.getInstance().easeTo(new RotationConfiguration( + new Target(entity), + (long) (400 + Math.random() * 200), + null + ).followTarget(true)); + } + FlyPathFinderExecutor.getInstance().setUseAOTV(false); + ItemStack currentItem3 = mc.thePlayer.getHeldItem(); + if (getVacuum(currentItem3)) { + break; + } + KeyBindUtils.setKeyBindState(mc.gameSettings.keyBindUseItem, true); + } else { + if (rotationState != RotationState.FAR) { + FlyPathFinderExecutor.getInstance().stop(); + rotationState = RotationState.FAR; + RotationHandler.getInstance().reset(); + } + if (!FlyPathFinderExecutor.getInstance().isRunning()) { + double yAddition = Math.max(2.75, Math.min(currentVacuumRange - 5, 10)); + LogUtils.sendDebug("Should pathfind to: " + entity.posX + " " + yAddition + " " + entity.posZ); + FlyPathFinderExecutor.getInstance().setSprinting(FarmHelperConfig.sprintWhileFlying); + FlyPathFinderExecutor.getInstance().setUseAOTV(InventoryUtils.hasItemInHotbar("Aspect of the Void", "Aspect of the End")); + FlyPathFinderExecutor.getInstance().findPath(entity, true, true, (float) yAddition, true); + } + if (FlyPathFinderExecutor.getInstance().getState() == FlyPathFinderExecutor.State.FAILED + && mc.thePlayer.motionX == 0 && mc.thePlayer.motionZ == 0) { + flyPathfinderTries++; + } else { + flyPathfinderTries = 0; + } + if (flyPathfinderTries > 5) { + LogUtils.sendWarning("[Pests Destroyer] Couldn't pathfind to the pest. Flying from the spawnpoint."); + flyPathfinderTries = 0; + KeyBindUtils.stopMovement(); + delayClock.schedule(1_000 + Math.random() * 500); + MacroHandler.getInstance().triggerWarpGarden(true, false); + state = States.CHECKING_SPAWN; + return; + } + if (!RotationHandler.getInstance().isRotating()) { + RotationHandler.getInstance().easeTo(new RotationConfiguration( + new Target(entity).additionalY(-0.3f), + (long) (400 + Math.random() * 200), + null + )); + } + FlyPathFinderExecutor.getInstance() + .setUseAOTV(distanceXZ > vacuumMinRange && InventoryUtils.hasItemInHotbar("Aspect of the Void", "Aspect of the End")); + if (distance2 < currentVacuumRange && getVacuum(mc.thePlayer.getHeldItem())) { + break; + } + KeyBindUtils.setKeyBindState(mc.gameSettings.keyBindUseItem, distance2 < currentVacuumRange); + } + break; + case CHECK_ANOTHER_PEST: + if (previousCurrentPlotPestsCount == GameStateHandler.getInstance().getCurrentPlotPestsCount() + && System.currentTimeMillis() - lastKillTimestamp < 2_000) { + return; + } + + LogUtils.sendDebug( + GameStateHandler.getInstance().getPestsCount() + " pest" + (GameStateHandler.getInstance().getPestsCount() == 1 ? "" : "s") + + " left"); + if (GameStateHandler.getInstance().getPestsCount() == 0) { + state = States.GO_BACK; + delayClock.schedule((long) (500 + Math.random() * 500)); + break; + } + System.out.println("Curr plot pests: " + GameStateHandler.getInstance().getCurrentPlotPestsCount()); + isPlotObstructed = false; + Entity closestPest2 = getClosestPest(); + KeyBindUtils.stopMovement(); + if (closestPest2 != null) { + LogUtils.sendDebug("Found another pest"); + state = States.KILL_PEST; + currentEntityTarget = Optional.of(closestPest2); + delayClock.schedule(50 + (long) (Math.random() * 100)); + } else { + PlotUtils.Plot plotOpt = getClosestPlot(); + if (plotOpt != null) { + double distanceToPlot = Math.sqrt(mc.thePlayer.getDistanceSqToCenter(PlotUtils.getPlotCenter(plotOpt.number))); + LogUtils.sendDebug("Distance to plot: " + distanceToPlot); + if (distanceToPlot < 150 || FarmHelperConfig.dontTeleportToPlots) { + LogUtils.sendDebug("Going manually to another plot"); + state = States.GET_CLOSEST_PLOT; + delayClock.schedule(100 + (long) (Math.random() * 150)); + break; + } else { + LogUtils.sendDebug("Teleporting to plot"); + state = States.TELEPORT_TO_PLOT; + delayClock.schedule(400 + (long) (Math.random() * 400)); + } + } else { + state = States.GO_BACK; + delayClock.schedule(300 + (long) (Math.random() * 300)); + } + } + break; + case GO_BACK: + state = States.FINISH; + break; + case FINISH: + finishing = true; + if (FarmHelperConfig.pestSwapArmorAfter && currentSlot != FarmHelperConfig.pestArmorSlot1) { + state = States.SWAP_ARMOR; + return; + } + finishMacro(); // state = States.FINISH; - break; + break; + } } - } - - @Nullable - private Entity getClosestPest() { - Entity closestPest = null; - double closestDistance = Double.MAX_VALUE; - for (Entity entity : pestsLocations) { - double distance = mc.thePlayer.getDistanceToEntity(entity); - if (distance < closestDistance) { - closestDistance = distance; - closestPest = entity; - } + + @Nullable + private Entity getClosestPest() { + Entity closestPest = null; + double closestDistance = Double.MAX_VALUE; + for (Entity entity : pestsLocations) { + double distance = mc.thePlayer.getDistanceToEntity(entity); + if (distance < closestDistance) { + closestDistance = distance; + closestPest = entity; + } + } + return closestPest; } - return closestPest; - } - - public boolean getVacuum(ItemStack currentItem2) { - if (currentItem2 == null || !currentItem2.getDisplayName().contains("Vacuum")) { - int vacuum = InventoryUtils.getSlotIdOfItemInHotbar("Vacuum"); - if (vacuum == -1) { - LogUtils.sendError("[Pests Destroyer] Failed to find vacuum in hotbar!"); - state = States.GO_BACK; - FarmHelperConfig.enablePestsDestroyer = false; + + public boolean getVacuum(ItemStack currentItem2) { + if (currentItem2 == null || !currentItem2.getDisplayName().contains("Vacuum")) { + int vacuum = InventoryUtils.getSlotIdOfItemInHotbar("Vacuum"); + if (vacuum == -1) { + LogUtils.sendError("[Pests Destroyer] Failed to find vacuum in hotbar!"); + state = States.GO_BACK; + FarmHelperConfig.enablePestsDestroyer = false; // finishMacro(); - state = States.FINISH; - return true; - } - mc.thePlayer.inventory.currentItem = vacuum; - delayClock.schedule((long) (200 + Math.random() * 200)); - return true; + state = States.FINISH; + return true; + } + mc.thePlayer.inventory.currentItem = vacuum; + delayClock.schedule((long) (200 + Math.random() * 200)); + return true; + } + return false; } - return false; - } - - private boolean isInventoryOpenDelayed() { - if (mc.currentScreen != null) { - KeyBindUtils.stopMovement(); - delayClock.schedule(300 + (long) (Math.random() * 300)); - Multithreading.schedule(() -> { + + private boolean isInventoryOpenDelayed() { if (mc.currentScreen != null) { - PlayerUtils.closeScreen(); - delayClock.schedule(100 + (long) (Math.random() * 200)); + KeyBindUtils.stopMovement(); + delayClock.schedule(300 + (long) (Math.random() * 300)); + Multithreading.schedule(() -> { + if (mc.currentScreen != null) { + PlayerUtils.closeScreen(); + delayClock.schedule(100 + (long) (Math.random() * 200)); + } + }, (long) (200 + Math.random() * 100), TimeUnit.MILLISECONDS); + return true; } - }, (long) (200 + Math.random() * 100), TimeUnit.MILLISECONDS); - return true; - } - return false; - } - - private boolean isInventoryOpen() { - if (mc.currentScreen != null) { - PlayerUtils.closeScreen(); - delayClock.schedule(500 + (long) (Math.random() * 500)); - return true; + return false; } - return false; - } - - private void finishMacro() { - if (isInventoryOpen()) { - return; - } - if (FlyPathFinderExecutor.getInstance().isPathing()) { - FlyPathFinderExecutor.getInstance().stop(); - } - if (MacroHandler.getInstance().isMacroToggled()) { - stop(); - MacroHandler.getInstance().triggerWarpGarden(true, true, false); - delayClock.schedule(2_000 + Math.random() * 500); - } else { - stop(); - } - } - - private boolean hasBlocksAround() { - Vec3 angle0 = AngleUtils.getVectorForRotation(0, mc.thePlayer.rotationYaw); - Vec3 angle90 = AngleUtils.getVectorForRotation(90, mc.thePlayer.rotationYaw); - Vec3 angle180 = AngleUtils.getVectorForRotation(180, mc.thePlayer.rotationYaw); - Vec3 angle270 = AngleUtils.getVectorForRotation(270, mc.thePlayer.rotationYaw); - Vec3 playerPos = mc.thePlayer.getPositionEyes(1); - if (checkIfBlockExists(angle0, playerPos)) { - return true; - } - if (checkIfBlockExists(angle90, playerPos)) { - return true; - } - if (checkIfBlockExists(angle180, playerPos)) { - return true; - } - return checkIfBlockExists(angle270, playerPos); - } - - private boolean checkIfBlockExists(Vec3 angle0, Vec3 playerPos) { - MovingObjectPosition mop0 = mc.theWorld.rayTraceBlocks(playerPos, - playerPos.addVector(angle0.xCoord * 1.5, angle0.yCoord * 1.5, angle0.zCoord * 1.5), false, true, false); - return mop0 != null && mop0.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK; - } - - @SubscribeEvent(receiveCanceled = true) - public void onChat(ClientChatReceivedEvent event) { - if (event.type != 0 || event.message == null) { - return; - } - String message = StringUtils.stripControlCodes(event.message.getUnformattedText().trim()); - if (message.startsWith("You can't fast travel while in combat!") && enabled) { - LogUtils.sendWarning("[Pests Destroyer] Can't fast travel while in combat, will try again to teleport."); -// Multithreading.schedule(this::finishMacro, 1_000 + (long) (Math.random() * 1_000), TimeUnit.MILLISECONDS); - state = States.FINISH; - return; - } - if (message.toLowerCase().startsWith("there are not any pests on your garden right now") && enabled && state != States.GO_BACK) { - LogUtils.sendDebug("[Pests Destroyer] There are not any Pests on your Garden right now! Keep farming!"); - state = States.GO_BACK; - delayClock.schedule((long) (500 + Math.random() * 500)); - return; - } - if (message.contains("The worm seems to have burrowed")) { - cantReachPest = 0; - return; - } - if (message.contains("Couldn't find Plot")) { - needToUpdatePlots = true; - delayClock.schedule((long) (500 + Math.random() * 500)); + private boolean isInventoryOpen() { + if (mc.currentScreen != null) { + PlayerUtils.closeScreen(); + delayClock.schedule(500 + (long) (Math.random() * 500)); + return true; + } + return false; } - } - private final Color vacuumRangeColor = new Color(200, 30, 30, 100); - @SubscribeEvent - public void onRender(RenderWorldLastEvent event) { - if (mc.thePlayer == null || mc.theWorld == null) { - return; + private void finishMacro() { + if (isInventoryOpen()) { + return; + } + if (FlyPathFinderExecutor.getInstance().isPathing()) { + FlyPathFinderExecutor.getInstance().stop(); + } + if (MacroHandler.getInstance().isMacroToggled()) { + stop(); + MacroHandler.getInstance().triggerWarpGarden(true, true, false); + delayClock.schedule(2_000 + Math.random() * 500); + } else { + stop(); + } } - if (!GameStateHandler.getInstance().inGarden()) { - return; + + private boolean hasBlocksAround() { + Vec3 angle0 = AngleUtils.getVectorForRotation(0, mc.thePlayer.rotationYaw); + Vec3 angle90 = AngleUtils.getVectorForRotation(90, mc.thePlayer.rotationYaw); + Vec3 angle180 = AngleUtils.getVectorForRotation(180, mc.thePlayer.rotationYaw); + Vec3 angle270 = AngleUtils.getVectorForRotation(270, mc.thePlayer.rotationYaw); + Vec3 playerPos = mc.thePlayer.getPositionEyes(1); + if (checkIfBlockExists(angle0, playerPos)) { + return true; + } + if (checkIfBlockExists(angle90, playerPos)) { + return true; + } + if (checkIfBlockExists(angle180, playerPos)) { + return true; + } + return checkIfBlockExists(angle270, playerPos); } - killedEntities.removeIf(e -> !mc.theWorld.loadedEntityList.contains(e)); + private boolean checkIfBlockExists(Vec3 angle0, Vec3 playerPos) { + MovingObjectPosition mop0 = mc.theWorld.rayTraceBlocks(playerPos, + playerPos.addVector(angle0.xCoord * 1.5, angle0.yCoord * 1.5, angle0.zCoord * 1.5), false, true, false); + return mop0 != null && mop0.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK; + } - List pests = mc.theWorld.loadedEntityList.stream().filter(entity -> { - if (entity.isDead) { - return false; - } - if (entity.posY < 50) { - return false; - } - if (entity instanceof EntityArmorStand) { - if (killedEntities.contains(entity)) { - return false; + @SubscribeEvent(receiveCanceled = true) + public void onChat(ClientChatReceivedEvent event) { + if (event.type != 0 || event.message == null) { + return; } - ItemStack itemStack = ((EntityArmorStand) entity).getEquipmentInSlot(4); - if (itemStack == null || !itemStack.hasTagCompound()) { - return false; + String message = StringUtils.stripControlCodes(event.message.getUnformattedText().trim()); + if (message.startsWith("You can't fast travel while in combat!") && enabled) { + LogUtils.sendWarning("[Pests Destroyer] Can't fast travel while in combat, will try again to teleport."); +// Multithreading.schedule(this::finishMacro, 1_000 + (long) (Math.random() * 1_000), TimeUnit.MILLISECONDS); + state = States.FINISH; + return; } - String displayName = itemStack.getTagCompound().toString(); - if (displayName.contains("display:")) { - return false; + if (message.toLowerCase().startsWith("there are not any pests on your garden right now") && enabled && state != States.GO_BACK) { + LogUtils.sendDebug("[Pests Destroyer] There are not any Pests on your Garden right now! Keep farming!"); + state = States.GO_BACK; + delayClock.schedule((long) (500 + Math.random() * 500)); + return; } - if (this.pests.stream().noneMatch(pest -> displayName.contains(pest.getSecond()))) { - return false; + if (message.contains("The worm seems to have burrowed")) { + cantReachPest = 0; + return; } - if (killedEntities.contains(entity)) { - return false; + if (message.contains("Couldn't find Plot")) { + needToUpdatePlots = true; + delayClock.schedule((long) (500 + Math.random() * 500)); } - Entity realEntity = PlayerUtils.getEntityCuttingOtherEntity(entity, (e) -> e instanceof EntityBat || e instanceof EntitySilverfish); - Entity nameEntity = PlayerUtils.getEntityCuttingOtherEntity(entity, (e) -> e instanceof EntityArmorStand && e != entity); - if (realEntity != null && (killedEntities.contains(realEntity) || realEntity.isDead)) { - return false; + } + + private final Color vacuumRangeColor = new Color(200, 30, 30, 100); + + @SubscribeEvent + public void onRender(RenderWorldLastEvent event) { + if (mc.thePlayer == null || mc.theWorld == null) { + return; } - if (nameEntity != null && (killedEntities.contains(nameEntity))) { - return false; + if (!GameStateHandler.getInstance().inGarden()) { + return; } - if (killedEntities.stream().noneMatch(ke -> ke.getDistanceToEntity(entity) < 1.5)) { - if (!FarmHelperConfig.streamerMode) { - drawESP(entity); - } - return true; + + killedEntities.removeIf(e -> !mc.theWorld.loadedEntityList.contains(e)); + + List pests = mc.theWorld.loadedEntityList.stream().filter(entity -> { + if (entity.isDead) { + return false; + } + if (entity.posY < 50) { + return false; + } + if (entity instanceof EntityArmorStand) { + if (killedEntities.contains(entity)) { + return false; + } + ItemStack itemStack = ((EntityArmorStand) entity).getEquipmentInSlot(4); + if (itemStack == null || !itemStack.hasTagCompound()) { + return false; + } + String displayName = itemStack.getTagCompound().toString(); + if (displayName.contains("display:")) { + return false; + } + if (this.pests.stream().noneMatch(pest -> displayName.contains(pest.getSecond()))) { + return false; + } + if (killedEntities.contains(entity)) { + return false; + } + Entity realEntity = PlayerUtils.getEntityCuttingOtherEntity(entity, (e) -> e instanceof EntityBat || e instanceof EntitySilverfish); + Entity nameEntity = PlayerUtils.getEntityCuttingOtherEntity(entity, (e) -> e instanceof EntityArmorStand && e != entity); + if (realEntity != null && (killedEntities.contains(realEntity) || realEntity.isDead)) { + return false; + } + if (nameEntity != null && (killedEntities.contains(nameEntity))) { + return false; + } + if (killedEntities.stream().noneMatch(ke -> ke.getDistanceToEntity(entity) < 1.5)) { + if (!FarmHelperConfig.streamerMode) { + drawESP(entity); + } + return true; + } + return false; + } + return false; + }).collect(Collectors.toList()); + + pestsLocations.clear(); + pestsLocations.addAll(pests); + + if (!FarmHelperConfig.highlightPlotWithPests) { + return; } - return false; - } - return false; - }).collect(Collectors.toList()); - pestsLocations.clear(); - pestsLocations.addAll(pests); + double d0 = Minecraft.getMinecraft().getRenderManager().viewerPosX; + double d1 = Minecraft.getMinecraft().getRenderManager().viewerPosY; + double d2 = Minecraft.getMinecraft().getRenderManager().viewerPosZ; + for (int plotNumber : GameStateHandler.getInstance().getInfestedPlots()) { + List> chunks = PlotUtils.getPlotChunksBasedOnNumber(plotNumber); + if (chunks.isEmpty()) { + continue; + } + AxisAlignedBB boundingBox = new AxisAlignedBB(chunks.get(0).getFirst() * 16, 66, chunks.get(0).getSecond() * 16, + chunks.get(chunks.size() - 1).getFirst() * 16 + 16, 80, chunks.get(chunks.size() - 1).getSecond() * 16 + 16); + float centerX = (float) (boundingBox.minX + (boundingBox.maxX - boundingBox.minX) / 2); + float centerZ = (float) (boundingBox.minZ + (boundingBox.maxZ - boundingBox.minZ) / 2); + boundingBox = boundingBox.offset(-d0, -d1, -d2); + RenderUtils.drawBox(boundingBox, FarmHelperConfig.plotHighlightColor.toJavaColor()); + RenderUtils.drawText("Plot " + plotNumber, centerX, 80, centerZ, 1); + } - if (!FarmHelperConfig.highlightPlotWithPests) { - return; - } + if (!FarmHelperConfig.debugMode) { + return; + } - double d0 = Minecraft.getMinecraft().getRenderManager().viewerPosX; - double d1 = Minecraft.getMinecraft().getRenderManager().viewerPosY; - double d2 = Minecraft.getMinecraft().getRenderManager().viewerPosZ; - for (int plotNumber : GameStateHandler.getInstance().getInfestedPlots()) { - List> chunks = PlotUtils.getPlotChunksBasedOnNumber(plotNumber); - if (chunks.isEmpty()) { - continue; - } - AxisAlignedBB boundingBox = new AxisAlignedBB(chunks.get(0).getFirst() * 16, 66, chunks.get(0).getSecond() * 16, - chunks.get(chunks.size() - 1).getFirst() * 16 + 16, 80, chunks.get(chunks.size() - 1).getSecond() * 16 + 16); - float centerX = (float) (boundingBox.minX + (boundingBox.maxX - boundingBox.minX) / 2); - float centerZ = (float) (boundingBox.minZ + (boundingBox.maxZ - boundingBox.minZ) / 2); - boundingBox = boundingBox.offset(-d0, -d1, -d2); - RenderUtils.drawBox(boundingBox, FarmHelperConfig.plotHighlightColor.toJavaColor()); - RenderUtils.drawText("Plot " + plotNumber, centerX, 80, centerZ, 1); + ItemStack currentItem = mc.thePlayer.getHeldItem(); + if (currentItem == null || !currentItem.getDisplayName().contains("Vacuum")) { + return; + } + Vec3 lookVec = mc.thePlayer.getLookVec(); + Vec3 playerPos = new Vec3(0, mc.thePlayer.eyeHeight, 0); + Vec3 vacuumRange = playerPos.addVector(lookVec.xCoord * currentVacuumRange, lookVec.yCoord * currentVacuumRange, + lookVec.zCoord * currentVacuumRange); + AxisAlignedBB aabb = new AxisAlignedBB(vacuumRange.xCoord - 0.05, vacuumRange.yCoord - 0.05, vacuumRange.zCoord - 0.05, + vacuumRange.xCoord + 0.05, + vacuumRange.yCoord + 0.05, vacuumRange.zCoord + 0.05); + RenderUtils.drawBox(aabb, vacuumRangeColor); + } + + private void drawESP(Entity entity) { + AxisAlignedBB boundingBox = new AxisAlignedBB(entity.posX - 0.5, entity.posY + entity.getEyeHeight() - 0.35, entity.posZ - 0.5, + entity.posX + 0.5, + entity.posY + entity.getEyeHeight() + 0.65, entity.posZ + 0.5); + double d0 = Minecraft.getMinecraft().getRenderManager().viewerPosX; + double d1 = Minecraft.getMinecraft().getRenderManager().viewerPosY; + double d2 = Minecraft.getMinecraft().getRenderManager().viewerPosZ; + boundingBox = boundingBox.offset(-d0, -d1, -d2); + if (FarmHelperConfig.pestsESP) { + Color color = FarmHelperConfig.pestsESPColor.toJavaColor(); + Vec3 entityPos = new Vec3(entity.posX, entity.posY + entity.getEyeHeight(), entity.posZ); + double distance = mc.thePlayer.getPositionEyes(1).distanceTo(entityPos); + boolean isInVacuumRange = distance < currentVacuumRange; + if (isInVacuumRange) { + color = new Color(color.getRed(), 255, color.getBlue(), Math.min(50, color.getAlpha())); + } + if (distance > 5) { + try { + EnumChatFormatting distanceColor = distance > currentVacuumRange ? EnumChatFormatting.RED : EnumChatFormatting.GREEN; + ItemStack itemStack = ((EntityArmorStand) entity).getEquipmentInSlot(4); + NBTTagCompound tagCompound = itemStack.getTagCompound(); + String texture = tagCompound.getCompoundTag("SkullOwner").getCompoundTag("Properties").getTagList("textures", 10) + .getCompoundTagAt(0) + .getString("Value"); + String pestName = this.pests.stream().filter(pest -> texture.equals(pest.getSecond())).findFirst().get().getFirst(); + RenderUtils.drawText(pestName + String.format(distanceColor + " %.1fm", distance), entity.posX, + entity.posY + entity.getEyeHeight() + 0.65 + 0.5, entity.posZ, (float) (1 + Math.min((distance / 20f), 2f))); + } catch (Exception ignored) { + } + } + RenderUtils.drawBox(boundingBox, color); + } + if (FarmHelperConfig.pestsTracers) { + RenderUtils.drawTracer(new Vec3(entity.posX, entity.posY + entity.getEyeHeight(), entity.posZ), + FarmHelperConfig.pestsTracersColor.toJavaColor()); + } } - if (!FarmHelperConfig.debugMode) { - return; + private boolean canEntityBeSeenIgnoreNonCollidable(Entity entity) { + Vec3 vec3 = new Vec3(entity.posX, entity.posY + entity.getEyeHeight() + 0.5, entity.posZ); + Vec3 vec31 = new Vec3(mc.thePlayer.posX, mc.thePlayer.posY + mc.thePlayer.getEyeHeight(), mc.thePlayer.posZ); + MovingObjectPosition mop = mc.theWorld.rayTraceBlocks(vec31, vec3, false, true, false); + return mop == null || mop.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK && ( + mc.theWorld.getBlockState(mop.getBlockPos()).getBlock().equals(Blocks.cactus) || !BlockUtils.hasCollision(mop.getBlockPos())); } - ItemStack currentItem = mc.thePlayer.getHeldItem(); - if (currentItem == null || !currentItem.getDisplayName().contains("Vacuum")) { - return; - } - Vec3 lookVec = mc.thePlayer.getLookVec(); - Vec3 playerPos = new Vec3(0, mc.thePlayer.eyeHeight, 0); - Vec3 vacuumRange = playerPos.addVector(lookVec.xCoord * currentVacuumRange, lookVec.yCoord * currentVacuumRange, - lookVec.zCoord * currentVacuumRange); - AxisAlignedBB aabb = new AxisAlignedBB(vacuumRange.xCoord - 0.05, vacuumRange.yCoord - 0.05, vacuumRange.zCoord - 0.05, vacuumRange.xCoord + 0.05, - vacuumRange.yCoord + 0.05, vacuumRange.zCoord + 0.05); - RenderUtils.drawBox(aabb, vacuumRangeColor); - } - - private void drawESP(Entity entity) { - AxisAlignedBB boundingBox = new AxisAlignedBB(entity.posX - 0.5, entity.posY + entity.getEyeHeight() - 0.35, entity.posZ - 0.5, entity.posX + 0.5, - entity.posY + entity.getEyeHeight() + 0.65, entity.posZ + 0.5); - double d0 = Minecraft.getMinecraft().getRenderManager().viewerPosX; - double d1 = Minecraft.getMinecraft().getRenderManager().viewerPosY; - double d2 = Minecraft.getMinecraft().getRenderManager().viewerPosZ; - boundingBox = boundingBox.offset(-d0, -d1, -d2); - if (FarmHelperConfig.pestsESP) { - Color color = FarmHelperConfig.pestsESPColor.toJavaColor(); - Vec3 entityPos = new Vec3(entity.posX, entity.posY + entity.getEyeHeight(), entity.posZ); - double distance = mc.thePlayer.getPositionEyes(1).distanceTo(entityPos); - boolean isInVacuumRange = distance < currentVacuumRange; - if (isInVacuumRange) { - color = new Color(color.getRed(), 255, color.getBlue(), Math.min(50, color.getAlpha())); - } - if (distance > 5) { - try { - EnumChatFormatting distanceColor = distance > currentVacuumRange ? EnumChatFormatting.RED : EnumChatFormatting.GREEN; - ItemStack itemStack = ((EntityArmorStand) entity).getEquipmentInSlot(4); - NBTTagCompound tagCompound = itemStack.getTagCompound(); - String texture = tagCompound.getCompoundTag("SkullOwner").getCompoundTag("Properties").getTagList("textures", 10).getCompoundTagAt(0) - .getString("Value"); - String pestName = this.pests.stream().filter(pest -> texture.equals(pest.getSecond())).findFirst().get().getFirst(); - RenderUtils.drawText(pestName + String.format(distanceColor + " %.1fm", distance), entity.posX, - entity.posY + entity.getEyeHeight() + 0.65 + 0.5, entity.posZ, (float) (1 + Math.min((distance / 20f), 2f))); - } catch (Exception ignored) { - } - } - RenderUtils.drawBox(boundingBox, color); - } - if (FarmHelperConfig.pestsTracers) { - RenderUtils.drawTracer(new Vec3(entity.posX, entity.posY + entity.getEyeHeight(), entity.posZ), - FarmHelperConfig.pestsTracersColor.toJavaColor()); - } - } - - private boolean canEntityBeSeenIgnoreNonCollidable(Entity entity) { - Vec3 vec3 = new Vec3(entity.posX, entity.posY + entity.getEyeHeight() + 0.5, entity.posZ); - Vec3 vec31 = new Vec3(mc.thePlayer.posX, mc.thePlayer.posY + mc.thePlayer.getEyeHeight(), mc.thePlayer.posZ); - MovingObjectPosition mop = mc.theWorld.rayTraceBlocks(vec31, vec3, false, true, false); - return mop == null || mop.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK && ( - mc.theWorld.getBlockState(mop.getBlockPos()).getBlock().equals(Blocks.cactus) || !BlockUtils.hasCollision(mop.getBlockPos())); - } - - @SubscribeEvent(receiveCanceled = true, priority = EventPriority.HIGHEST) - public void onEntityDeath(LivingDeathEvent event) { - if (mc.thePlayer == null || mc.theWorld == null) { - return; - } - if (!GameStateHandler.getInstance().inGarden()) { - return; - } + @SubscribeEvent(receiveCanceled = true, priority = EventPriority.HIGHEST) + public void onEntityDeath(LivingDeathEvent event) { + if (mc.thePlayer == null || mc.theWorld == null) { + return; + } + if (!GameStateHandler.getInstance().inGarden()) { + return; + } - Entity entity = event.entity; - LogUtils.sendDebug("[Pests Destroyer] Entity died: " + entity.getName() + "(" + entity.getEntityId() + ")" + " at: " + entity.getPosition()); - killedEntities.add(entity); - if (mc.thePlayer.getDistanceToEntity(entity) < 20) { - lastKillTimestamp = System.currentTimeMillis(); - previousCurrentPlotPestsCount = GameStateHandler.getInstance().getCurrentPlotPestsCount(); - state = States.CHECK_ANOTHER_PEST; - } - if (entity instanceof EntityArmorStand) { - Entity realEntity = PlayerUtils.getEntityCuttingOtherEntity(entity, (e) -> e instanceof EntityBat || e instanceof EntitySilverfish); - Entity nameEntity = PlayerUtils.getEntityCuttingOtherEntity(entity, (e) -> e instanceof EntityArmorStand && e != entity); - if (realEntity != null) { - LogUtils.sendDebug("[Pests Destroyer] Found real entity: " + realEntity.getName() + "(" + realEntity.getEntityId() + ")" + " at: " - + realEntity.getPosition()); - killedEntities.add(realEntity); - } - if (nameEntity != null) { - LogUtils.sendDebug("[Pests Destroyer] Found name entity: " + nameEntity.getName() + "(" + nameEntity.getEntityId() + ")" + " at: " - + nameEntity.getPosition()); - killedEntities.add(nameEntity); - } - } - if (entity instanceof EntityBat || entity instanceof EntitySilverfish) { - Entity armorStand = PlayerUtils.getEntityCuttingOtherEntity(entity, - (e) -> e instanceof EntityArmorStand && e.getName().contains("Armor Stand")); - Entity nameEntity = PlayerUtils.getEntityCuttingOtherEntity(entity, (e) -> e instanceof EntityArmorStand && e != armorStand); - if (armorStand != null) { - LogUtils.sendDebug("[Pests Destroyer] Found armor stand: " + armorStand.getName() + "(" + armorStand.getEntityId() + ")" + " at: " - + armorStand.getPosition()); - killedEntities.add(armorStand); - } - if (nameEntity != null) { - LogUtils.sendDebug("[Pests Destroyer] Found name entity: " + nameEntity.getName() + "(" + nameEntity.getEntityId() + ")" + " at: " - + nameEntity.getPosition()); - killedEntities.add(nameEntity); - } - } - if (isRunning()) { - FlyPathFinderExecutor.getInstance().stop(); - } - resetFireworkInfo(); - lastFireworkTime = 0; - currentEntityTarget.ifPresent(e -> { - if (!e.equals(event.entity)) { - return; - } - if (isRunning()) { - KeyBindUtils.stopMovement(); - } - currentEntityTarget = Optional.empty(); - stuckClock.reset(); - }); - PlotUtils.Plot plot = PlotUtils.getPlotNumberBasedOnLocation(entity.getPosition()); - if (plot == null) { - if (isRunning()) { - LogUtils.sendDebug("[Pests Destroyer] Failed to get plot for entity: " + entity.getName() + " at: " + entity.getPosition()); - } - return; - } - LogUtils.sendDebug("[Pests Destroyer] Removed 1 pest from plot number: " + plot.number); - killedPestsFrom.add(plot.number); - } - - private final List locations = new ArrayList<>(); - private Vec3 firstLocation = null; - private Vec3 lastLocation = null; - - @SubscribeEvent(receiveCanceled = true, priority = EventPriority.HIGHEST) - public void onFirework(SpawnParticleEvent event) { - if (mc.thePlayer == null || mc.theWorld == null) { - return; - } - if (!GameStateHandler.getInstance().inGarden()) { - return; - } - if (!enabled) { - return; - } - if (state != States.WAIT_FOR_LOCATION) { - return; + Entity entity = event.entity; + LogUtils.sendDebug("[Pests Destroyer] Entity died: " + entity.getName() + "(" + entity.getEntityId() + ")" + " at: " + entity.getPosition()); + killedEntities.add(entity); + if (mc.thePlayer.getDistanceToEntity(entity) < 20) { + lastKillTimestamp = System.currentTimeMillis(); + previousCurrentPlotPestsCount = GameStateHandler.getInstance().getCurrentPlotPestsCount(); + state = States.CHECK_ANOTHER_PEST; + } + if (entity instanceof EntityArmorStand) { + Entity realEntity = PlayerUtils.getEntityCuttingOtherEntity(entity, (e) -> e instanceof EntityBat || e instanceof EntitySilverfish); + Entity nameEntity = PlayerUtils.getEntityCuttingOtherEntity(entity, (e) -> e instanceof EntityArmorStand && e != entity); + if (realEntity != null) { + LogUtils.sendDebug("[Pests Destroyer] Found real entity: " + realEntity.getName() + "(" + realEntity.getEntityId() + ")" + " at: " + + realEntity.getPosition()); + killedEntities.add(realEntity); + } + if (nameEntity != null) { + LogUtils.sendDebug("[Pests Destroyer] Found name entity: " + nameEntity.getName() + "(" + nameEntity.getEntityId() + ")" + " at: " + + nameEntity.getPosition()); + killedEntities.add(nameEntity); + } + } + if (entity instanceof EntityBat || entity instanceof EntitySilverfish) { + Entity armorStand = PlayerUtils.getEntityCuttingOtherEntity(entity, + (e) -> e instanceof EntityArmorStand && e.getName().contains("Armor Stand")); + Entity nameEntity = PlayerUtils.getEntityCuttingOtherEntity(entity, (e) -> e instanceof EntityArmorStand && e != armorStand); + if (armorStand != null) { + LogUtils.sendDebug("[Pests Destroyer] Found armor stand: " + armorStand.getName() + "(" + armorStand.getEntityId() + ")" + " at: " + + armorStand.getPosition()); + killedEntities.add(armorStand); + } + if (nameEntity != null) { + LogUtils.sendDebug("[Pests Destroyer] Found name entity: " + nameEntity.getName() + "(" + nameEntity.getEntityId() + ")" + " at: " + + nameEntity.getPosition()); + killedEntities.add(nameEntity); + } + } + if (isRunning()) { + FlyPathFinderExecutor.getInstance().stop(); + } + resetFireworkInfo(); + lastFireworkTime = 0; + currentEntityTarget.ifPresent(e -> { + if (!e.equals(event.entity)) { + return; + } + if (isRunning()) { + KeyBindUtils.stopMovement(); + } + currentEntityTarget = Optional.empty(); + stuckClock.reset(); + }); + PlotUtils.Plot plot = PlotUtils.getPlotNumberBasedOnLocation(entity.getPosition()); + if (plot == null) { + if (isRunning()) { + LogUtils.sendDebug("[Pests Destroyer] Failed to get plot for entity: " + entity.getName() + " at: " + entity.getPosition()); + } + return; + } + LogUtils.sendDebug("[Pests Destroyer] Removed 1 pest from plot number: " + plot.number); + killedPestsFrom.add(plot.number); } - EnumParticleTypes type = event.getParticleTypes(); - if (type != EnumParticleTypes.VILLAGER_ANGRY) { - return; - } + private final List locations = new ArrayList<>(); + private Vec3 firstLocation = null; + private Vec3 lastLocation = null; - lastFireworkTime = System.currentTimeMillis(); - if (firstLocation == null) { - if (mc.thePlayer.getPositionVector().distanceTo(event.getPos()) > 5) { - return; - } - firstLocation = event.getPos(); - locations.add(firstLocation); - lastLocation = firstLocation; - return; - } - double dist = lastLocation.distanceTo(event.getPos()); - if (dist > 1.75) { - return; - } - locations.add(event.getPos()); - lastLocation = event.getPos(); - } + @SubscribeEvent(receiveCanceled = true, priority = EventPriority.HIGHEST) + public void onFirework(SpawnParticleEvent event) { + if (mc.thePlayer == null || mc.theWorld == null) { + return; + } + if (!GameStateHandler.getInstance().inGarden()) { + return; + } + if (!enabled) { + return; + } + if (state != States.WAIT_FOR_LOCATION) { + return; + } - private Vec3 calculateWaypoint() { - if (lastLocation == null) { - return null; - } - Vec3 direction = lastLocation.subtract(firstLocation).normalize(); - return lastLocation.addVector(direction.xCoord * 10, 0, direction.zCoord * 10); - } - - public void resetFireworkInfo() { - locations.clear(); - firstLocation = null; - lastLocation = null; - lastFireworkTime = 0; - } - - @SubscribeEvent - public void onSpawnObject(SpawnObjectEvent event) { - if (mc.thePlayer == null || mc.theWorld == null) { - return; - } - if (!GameStateHandler.getInstance().inGarden()) { - return; - } - if (event.type != 76) { - return; - } - if (!enabled) { - return; + EnumParticleTypes type = event.getParticleTypes(); + if (type != EnumParticleTypes.VILLAGER_ANGRY) { + return; + } + + lastFireworkTime = System.currentTimeMillis(); + if (firstLocation == null) { + if (mc.thePlayer.getPositionVector().distanceTo(event.getPos()) > 5) { + return; + } + firstLocation = event.getPos(); + locations.add(firstLocation); + lastLocation = firstLocation; + return; + } + double dist = lastLocation.distanceTo(event.getPos()); + if (dist > 1.75) { + return; + } + locations.add(event.getPos()); + lastLocation = event.getPos(); } - if (state != States.WAIT_FOR_LOCATION) { - return; + + private Vec3 calculateWaypoint() { + if (lastLocation == null) { + return null; + } + Vec3 direction = lastLocation.subtract(firstLocation).normalize(); + return lastLocation.addVector(direction.xCoord * 10, 0, direction.zCoord * 10); } - double distance = mc.thePlayer.getDistance(event.pos.xCoord, event.pos.yCoord, event.pos.zCoord); - if (distance < 3) { - int y = 130; - Block block = mc.theWorld.getBlockState(new BlockPos(event.pos.xCoord, y, event.pos.zCoord)).getBlock(); - while (y > 90 && block.equals(Blocks.air)) { - y--; - } - y += 3; - FlyPathFinderExecutor.getInstance().setDontRotate(true); - FlyPathFinderExecutor.getInstance().setSprinting(false); - FlyPathFinderExecutor.getInstance().findPath(new Vec3(event.pos.xCoord, y, event.pos.zCoord), true, true); - LogUtils.sendWarning( - "[Pests Destroyer] Firework is too close to player. Flying to x: " + event.pos.xCoord + " y: " + y + " z: " + event.pos.zCoord); - state = States.GET_LOCATION; + public void resetFireworkInfo() { + locations.clear(); + firstLocation = null; + lastLocation = null; + lastFireworkTime = 0; } - } - private boolean checkedThisGui = false; + @SubscribeEvent + public void onSpawnObject(SpawnObjectEvent event) { + if (mc.thePlayer == null || mc.theWorld == null) { + return; + } + if (!GameStateHandler.getInstance().inGarden()) { + return; + } + if (event.type != 76) { + return; + } + if (!enabled) { + return; + } + if (state != States.WAIT_FOR_LOCATION) { + return; + } - @SubscribeEvent - public void onGuiOpen(DrawScreenAfterEvent event) { - if (mc.thePlayer == null || mc.theWorld == null) { - return; - } - if (!GameStateHandler.getInstance().inGarden()) { - return; - } - if (checkedThisGui) { - return; - } - if (!(event.guiScreen instanceof GuiChest)) { - return; - } - String guiName = InventoryUtils.getInventoryName(); - if (guiName == null) { - return; - } - if (!delayClock.passed()) { - return; + double distance = mc.thePlayer.getDistance(event.pos.xCoord, event.pos.yCoord, event.pos.zCoord); + if (distance < 3) { + int y = 130; + Block block = mc.theWorld.getBlockState(new BlockPos(event.pos.xCoord, y, event.pos.zCoord)).getBlock(); + while (y > 90 && block.equals(Blocks.air)) { + y--; + } + y += 3; + FlyPathFinderExecutor.getInstance().setDontRotate(true); + FlyPathFinderExecutor.getInstance().setSprinting(false); + FlyPathFinderExecutor.getInstance().findPath(new Vec3(event.pos.xCoord, y, event.pos.zCoord), true, true); + LogUtils.sendWarning( + "[Pests Destroyer] Firework is too close to player. Flying to x: " + event.pos.xCoord + " y: " + y + " z: " + event.pos.zCoord); + state = States.GET_LOCATION; + } } - ContainerChest guiChest = (ContainerChest) ((GuiChest) event.guiScreen).inventorySlots; - if (!InventoryUtils.isInventoryLoaded()) { - return; - } + private boolean checkedThisGui = false; - int plotCounter = 0; - if (StringUtils.stripControlCodes(guiName).equals("Configure Plots")) { - for (int i = 0; i < guiChest.inventorySlots.size(); i++) { - Slot slot = guiChest.inventorySlots.get(i); - if (slot == null || !slot.getHasStack()) { - continue; - } - if (slot.getStack().getDisplayName().contains("Plot")) { - String displayName = StringUtils.stripControlCodes(slot.getStack().getDisplayName()); - try { - String plotName = displayName.replace("Plot - ", "").trim(); - int plotNumber = PlotUtils.getPLOT_NUMBERS().get(plotCounter); - PlotUtils.setPlot(plotNumber, plotName); - } catch (Exception e) { - LogUtils.sendError("[Pests Destroyer] Failed to parse plot number: " + displayName); - } - plotCounter++; - } else if (StringUtils.stripControlCodes(slot.getStack().getDisplayName()).equals("The Barn")) { - plotCounter++; - } - } - - } else { - return; - } - needToUpdatePlots = false; - checkedThisGui = true; - PlotUtils.savePlots(); - LogUtils.sendDebug("[Pests Destroyer] Updated plots"); - if (state == States.WAIT_FOR_INFO) { - PlayerUtils.closeScreen(); - if (FarmHelperConfig.dontTeleportToPlots) { - state = States.GET_CLOSEST_PLOT; - } else { - state = States.TELEPORT_TO_PLOT; - } - delayClock.schedule(300 + (long) (Math.random() * 250)); - } - } + @SubscribeEvent + public void onGuiOpen(DrawScreenAfterEvent event) { + if (mc.thePlayer == null || mc.theWorld == null) { + return; + } + if (!GameStateHandler.getInstance().inGarden()) { + return; + } + if (checkedThisGui) { + return; + } + if (!(event.guiScreen instanceof GuiChest)) { + return; + } + String guiName = InventoryUtils.getInventoryName(); + if (guiName == null) { + return; + } + if (!delayClock.passed()) { + return; + } + ContainerChest guiChest = (ContainerChest) ((GuiChest) event.guiScreen).inventorySlots; - private final Clock flyDelay = new Clock(); + if (!InventoryUtils.isInventoryLoaded()) { + return; + } - private void fly() { - if (mc.thePlayer.capabilities.isFlying) { - KeyBindUtils.holdThese(mc.gameSettings.keyBindJump); - return; - } - if (mc.thePlayer.motionY < -0.0784000015258789 || BlockUtils.getRelativeBlock(0, 0, 0).getMaterial().isLiquid()) { - if (flyDelay.passed()) { - if (!mc.thePlayer.capabilities.isFlying) { - mc.thePlayer.capabilities.isFlying = true; - mc.thePlayer.sendPlayerAbilities(); - } - flyDelay.reset(); - } else if (flyDelay.isScheduled()) { - return; - } - } - if (mc.thePlayer.onGround) { - mc.thePlayer.jump(); - flyDelay.schedule(80 + (long) (Math.random() * 80)); - } else if (!mc.thePlayer.capabilities.isFlying && !flyDelay.isScheduled()) { - flyDelay.schedule(80 + (long) (Math.random() * 80)); - } - } + int plotCounter = 0; + if (StringUtils.stripControlCodes(guiName).equals("Configure Plots")) { + for (int i = 0; i < guiChest.inventorySlots.size(); i++) { + Slot slot = guiChest.inventorySlots.get(i); + if (slot == null || !slot.getHasStack()) { + continue; + } + if (slot.getStack().getDisplayName().contains("Plot")) { + String displayName = StringUtils.stripControlCodes(slot.getStack().getDisplayName()); + try { + String plotName = displayName.replace("Plot - ", "").trim(); + int plotNumber = PlotUtils.getPLOT_NUMBERS().get(plotCounter); + PlotUtils.setPlot(plotNumber, plotName); + } catch (Exception e) { + LogUtils.sendError("[Pests Destroyer] Failed to parse plot number: " + displayName); + } + plotCounter++; + } else if (StringUtils.stripControlCodes(slot.getStack().getDisplayName()).equals("The Barn")) { + plotCounter++; + } + } - private PlotUtils.Plot getClosestPlot() { - List infestedPlots = GameStateHandler.getInstance().getInfestedPlots(); - if (infestedPlots.isEmpty()) { - LogUtils.sendError("[Pests Destroyer] Couldn't find infested plots on Tablist! Make sure you have it enabled in Tablist Widgets"); - return null; - } - if (GameStateHandler.getInstance().getCurrentPlotPestsCount() == 0) { - infestedPlots.removeIf(killedPestsFrom::contains); - } - PlotUtils.Plot closestPlot = null; - double closestDistance = Double.MAX_VALUE; - for (int plot : infestedPlots) { - double distance = mc.thePlayer.getDistanceSqToCenter(PlotUtils.getPlotCenter(plot)); - if (distance < closestDistance) { - closestDistance = distance; - closestPlot = PlotUtils.getPlotBasedOnNumber(plot); - } + } else { + return; + } + needToUpdatePlots = false; + checkedThisGui = true; + PlotUtils.savePlots(); + LogUtils.sendDebug("[Pests Destroyer] Updated plots"); + if (state == States.WAIT_FOR_INFO) { + PlayerUtils.closeScreen(); + if (FarmHelperConfig.dontTeleportToPlots) { + state = States.GET_CLOSEST_PLOT; + } else { + state = States.TELEPORT_TO_PLOT; + } + delayClock.schedule(300 + (long) (Math.random() * 250)); + } } - if (closestPlot == null) { - LogUtils.sendDebug("[Pests Destroyer] Failed to get closest plot"); - return null; + + private final Clock flyDelay = new Clock(); + + private void fly() { + if (mc.thePlayer.capabilities.isFlying) { + KeyBindUtils.holdThese(mc.gameSettings.keyBindJump); + return; + } + if (mc.thePlayer.motionY < -0.0784000015258789 || BlockUtils.getRelativeBlock(0, 0, 0).getMaterial().isLiquid()) { + if (flyDelay.passed()) { + if (!mc.thePlayer.capabilities.isFlying) { + mc.thePlayer.capabilities.isFlying = true; + mc.thePlayer.sendPlayerAbilities(); + } + flyDelay.reset(); + } else if (flyDelay.isScheduled()) { + return; + } + } + if (mc.thePlayer.onGround) { + mc.thePlayer.jump(); + flyDelay.schedule(80 + (long) (Math.random() * 80)); + } else if (!mc.thePlayer.capabilities.isFlying && !flyDelay.isScheduled()) { + flyDelay.schedule(80 + (long) (Math.random() * 80)); + } } - return closestPlot; - } - private boolean isNearPlotCenter() { - if (!closestPlot.isPresent()) { - return false; + private PlotUtils.Plot getClosestPlot() { + List infestedPlots = GameStateHandler.getInstance().getInfestedPlots(); + if (infestedPlots.isEmpty()) { + LogUtils.sendError("[Pests Destroyer] Couldn't find infested plots on Tablist! Make sure you have it enabled in Tablist Widgets"); + return null; + } + if (GameStateHandler.getInstance().getCurrentPlotPestsCount() == 0) { + infestedPlots.removeIf(killedPestsFrom::contains); + } + PlotUtils.Plot closestPlot = null; + double closestDistance = Double.MAX_VALUE; + for (int plot : infestedPlots) { + double distance = mc.thePlayer.getDistanceSqToCenter(PlotUtils.getPlotCenter(plot)); + if (distance < closestDistance) { + closestDistance = distance; + closestPlot = PlotUtils.getPlotBasedOnNumber(plot); + } + } + if (closestPlot == null) { + LogUtils.sendDebug("[Pests Destroyer] Failed to get closest plot"); + return null; + } + return closestPlot; + } + + private boolean isNearPlotCenter() { + if (!closestPlot.isPresent()) { + return false; + } + BlockPos plotCenter = PlotUtils.getPlotCenter(closestPlot.get().number); + double distance = mc.thePlayer.getDistance(plotCenter.getX(), mc.thePlayer.posY, plotCenter.getZ()); + return distance < 15; + } + + public enum States { + IDLE, + SWAP_ARMOR, + ARMOR_SWAP_VERIFY, + OPEN_DESK, + OPEN_PLOTS, + WAIT_FOR_INFO, + TELEPORT_TO_PLOT, + WAIT_FOR_TP, + CHECKING_PLOT, + CHECKING_SPAWN, + GET_CLOSEST_PLOT, + FLY_TO_THE_CLOSEST_PLOT, + GET_LOCATION, + WAIT_FOR_LOCATION, + FIND_PEST, + KILL_PEST, + CHECK_ANOTHER_PEST, + GO_BACK, + FINISH + } + + enum RotationState { + NONE, + CLOSE, + MEDIUM, + FAR + } + + public enum EscapeState { + NONE, + GO_TO_HUB, + GO_TO_GARDEN, + RESUME_MACRO } - BlockPos plotCenter = PlotUtils.getPlotCenter(closestPlot.get().number); - double distance = mc.thePlayer.getDistance(plotCenter.getX(), mc.thePlayer.posY, plotCenter.getZ()); - return distance < 15; - } - - public enum States { - IDLE, - SWAP_ARMOR, - ARMOR_SWAP_VERIFY, - OPEN_DESK, - OPEN_PLOTS, - WAIT_FOR_INFO, - TELEPORT_TO_PLOT, - WAIT_FOR_TP, - CHECKING_PLOT, - CHECKING_SPAWN, - GET_CLOSEST_PLOT, - FLY_TO_THE_CLOSEST_PLOT, - GET_LOCATION, - WAIT_FOR_LOCATION, - FIND_PEST, - KILL_PEST, - CHECK_ANOTHER_PEST, - GO_BACK, - FINISH - } - - enum RotationState { - NONE, - CLOSE, - MEDIUM, - FAR - } - - public enum EscapeState { - NONE, - GO_TO_HUB, - GO_TO_GARDEN, - RESUME_MACRO - } } From af45e2cafb80158ade90ad01f0609efeb880ebff Mon Sep 17 00:00:00 2001 From: Osama Date: Mon, 24 Feb 2025 18:51:00 +0600 Subject: [PATCH 06/10] A --- gradle.properties | 2 +- .../command/FarmHelperMainCommand.java | 29 +- .../farmhelperv2/config/FarmHelperConfig.java | 96 +++- .../farmhelperv2/feature/FeatureManager.java | 7 +- .../feature/impl/AutoSprayonator.java | 7 +- .../feature/impl/AutoWardrobe.java | 80 +++- .../farmhelperv2/feature/impl/PestFarmer.java | 441 ++++++++++++++++-- .../feature/impl/PestsDestroyer.java | 55 ++- .../feature/impl/VisitorsMacro.java | 5 +- .../farmhelperv2/handler/MacroHandler.java | 1 + .../farmhelperv2/macro/AbstractMacro.java | 6 +- .../pathfinder/FlyPathFinderExecutor.java | 29 +- .../jelly/farmhelperv2/util/PlayerUtils.java | 5 + 13 files changed, 688 insertions(+), 75 deletions(-) diff --git a/gradle.properties b/gradle.properties index 7af6b265..68e46029 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,5 +4,5 @@ baseGroup=com.jelly.farmhelperv2 mcVersion=1.8.9 modid=farmhelperv2 modName=FarmHelper -version=2.9.0 +version=2.9.9 shouldRelease=true diff --git a/src/main/java/com/jelly/farmhelperv2/command/FarmHelperMainCommand.java b/src/main/java/com/jelly/farmhelperv2/command/FarmHelperMainCommand.java index 9c1bc20f..74f39556 100644 --- a/src/main/java/com/jelly/farmhelperv2/command/FarmHelperMainCommand.java +++ b/src/main/java/com/jelly/farmhelperv2/command/FarmHelperMainCommand.java @@ -16,6 +16,8 @@ import net.minecraft.util.Vec3; import java.util.Optional; +import java.util.Arrays; +import java.lang.Float; @Command(value = "fh", aliases = {"farmhelper"}, description = "FarmHelper main command") public class FarmHelperMainCommand { @@ -59,6 +61,21 @@ public void pathfind(int x, int y, int z, FlyPathFinderExecutor.getInstance().findPath(new Vec3(x, y, z), follow, smooth); } + @SubCommand(aliases = {"pf"}) + public void pathfind(String x, String y, String z, String threshold, + @Description(value = "Tell the pathfinder, to constantly follow and recalibrate path until arrive", autoCompletesTo = {"true", "false"}) boolean follow, + @Description(value = "Tell the pathfinder, to smooth out the path", autoCompletesTo = {"true", "false"}) boolean smooth, + @Description(value = "Tell to pathfinder, to sprint while flying") boolean sprint) { + try { + FlyPathFinderExecutor.getInstance().setStoppingPositionThreshold(Float.valueOf(threshold)); + FlyPathFinderExecutor.getInstance().setSprinting(sprint); + FlyPathFinderExecutor.getInstance().findPath(new Vec3(Float.valueOf(x), Float.valueOf(y), Float.valueOf(z)), follow, smooth); + } catch (Exception e) { + LogUtils.sendError("Could not. KYS"); + e.printStackTrace(); + } + } + @SubCommand(aliases = {"sp"}) public void stoppath() { FlyPathFinderExecutor.getInstance().stop(); @@ -69,4 +86,14 @@ public void update() { PlayerUtils.closeScreen(); FarmHelperConfig.checkForUpdate(); } -} \ No newline at end of file + + @SubCommand(aliases = {"stp"}) + public void swapToPest() { + AutoWardrobe.instance.swapTo(FarmHelperConfig.pestFarmingSet0Slot, Arrays.asList(FarmHelperConfig.pestFarmingEq0.split("\\|"))); + } + + @SubCommand(aliases = {"stf"}) + public void swapToFarm() { + AutoWardrobe.instance.swapTo(FarmHelperConfig.pestFarmingSet1Slot, Arrays.asList(FarmHelperConfig.pestFarmingEq1.split("\\|"))); + } +} diff --git a/src/main/java/com/jelly/farmhelperv2/config/FarmHelperConfig.java b/src/main/java/com/jelly/farmhelperv2/config/FarmHelperConfig.java index 04743128..fb10e0d3 100644 --- a/src/main/java/com/jelly/farmhelperv2/config/FarmHelperConfig.java +++ b/src/main/java/com/jelly/farmhelperv2/config/FarmHelperConfig.java @@ -212,6 +212,27 @@ public class FarmHelperConfig extends Config { ) public static int spawnPosZ = 0; + @Number( + name = "Yaw", category = GENERAL, subcategory = "Spawn Position", + description = "The Yaw of the spawn", + min = -180.0f, max = 180.0f + ) + public static float spawnYaw = 0; + + @Number( + name = "Pitch", category = GENERAL, subcategory = "Spawn Position", + description = "The Pitch of the spawn", + min = -90.0f, max = 90.0f + ) + public static float spawnPitch = 0; + + @Number( + name = "Spawn Plot", category = GENERAL, subcategory = "Spawn Position", + description = "The Plot that the spawn is in", + min = 0, max = 24 + ) + public static int spawnPlot = 0; + @Button( name = "Set SpawnPos", category = GENERAL, subcategory = "Spawn Position", description = "Sets the spawn position to your current position", @@ -268,6 +289,12 @@ public class FarmHelperConfig extends Config { description = "Cancels failsafe and continues macroing", size = 2 ) public static OneKeyBind cancelFailsafeKeybind = new OneKeyBind(Keyboard.KEY_NONE); + + @KeyBind( + name = "Tp To Infested Plot", category = MISCELLANEOUS, subcategory = "Keybinds", + description = "Teleport to a plot with pest for skyhanni haters :D", size = 2 + ) + public static OneKeyBind tpToInfestedPlot = new OneKeyBind(Keyboard.KEY_NONE); // // @@ -1231,7 +1258,7 @@ public class FarmHelperConfig extends Config { @Switch( name = "Pause the Pests Destroyer during Jacob's contests", category = PESTS_DESTROYER, subcategory = "Pests Destroyer", description = "Pauses the Pests Destroyer during Jacob's contests", - size = 2 + size = 1 ) public static boolean pausePestsDestroyerDuringJacobsContest = true; @@ -1323,6 +1350,20 @@ public static void triggerManuallyPestsDestroyer() { min = 1, max = 18 ) public static int pestArmorSlot1 = 1; + + @Switch( + name = "Swap Equipments", category = PESTS_DESTROYER, subcategory = "Armor Swapper", + description = "Swap Equipments or not" + ) + public static boolean pestSwapEquipments = false; + + @Text( + name = "Pest Swap Equipments", category = PESTS_DESTROYER, subcategory = "Armor Swapper", size=2, + description = "Separate Equipment Names With |", placeholder = "Pesthunter's Necklace|Pesthunter's Cloak|Pesthunter's Belt" + ) + public static String pestSwapEq = ""; + + // // @@ -1394,12 +1435,6 @@ public static void triggerManuallyPestsDestroyer() { ) public static boolean pestFarming = false; - @Switch( - name = "Hold Daedalus Axe", category = PEST_FARMER, - description = "Farms with daedalus axe while waiting for pests to spawn" - ) - public static boolean pestFarmingHoldDaedalus = false; - @Slider( name = "Farming Armor Slot", category = PEST_FARMER, min = 1, max = 18 @@ -1419,6 +1454,40 @@ public static void triggerManuallyPestsDestroyer() { ) public static int pestFarmingWaitTime = 255; + @Switch( + name = "Swap Equipments", category = PEST_FARMER + ) + public static boolean pestFarmingSwapEq = false; + + @Text( + name = "Farming Fortune Equipments", category = PEST_FARMER, size=2, + description = "Separate Equipment Names With |", placeholder = "Lotus Necklace|Lotus Cloak|Lotus Belt" + ) + public static String pestFarmingEq0 = ""; + + @Text( + name = "Pest Chance Equipments", category = PEST_FARMER, size=2, + description = "Separate Equipment Names With |", placeholder = "Pesthunter's Necklace|Pesthunter's Cloak|Pesthunter's Belt" + ) + public static String pestFarmingEq1 = ""; + + @Slider( + name = "Equipment Click Delay", category = PEST_FARMER, + min = 50, max = 2000, step = 10 + ) + public static int pestFarmerEquipmentClickDelay = 400; + + @Switch( + name = "Start Pests Destroyer During Farming", category = PEST_FARMER + ) + public static boolean pestFarmerKillPests = false; + + @Slider( + name = "Pest Count to Start Killing At", category = PEST_FARMER, + min = 1, max = 8 + ) + public static int pestFarmerStartKillAt = 1; + @Info( text = "It's supposed to swap armor before pest spawns, swap back after pest spawns and kill with Pest Destryoer/the other one.", type = InfoType.INFO, category = PEST_FARMER, size = 2 @@ -2361,7 +2430,13 @@ public FarmHelperConfig() { this.addDependency("rotationTimeRandomnessDuringJacob", "customRotationDelaysDuringJacob"); this.addDependency("pestArmorSlot0", "pestSwapArmorBefore"); - this.addDependency("pestArmorSlot1", "pestSwapArmorAfter"); + this.addDependency("pestArmorSlot0", "pestSwapArmorBefore"); + this.addDependency("pestFarmingEq0", "pestFarmingSwapEq"); + this.addDependency("pestFarmingEq1", "pestFarmingSwapEq"); + this.addDependency("pestFarmerEquipmentClickDelay", "pestFarmingSwapEq"); + this.addDependency("pestFarmerStartKillAt", "pestFarmerKillPests"); + + this.addDependency("pestSwapEq", "pestSwapEquipments"); this.addDependency("leaveTime", "leaveTimer"); @@ -2386,6 +2461,11 @@ public FarmHelperConfig() { LogUtils.sendWarning("[Failsafe] Emergency has been cancelled!"); } }); + registerKeyBind(tpToInfestedPlot, () -> { + List infestedPlots = GameStateHandler.getInstance().getInfestedPlots(); + if (infestedPlots.isEmpty()) return; + mc.thePlayer.sendChatMessage("/plottp " + infestedPlots.get(0)); + }); // registerKeyBind(debugKeybind2, () -> { // MovingObjectPosition objectMouseOver = Minecraft.getMinecraft().objectMouseOver; // if (objectMouseOver != null && objectMouseOver.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK) { diff --git a/src/main/java/com/jelly/farmhelperv2/feature/FeatureManager.java b/src/main/java/com/jelly/farmhelperv2/feature/FeatureManager.java index e571d82c..5ffa1dd3 100644 --- a/src/main/java/com/jelly/farmhelperv2/feature/FeatureManager.java +++ b/src/main/java/com/jelly/farmhelperv2/feature/FeatureManager.java @@ -103,8 +103,8 @@ public boolean shouldIgnoreFalseCheck() { if (AutoReconnect.getInstance().isRunning() && !AutoReconnect.getInstance().shouldCheckForFailsafes()) { return true; } - if (PestsDestroyer.getInstance().isRunning()) { - if (!PestsDestroyer.getInstance().shouldCheckForFailsafes()) return true; + if (PestsDestroyer.getInstance().isRunning() && !PestsDestroyer.getInstance().shouldCheckForFailsafes()) { + return true; } if (PlotCleaningHelper.getInstance().isRunning() && !PlotCleaningHelper.getInstance().shouldCheckForFailsafes()) { return true; @@ -115,6 +115,9 @@ public boolean shouldIgnoreFalseCheck() { if (AutoPestExchange.getInstance().isRunning() && !AutoPestExchange.getInstance().shouldCheckForFailsafes()) { return true; } + if (PestFarmer.instance.isRunning() && !PestFarmer.instance.shouldCheckForFailsafes()) { + return true; + } return false; } diff --git a/src/main/java/com/jelly/farmhelperv2/feature/impl/AutoSprayonator.java b/src/main/java/com/jelly/farmhelperv2/feature/impl/AutoSprayonator.java index b0287416..fd885bc7 100644 --- a/src/main/java/com/jelly/farmhelperv2/feature/impl/AutoSprayonator.java +++ b/src/main/java/com/jelly/farmhelperv2/feature/impl/AutoSprayonator.java @@ -140,10 +140,15 @@ public void onTablistUpdate(UpdateTablistEvent event) { return; } if (GameStateHandler.getInstance().getSprayonatorState() != BuffState.NOT_ACTIVE) { + if (this.timer.isScheduled()) this.timer.reset(); return; } - this.start(); + if (!this.timer.isScheduled()) { + this.timer.schedule(5000); + } else if (this.timer.passed()) { + this.start(); + } } @SubscribeEvent diff --git a/src/main/java/com/jelly/farmhelperv2/feature/impl/AutoWardrobe.java b/src/main/java/com/jelly/farmhelperv2/feature/impl/AutoWardrobe.java index cdcb7de1..47ad62c8 100644 --- a/src/main/java/com/jelly/farmhelperv2/feature/impl/AutoWardrobe.java +++ b/src/main/java/com/jelly/farmhelperv2/feature/impl/AutoWardrobe.java @@ -16,6 +16,9 @@ import net.minecraft.item.ItemStack; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent.Phase; +import java.util.List; +import java.util.ArrayList; public class AutoWardrobe implements IFeature { @@ -24,6 +27,9 @@ public class AutoWardrobe implements IFeature { private final Minecraft mc = Minecraft.getMinecraft(); private boolean enabled = false; private int swapTo = -1; + private int invStart = 54; + private int invEnd = 54; + private List equipmentsToSwapTo = new ArrayList<>(); private State state = State.STARTING; private Clock timer = new Clock(); @@ -49,7 +55,7 @@ public boolean shouldStartAtMacroStart() { @Override public void resetStatesAfterMacroDisabled() { - activeSlot = -1; + // activeSlot = -1; } @Override @@ -72,6 +78,16 @@ public void swapTo(int slot) { LogUtils.sendSuccess("[AutoWardrobe] Starting. Swapping to slot " + slot); } + public void swapTo(int slot, List equipments) { + if (slot< 1 || slot > 18) { + return; + } + swapTo = slot; + equipmentsToSwapTo = new ArrayList(equipments); + enabled = true; + LogUtils.sendSuccess("[AutoWardrobe] Starting. Swapping to slot " + slot + ", and equipments: " + equipments); + } + @Override public void stop() { if (!enabled) { @@ -79,6 +95,9 @@ public void stop() { } enabled = false; swapTo = -1; + invStart = 54; + invEnd = 54; + equipmentsToSwapTo.clear(); state = State.STARTING; timer.reset(); @@ -103,7 +122,7 @@ public boolean hasTimerEnded() { @SubscribeEvent public void onTick(ClientTickEvent event) { - if (!enabled) { + if (!enabled || mc.thePlayer == null || event.phase != Phase.START) { return; } @@ -126,7 +145,7 @@ public void onTick(ClientTickEvent event) { return; } - if (inventoryName().startsWith("Wardrobe")) { + if (inventoryName().startsWith("Wardrobe") && InventoryUtils.isInventoryLoaded()) { setState(State.NAVIGATING, FarmHelperConfig.getRandomGUIMacroDelay()); } break; @@ -168,20 +187,63 @@ public void onTick(ClientTickEvent event) { activeSlot = swapTo; setState(State.WAITING, FarmHelperConfig.getRandomGUIMacroDelay()); break; + // this is just here to give a bit extra pause before it stops case WAITING: if (isTimerRunning()) { return; } - PlayerUtils.closeScreen(); - setState(State.ENDING, FarmHelperConfig.getRandomGUIMacroDelay()); + if (equipmentsToSwapTo.isEmpty()) { + PlayerUtils.closeScreen(); + setState(State.ENDING, FarmHelperConfig.getRandomGUIMacroDelay()); + } else { + setState(State.OPENING_EQ, 0); + } + break; + case OPENING_EQ: + if (isTimerRunning()) { + return; + } + mc.thePlayer.sendChatMessage("/eq"); + setState(State.EQ_VERIFY, 2000); + break; + case EQ_VERIFY: + if (hasTimerEnded()) { + LogUtils.sendError("Could not open eq in under 2 seconds. Stopping"); + setState(State.WAITING, 0); + return; + } + + if (inventoryName().startsWith("Your Equipment") && InventoryUtils.isInventoryLoaded()) { + setState(State.SWAPPING_EQUIPMENT, FarmHelperConfig.getRandomGUIMacroDelay()); + invStart = 54; + invEnd = mc.thePlayer.openContainer.inventorySlots.size(); + } + break; + case SWAPPING_EQUIPMENT: + if (isTimerRunning()) { + return; + } + + for (; invStart < invEnd; invStart++) { + slot = mc.thePlayer.openContainer.getSlot(invStart); + if (slot.getHasStack()) { + ItemStack stack = slot.getStack(); + if (stack.hasDisplayName() && equipmentsToSwapTo.removeIf(it -> stack.getDisplayName().contains(it.trim()))) { + InventoryUtils.clickContainerSlot(invStart, ClickType.LEFT, ClickMode.PICKUP); + timer.schedule(FarmHelperConfig.pestFarmerEquipmentClickDelay); + return; + } + } + } + equipmentsToSwapTo.clear(); + setState(State.WAITING, FarmHelperConfig.getRandomGUIMacroDelay()); break; - // this is just here to give a bit extra pause before it stops case ENDING: if (isTimerRunning()) { return; } - stop(); - break; + stop(); + break; } } @@ -203,6 +265,6 @@ private String inventoryName() { enum State { - STARTING, OPENING_WD, WD_VERIFY, NAVIGATING, NAVIGATION_VERIFY, CLICKING_SLOT, WAITING, ENDING + STARTING, OPENING_WD, WD_VERIFY, NAVIGATING, NAVIGATION_VERIFY, CLICKING_SLOT, WAITING, OPENING_EQ, EQ_VERIFY, SWAPPING_EQUIPMENT, ENDING } } diff --git a/src/main/java/com/jelly/farmhelperv2/feature/impl/PestFarmer.java b/src/main/java/com/jelly/farmhelperv2/feature/impl/PestFarmer.java index 688a751d..d7c5864b 100644 --- a/src/main/java/com/jelly/farmhelperv2/feature/impl/PestFarmer.java +++ b/src/main/java/com/jelly/farmhelperv2/feature/impl/PestFarmer.java @@ -5,27 +5,49 @@ import com.jelly.farmhelperv2.failsafe.FailsafeManager; import com.jelly.farmhelperv2.feature.FeatureManager; import com.jelly.farmhelperv2.feature.IFeature; +import com.jelly.farmhelperv2.feature.impl.PestsDestroyer; import com.jelly.farmhelperv2.handler.GameStateHandler; import com.jelly.farmhelperv2.handler.MacroHandler; -import com.jelly.farmhelperv2.util.InventoryUtils; -import com.jelly.farmhelperv2.util.LogUtils; +import com.jelly.farmhelperv2.handler.RotationHandler; +import com.jelly.farmhelperv2.pathfinder.FlyPathFinderExecutor; +import com.jelly.farmhelperv2.util.*; +import com.jelly.farmhelperv2.util.helper.*; import java.util.ArrayList; import java.util.List; +import java.util.Arrays; +import java.util.Optional; +import net.minecraft.util.*; import net.minecraft.client.Minecraft; import net.minecraftforge.client.event.ClientChatReceivedEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent; import net.minecraftforge.fml.common.gameevent.TickEvent.Phase; +import net.minecraftforge.fml.common.eventhandler.EventPriority; + +import java.lang.Math; public class PestFarmer implements IFeature { public static PestFarmer instance = new PestFarmer(); + private final Minecraft mc = Minecraft.getMinecraft(); private boolean enabled = false; private long pestSpawnTime = 0L; private int swapTo = -1; + private List equipments = new ArrayList(); + private MainState mainState = MainState.NONE; private State state = State.SWAPPING; + private ReturnState returnState = ReturnState.STARTING; private boolean pestSpawned = false; - private boolean holdDae = false; + private boolean kill = false; + public boolean wasSpawnChanged = false; + private Clock timer = new Clock(); + + // return + private boolean isRewarpObstructed = false; + private Optional preTpBlockPos = Optional.empty(); + private int flyAttempts = 0; + private int mainAttempts = 0; // this isnt needed, like at all, but im adding this because fuck you thats why + private boolean failed = false; @Override public String getName() { @@ -50,9 +72,11 @@ public boolean shouldStartAtMacroStart() { @Override public void resetStatesAfterMacroDisabled() { state = State.SWAPPING; - pestSpawned = false; - holdDae = false; + mainState = MainState.NONE; + returnState = ReturnState.STARTING; swapTo = -1; + equipments.clear(); + enabled = false; } @Override @@ -62,7 +86,7 @@ public boolean isToggled() { @Override public boolean shouldCheckForFailsafes() { - return false; + return (mainState != MainState.RETURN || returnState.ordinal() > 7) && (state != State.WAITING_FOR_WARP); } @Override @@ -72,6 +96,7 @@ public void start() { } MacroHandler.getInstance().pauseMacro(); enabled = true; + IFeature.super.start(); } @Override @@ -81,24 +106,34 @@ public void stop() { } enabled = false; + kill = false; + equipments = new ArrayList<>(); + mainState = MainState.NONE; state = State.SWAPPING; - if (MacroHandler.getInstance().isMacroToggled()) { + returnState = ReturnState.STARTING; + preTpBlockPos = Optional.empty(); + flyAttempts = 0; + mainAttempts = 0; + if (failed) { + MacroHandler.getInstance().disableMacro(); + LogUtils.sendError("Failed, disabling"); + } + if (!failed && MacroHandler.getInstance().isMacroToggled()) { MacroHandler.getInstance().resumeMacro(); } + failed = false; + IFeature.super.stop(); } - public boolean holdDaedalus() { - return holdDae && FarmHelperConfig.pestFarming && FarmHelperConfig.pestFarmingHoldDaedalus - && AutoWardrobe.activeSlot == FarmHelperConfig.pestFarmingSet1Slot && InventoryUtils.holdItem("Daedalus Axe"); - } - - @SubscribeEvent + @SubscribeEvent(priority = EventPriority.HIGHEST) public void onTick(ClientTickEvent event) { if (event.phase != Phase.START) { return; } - if (!this.isToggled() || !MacroHandler.getInstance().isCurrentMacroEnabled() - || MacroHandler.getInstance().getCurrentMacro().get().currentState.ordinal() < 4 || enabled) { + if (!this.isToggled() || !MacroHandler.getInstance().isCurrentMacroEnabled() || MacroHandler.getInstance().getCurrentMacro().get().currentState.ordinal() < 4 || enabled) { + return; + } + if (mc.currentScreen != null) { return; } if (!GameStateHandler.getInstance().inGarden()) { @@ -117,34 +152,70 @@ public void onTick(ClientTickEvent event) { return; } + if (wasSpawnChanged && FarmHelperConfig.pestFarmerKillPests && PlayerUtils.isStandingOnRewarpLocation()) { + mainState = MainState.RETURN; + start(); + return; + } + if (pestSpawned) { long timeDiff = System.currentTimeMillis() - pestSpawnTime; - if (timeDiff >= FarmHelperConfig.pestFarmingWaitTime * 1000L && AutoWardrobe.activeSlot != FarmHelperConfig.pestFarmingSet1Slot) { - LogUtils.sendDebug("Swapping to " + FarmHelperConfig.pestFarmingSet1Slot); - swapTo = FarmHelperConfig.pestFarmingSet1Slot; + if (timeDiff >= FarmHelperConfig.pestFarmingWaitTime * 1000L) { pestSpawned = false; - holdDae = true; - start(); + if (AutoWardrobe.activeSlot != FarmHelperConfig.pestFarmingSet1Slot) { + LogUtils.sendDebug("Swapping to " + FarmHelperConfig.pestFarmingSet1Slot); + swapTo = FarmHelperConfig.pestFarmingSet1Slot; + if (FarmHelperConfig.pestFarmingSwapEq) { + equipments = Arrays.asList(FarmHelperConfig.pestFarmingEq1.split("\\|")); + } + mainState = MainState.SWAP_N_START; + start(); + } } else if (AutoWardrobe.activeSlot != FarmHelperConfig.pestFarmingSet0Slot) { LogUtils.sendDebug("Swapping to " + FarmHelperConfig.pestFarmingSet0Slot); swapTo = FarmHelperConfig.pestFarmingSet0Slot; - holdDae = false; + if (FarmHelperConfig.pestFarmingSwapEq) { + equipments = Arrays.asList(FarmHelperConfig.pestFarmingEq0.split("\\|")); + } + mainState = MainState.SWAP_N_START; start(); } } } - @SubscribeEvent + @SubscribeEvent(priority = EventPriority.HIGHEST) public void onChat(ClientChatReceivedEvent event) { if (event.type != 0) { return; } String message = event.message.getUnformattedText(); - if (message.startsWith("§6§lYUCK!") || message.startsWith("§6§lEWW!") || message.startsWith("§6§lGROSS!")) { + if (message.contains("§6§lYUCK!") || message.startsWith("§6§lEWW!") || message.startsWith("§6§lGROSS!")) { pestSpawnTime = System.currentTimeMillis(); pestSpawned = true; LogUtils.sendDebug("[PestFarmer] Pest Spawned."); } + + if (!enabled || (state != State.WAITING_FOR_SPAWN && returnState != ReturnState.WAITING_FOR_SPAWN && returnState != ReturnState.WAITING_FOR_SPAWN_2)) return; + if (message.contains("Your spawn location has been set!")) { + event.setCanceled(true); + mc.thePlayer.addChatMessage(event.message); + if (mainState == MainState.SWAP_N_START) { + setState(State.TOGGLING_PEST_DESTROYER, 0); + } else { + if (returnState.ordinal() == 1) setState(ReturnState.TP_TO_SPAWN_PLOT, 0); + else { + setState(ReturnState.ENDING, 0); + wasSpawnChanged = false; + } + } + wasSpawnChanged = true; + return; + } + + if (message.contains("You cannot set your spawn here!")) { + LogUtils.sendError("Could not set spawn, returning to farming"); + stop(); + } } @SubscribeEvent @@ -153,23 +224,327 @@ public void onTickSwap(ClientTickEvent event) { return; } - switch (state) { - case SWAPPING: - AutoWardrobe.instance.swapTo(swapTo); - state = State.ENDING; - break; - case ENDING: - if (AutoWardrobe.instance.isRunning()) { - return; + if (event.phase != Phase.START) { + return; + } + + switch (mainState) { + case NONE: + stop(); + break; + case SWAP_N_START: { + switch (state) { + case SWAPPING: + AutoWardrobe.instance.swapTo(swapTo, equipments); + setState(State.WAITING_FOR_SWAP, 0); + break; + case WAITING_FOR_SWAP: + if (AutoWardrobe.instance.isRunning()) { + return; + } + if (pestSpawned && FarmHelperConfig.pestFarmerKillPests && GameStateHandler.getInstance().getPestsCount() >= FarmHelperConfig.pestFarmerStartKillAt) { + setState(State.SETTING_SPAWN, 0); + } else { + stop(); + } + break; + case SETTING_SPAWN: + mc.thePlayer.sendChatMessage("/setspawn"); + setState(State.WAITING_FOR_SPAWN, 5000); + break; + case WAITING_FOR_SPAWN: + if (hasTimerEnded()) { + LogUtils.sendError("Could not verify spawn change under 5 seconds, disabling"); + stop(); + } + break; + case TOGGLING_PEST_DESTROYER: + if (PestsDestroyer.getInstance().canEnableMacro(true)) { + PestsDestroyer.getInstance().start(); + setState(State.WAITING_FOR_PEST_DESTROYER, 0); + break; + } + LogUtils.sendError("Cannot enable PestsDestroyer"); + stop(); + break; + case WAITING_FOR_PEST_DESTROYER: + if (PestsDestroyer.getInstance().isRunning()) { + break; + } + mc.thePlayer.sendChatMessage("/warp garden"); + setState(State.WAITING_FOR_WARP, 5000); + preTpBlockPos = Optional.of(mc.thePlayer.getPosition()); + break; + case WAITING_FOR_WARP: + if (hasTimerEnded() || !preTpBlockPos.isPresent()) { + LogUtils.sendError("Could not tp/pretpblockpos isnt present. pretpblockpos: " + preTpBlockPos.isPresent()); + setState(State.ENDING, 0); + failed = true; + break; + } + + if (preTpBlockPos.get().equals(mc.thePlayer.getPosition())) { + break; + } + + setState(State.ENDING, 0); + break; + case ENDING: + stop(); + break; + } + break; + } + + case RETURN: { + switch (returnState) { + case STARTING: + if (BlockUtils.canFlyHigher(10)) { + mc.thePlayer.sendChatMessage("/setspawn"); + setState(ReturnState.WAITING_FOR_SPAWN, 5000); + return; + } else { + isRewarpObstructed = true; + } + + setState(ReturnState.TP_TO_SPAWN_PLOT, 250); + break; + case WAITING_FOR_SPAWN: + if (hasTimerEnded()) { + LogUtils.sendError("Could not verify spawn change under 5 seconds. Continuing"); + isRewarpObstructed = true; + setState(ReturnState.TP_TO_SPAWN_PLOT, 0); + } + break; + case TP_TO_SPAWN_PLOT: + if (isTimerRunning()) return; + + if (!mc.thePlayer.capabilities.isFlying) { + PestsDestroyer.getInstance().fly(); + return; + } + + mc.thePlayer.sendChatMessage("/plottp " + FarmHelperConfig.spawnPlot); + setState(ReturnState.TP_VERIFY, 5000); + preTpBlockPos = Optional.of(mc.thePlayer.getPosition()); + break; + case TP_VERIFY: + if (hasTimerEnded() || !preTpBlockPos.isPresent()) { + LogUtils.sendError("Could not tp/pretpblockpos isnt present. pretpblockpos: " + preTpBlockPos.isPresent()); + setState(ReturnState.ENDING, 0); + failed = true; + break; + } + + if (preTpBlockPos.get().equals(mc.thePlayer.getPosition())) { + break; + } + + setState(ReturnState.VERIFY_PLOT, 0); + break; + case VERIFY_PLOT: + boolean isSuffocating = PlayerUtils.isPlayerSuffocating(); + if (isTimerRunning() && isSuffocating) return; + + if (isSuffocating) { + if (!timer.isScheduled()) { + KeyBindUtils.setKeyBindState(mc.gameSettings.keyBindJump, true); + timer.schedule(5000); + } else { + setState(ReturnState.ESCAPE_TP, 0); + } + break; + } + + KeyBindUtils.stopMovement(); + setState(ReturnState.FLY_TO_ABOVE_SPAWN, 0); + break; + case ESCAPE_TP: + mc.thePlayer.sendChatMessage("/plottp barn"); + preTpBlockPos = Optional.of(mc.thePlayer.getPosition()); + setState(ReturnState.ESCAPE_TP_VERIFY, 5000); + break; + case ESCAPE_TP_VERIFY: + if (hasTimerEnded() || !preTpBlockPos.isPresent()) { + LogUtils.sendError("Could not tp/pretpblockpos isnt present. pretpblockpos: " + preTpBlockPos.isPresent()); + setState(ReturnState.ENDING, 0); + failed = true; + break; + } + + if (preTpBlockPos.get().equals(mc.thePlayer.getPosition())) { + break; + } + + setState(ReturnState.FLY_TO_ABOVE_SPAWN, 0); + break; + case FLY_TO_ABOVE_SPAWN: + if (FlyPathFinderExecutor.getInstance().isRunning()) { + FlyPathFinderExecutor.getInstance().stop(); + break; + } + + if (flyAttempts > 3 || mainAttempts > 3) { + LogUtils.sendError("Tried " + (flyAttempts + mainAttempts * 3) + " times but failed"); + setState(ReturnState.ENDING, 0); + failed = true; + break; + } + + flyAttempts++; + FlyPathFinderExecutor.getInstance().setStoppingPositionThreshold(0.5f); + FlyPathFinderExecutor.getInstance().findPath(new Vec3(FarmHelperConfig.spawnPosX + 0.5f, 85, FarmHelperConfig.spawnPosZ + 0.5f), true, true); + setState(ReturnState.WAITING_FOR_FLIGHT, 0); + break; + case WAITING_FOR_FLIGHT: + if (FlyPathFinderExecutor.getInstance().isRunning()) break; + + if (FlyPathFinderExecutor.getInstance().getState().ordinal() != 2 && Math.abs(Math.floor(mc.thePlayer.posX) - FarmHelperConfig.spawnPosX) < 1 && Math.abs(Math.floor(mc.thePlayer.posZ) - FarmHelperConfig.spawnPosZ) < 1) { + setState(ReturnState.FLY_TO_SPAWN_BLOCK, 0); + flyAttempts = 0; + } else { + setState(ReturnState.FLY_TO_ABOVE_SPAWN, 0); + } + break; + case FLY_TO_SPAWN_BLOCK: + if (FlyPathFinderExecutor.getInstance().isRunning()) { + FlyPathFinderExecutor.getInstance().stop(); + break; + } + + if (flyAttempts > 3 || mainAttempts > 3) { + LogUtils.sendError("Tried " + (flyAttempts + 1 + mainAttempts * 3) + " times but failed"); + setState(ReturnState.ENDING, 0); + failed = true; + break; + } + + flyAttempts++; + FlyPathFinderExecutor.getInstance().setStoppingPositionThreshold(0.2f); + FlyPathFinderExecutor.getInstance().findPath(new Vec3(FarmHelperConfig.spawnPosX + 0.5f, FarmHelperConfig.spawnPosY + 0.15, FarmHelperConfig.spawnPosZ + 0.5f), true, true); + setState(ReturnState.WAITING_FOR_FLIGHT_AND_VERIFYING, 0); + break; + case WAITING_FOR_FLIGHT_AND_VERIFYING: + if (FlyPathFinderExecutor.getInstance().isRunning()) break; + + if (FlyPathFinderExecutor.getInstance().getState().ordinal() == 2) { + LogUtils.sendError("Failed to pathfind to spawn. Stoping"); + FlyPathFinderExecutor.getInstance().stop(); + setState(ReturnState.ENDING, 0); + failed = true; + break; + } + + BlockPos pos = BlockUtils.getRelativeBlockPos(0, 0, 0); + if (pos.getX() == FarmHelperConfig.spawnPosX && pos.getY() == FarmHelperConfig.spawnPosY && pos.getZ() == FarmHelperConfig.spawnPosZ) { + setState(ReturnState.SNEAKING_AND_ROTATING, 0); + flyAttempts = 0; + } else { + setState(ReturnState.FLY_TO_ABOVE_SPAWN, 0); + mainAttempts++; + } + break; + case SNEAKING_AND_ROTATING: + if (mc.thePlayer.capabilities.isFlying) KeyBindUtils.setKeyBindState(mc.gameSettings.keyBindSneak, true); + + RotationHandler.getInstance().easeTo(new RotationConfiguration( + new Rotation(AngleUtils.get360RotationYaw(FarmHelperConfig.spawnYaw), FarmHelperConfig.spawnPitch), + 500, + null + )); + setState(ReturnState.SETTING_SPAWN, 5000); + break; + case SETTING_SPAWN: + if (hasTimerEnded()) { + LogUtils.sendError("Failed to rotate and shift"); + setState(ReturnState.ENDING, 0); + failed = true; + break; + } + + if (RotationHandler.getInstance().isRotating() || !mc.thePlayer.onGround) break; + mc.thePlayer.sendChatMessage("/setspawn"); + setState(ReturnState.WAITING_FOR_SPAWN_2, 5000); + break; + case WAITING_FOR_SPAWN_2: + if (hasTimerEnded()) { + LogUtils.sendError("Failed to set spawn 2"); + setState(ReturnState.ENDING, 0); + failed = true; + break; + } + break; + case ENDING: + KeyBindUtils.stopMovement(); + stop(); + break; + } - stop(); - break; + break; + } } } + public boolean isTimerRunning() { + return timer.isScheduled() && !timer.passed(); + } + + public boolean hasTimerEnded() { + return timer.isScheduled() && timer.passed(); + } + + public void setState(State state, long time) { + this.state = state; + if (time == 0) { + timer.reset(); + return; + } + timer.schedule(time); + } + + public void setState(ReturnState state, long time) { + this.returnState = state; + if (time == 0) { + timer.reset(); + return; + } + timer.schedule(time); + } + + enum MainState { + NONE, + SWAP_N_START, + RETURN + } + // bleh, its only for the tracker basically enum State { SWAPPING, + WAITING_FOR_SWAP, + ANALYZING, // :nerd: + SETTING_SPAWN, + WAITING_FOR_SPAWN, + TOGGLING_PEST_DESTROYER, + WAITING_FOR_PEST_DESTROYER, + WAITING_FOR_WARP, + ENDING + } + + enum ReturnState { + STARTING, + WAITING_FOR_SPAWN, + TP_TO_SPAWN_PLOT, + TP_VERIFY, + VERIFY_PLOT, + ESCAPE_TP, + ESCAPE_TP_VERIFY, + FLY_TO_ABOVE_SPAWN, + WAITING_FOR_FLIGHT, + FLY_TO_SPAWN_BLOCK, + WAITING_FOR_FLIGHT_AND_VERIFYING, + SNEAKING_AND_ROTATING, + SETTING_SPAWN, + WAITING_FOR_SPAWN_2, // definitely could've improved but you dont see me care now do you ENDING } } diff --git a/src/main/java/com/jelly/farmhelperv2/feature/impl/PestsDestroyer.java b/src/main/java/com/jelly/farmhelperv2/feature/impl/PestsDestroyer.java index 24b4030e..3de7c56e 100644 --- a/src/main/java/com/jelly/farmhelperv2/feature/impl/PestsDestroyer.java +++ b/src/main/java/com/jelly/farmhelperv2/feature/impl/PestsDestroyer.java @@ -83,6 +83,7 @@ public class PestsDestroyer implements IFeature { private final Clock delayClock = new Clock(); private final Clock delayBetweenBackTaps = new Clock(); private final Clock delayBetweenFireworks = new Clock(); + private final Clock suffocateEscapeTimer = new Clock(); @Getter private Optional currentEntityTarget = Optional.empty(); private boolean enabled = false; @@ -199,6 +200,7 @@ public void stop() { delayBetweenFireworks.reset(); delayClock.reset(); stuckClock.reset(); + suffocateEscapeTimer.reset(); preparing = false; enabled = false; isPlotObstructed = false; @@ -477,6 +479,10 @@ public void onTickExecute(TickEvent.ClientTickEvent event) { switch (state) { case IDLE: + if (!mc.thePlayer.capabilities.isFlying) { + fly(); + break; + } ItemStack currentItem = mc.thePlayer.getHeldItem(); if (GameStateHandler.getInstance().getPestsCount() == 0) { if (isInventoryOpen()) { @@ -491,6 +497,7 @@ public void onTickExecute(TickEvent.ClientTickEvent event) { } state = States.SWAP_ARMOR; delayClock.schedule((long) (200 + Math.random() * 200)); + LogUtils.sendDebug("Delay 2"); break; case SWAP_ARMOR: if (FarmHelperConfig.pestSwapArmorBefore) { @@ -499,7 +506,7 @@ public void onTickExecute(TickEvent.ClientTickEvent event) { currentSlot = FarmHelperConfig.pestArmorSlot1; } if (AutoWardrobe.activeSlot != currentSlot) { - AutoWardrobe.instance.swapTo(currentSlot); + AutoWardrobe.instance.swapTo(currentSlot, FarmHelperConfig.pestSwapEquipments ? Arrays.asList(FarmHelperConfig.pestSwapEq.split("\\|")) : Collections.emptyList()); } } state = States.ARMOR_SWAP_VERIFY; @@ -529,11 +536,13 @@ public void onTickExecute(TickEvent.ClientTickEvent event) { mc.thePlayer.sendChatMessage("/desk"); state = States.OPEN_PLOTS; delayClock.schedule((long) (FarmHelperConfig.pestAdditionalGUIDelay + 500 + Math.random() * 500)); + LogUtils.sendDebug("Delay 3"); break; case OPEN_PLOTS: String chestName = InventoryUtils.getInventoryName(); if (mc.currentScreen == null) { delayClock.schedule((long) (FarmHelperConfig.pestAdditionalGUIDelay + 300 + Math.random() * 300)); + LogUtils.sendDebug("Delay 4"); break; } if (!InventoryUtils.isInventoryLoaded()) { @@ -549,6 +558,7 @@ public void onTickExecute(TickEvent.ClientTickEvent event) { state = States.WAIT_FOR_INFO; InventoryUtils.clickContainerSlot(configurePlots.slotNumber, InventoryUtils.ClickType.LEFT, InventoryUtils.ClickMode.PICKUP); delayClock.schedule((long) (FarmHelperConfig.pestAdditionalGUIDelay + 500 + Math.random() * 500)); + LogUtils.sendDebug("Delay 5"); break; case WAIT_FOR_INFO: break; @@ -556,6 +566,7 @@ public void onTickExecute(TickEvent.ClientTickEvent event) { PlotUtils.Plot plot; if (FarmHelperConfig.dontTeleportToPlots) { delayClock.schedule(1_000 + Math.random() * 500); + LogUtils.sendDebug("Delay 6"); MacroHandler.getInstance().triggerWarpGarden(true, false); state = States.CHECKING_SPAWN; return; @@ -565,6 +576,7 @@ public void onTickExecute(TickEvent.ClientTickEvent event) { if (plot == null) { state = States.GO_BACK; delayClock.schedule((long) (500 + Math.random() * 500)); + LogUtils.sendDebug("Delay 7"); return; } if (GameStateHandler.getInstance().getCurrentPlot() == plot.number && BlockUtils.canFlyHigher(8)) { @@ -575,7 +587,9 @@ public void onTickExecute(TickEvent.ClientTickEvent event) { preTpBlockPos = Optional.of(mc.thePlayer.getPosition()); mc.thePlayer.sendChatMessage("/tptoplot " + plotNumber); state = States.WAIT_FOR_TP; + this.closestPlot = Optional.of(plot); delayClock.schedule((long) (900 + Math.random() * 500)); + LogUtils.sendDebug("Delay 8"); break; case WAIT_FOR_TP: if (!preTpBlockPos.isPresent()) { @@ -587,22 +601,37 @@ public void onTickExecute(TickEvent.ClientTickEvent event) { } state = States.CHECKING_PLOT; delayClock.schedule((long) (200 + Math.random() * 200)); + LogUtils.sendDebug("Delay 9"); break; case CHECKING_PLOT: if (isInventoryOpenDelayed()) { break; } - KeyBindUtils.stopMovement(); - if (PlayerUtils.isPlayerSuffocating() || !BlockUtils.canFlyHigher(5)) { + boolean isSuffocating = PlayerUtils.isPlayerSuffocating(); + if (isSuffocating || !BlockUtils.canFlyHigher(5)) { + if (!suffocateEscapeTimer.isScheduled()) { + suffocateEscapeTimer.schedule(5000); + } + if (!suffocateEscapeTimer.passed()) { + if (!mc.gameSettings.keyBindJump.isKeyDown()) KeyBindUtils.setKeyBindState(mc.gameSettings.keyBindJump, true); + break; + } LogUtils.sendWarning("[Pests Destroyer] The player is suffocating and/or it can't fly higher. Going back to spawnpoint."); delayClock.schedule(1_000 + Math.random() * 500); + LogUtils.sendDebug("Delay 10"); MacroHandler.getInstance().triggerWarpGarden(true, false); isPlotObstructed = true; state = States.CHECKING_SPAWN; + KeyBindUtils.stopMovement(); + suffocateEscapeTimer.reset(); return; } - state = States.GET_LOCATION; + if (suffocateEscapeTimer.isScheduled()) { + suffocateEscapeTimer.reset(); + } + KeyBindUtils.stopMovement(); + state = States.FLY_TO_THE_CLOSEST_PLOT; break; case CHECKING_SPAWN: if (MacroHandler.getInstance().isTeleporting()) { @@ -610,8 +639,7 @@ public void onTickExecute(TickEvent.ClientTickEvent event) { } if (PlayerUtils.isPlayerSuffocating() || !BlockUtils.canFlyHigher(5)) { - LogUtils.sendError( - "[Pests Destroyer] Your spawnpoint is obstructed! Make sure there is no block above your spawnpoint! Disabling Pests Destroyer!"); + LogUtils.sendError("[Pests Destroyer] Your spawnpoint is obstructed! Make sure there is no block above your spawnpoint! Disabling Pests Destroyer!"); stop(); FarmHelperConfig.enablePestsDestroyer = false; // finishMacro(); @@ -654,7 +682,7 @@ public void onTickExecute(TickEvent.ClientTickEvent event) { } else { state = States.FLY_TO_THE_CLOSEST_PLOT; } - delayClock.schedule((long) (500 + Math.random() * 500)); + // delayClock.schedule((long) (500 + Math.random() * 500)); break; case FLY_TO_THE_CLOSEST_PLOT: if (MacroHandler.getInstance().isTeleporting()) { @@ -778,6 +806,7 @@ public void onTickExecute(TickEvent.ClientTickEvent event) { null ).easeOutBack(true)); delayClock.schedule(300); + LogUtils.sendDebug("Delay 11"); break; } state = States.WAIT_FOR_LOCATION; @@ -792,6 +821,7 @@ public void onTickExecute(TickEvent.ClientTickEvent event) { stuckClock.schedule(1_000 * 60 * FarmHelperConfig.pestsKillerStuckTime); } delayClock.schedule(300); + LogUtils.sendDebug("Delay 12"); break; case WAIT_FOR_LOCATION: if (isInventoryOpenDelayed()) { @@ -840,6 +870,7 @@ public void onTickExecute(TickEvent.ClientTickEvent event) { state = States.FIND_PEST; delayBetweenFireworks.schedule(3_000); delayClock.schedule(300); + LogUtils.sendDebug("Delay 13"); break; } if (System.currentTimeMillis() - lastFireworkTime > 6_000) { @@ -905,6 +936,7 @@ public void onTickExecute(TickEvent.ClientTickEvent event) { stuckClock.schedule(1_000 * 60 * FarmHelperConfig.pestsKillerStuckTime); } delayClock.schedule(300); + LogUtils.sendDebug("Delay 14"); break; case KILL_PEST: if (isInventoryOpenDelayed()) { @@ -947,6 +979,7 @@ public void onTickExecute(TickEvent.ClientTickEvent event) { escapeState = EscapeState.GO_TO_HUB; KeyBindUtils.stopMovement(); delayClock.schedule(300); + LogUtils.sendDebug("Delay 15"); return; } @@ -1008,6 +1041,7 @@ public void onTickExecute(TickEvent.ClientTickEvent event) { flyPathfinderTries = 0; KeyBindUtils.stopMovement(); delayClock.schedule(1_000 + Math.random() * 500); + LogUtils.sendDebug("Delay 16"); MacroHandler.getInstance().triggerWarpGarden(true, false); state = States.CHECKING_SPAWN; return; @@ -1039,6 +1073,7 @@ public void onTickExecute(TickEvent.ClientTickEvent event) { if (GameStateHandler.getInstance().getPestsCount() == 0) { state = States.GO_BACK; delayClock.schedule((long) (500 + Math.random() * 500)); + LogUtils.sendDebug("Delay 17"); break; } System.out.println("Curr plot pests: " + GameStateHandler.getInstance().getCurrentPlotPestsCount()); @@ -1050,6 +1085,7 @@ public void onTickExecute(TickEvent.ClientTickEvent event) { state = States.KILL_PEST; currentEntityTarget = Optional.of(closestPest2); delayClock.schedule(50 + (long) (Math.random() * 100)); + LogUtils.sendDebug("Delay 18"); } else { PlotUtils.Plot plotOpt = getClosestPlot(); if (plotOpt != null) { @@ -1059,15 +1095,18 @@ public void onTickExecute(TickEvent.ClientTickEvent event) { LogUtils.sendDebug("Going manually to another plot"); state = States.GET_CLOSEST_PLOT; delayClock.schedule(100 + (long) (Math.random() * 150)); + LogUtils.sendDebug("Delay 19"); break; } else { LogUtils.sendDebug("Teleporting to plot"); state = States.TELEPORT_TO_PLOT; delayClock.schedule(400 + (long) (Math.random() * 400)); + LogUtils.sendDebug("Delay 20"); } } else { state = States.GO_BACK; delayClock.schedule(300 + (long) (Math.random() * 300)); + LogUtils.sendDebug("Delay 21"); } } break; @@ -1591,7 +1630,7 @@ public void onGuiOpen(DrawScreenAfterEvent event) { private final Clock flyDelay = new Clock(); - private void fly() { + public void fly() { if (mc.thePlayer.capabilities.isFlying) { KeyBindUtils.holdThese(mc.gameSettings.keyBindJump); return; diff --git a/src/main/java/com/jelly/farmhelperv2/feature/impl/VisitorsMacro.java b/src/main/java/com/jelly/farmhelperv2/feature/impl/VisitorsMacro.java index 9174514c..50b92cd5 100644 --- a/src/main/java/com/jelly/farmhelperv2/feature/impl/VisitorsMacro.java +++ b/src/main/java/com/jelly/farmhelperv2/feature/impl/VisitorsMacro.java @@ -239,7 +239,10 @@ public boolean canEnableMacro(boolean manual, boolean withError) { if (isRunning()) return false; if (!GameStateHandler.getInstance().inGarden()) return false; if (mc.thePlayer == null || mc.theWorld == null) return false; - if (FeatureManager.getInstance().isAnyOtherFeatureEnabled()) return false; + if (FeatureManager.getInstance().isAnyOtherFeatureEnabled()) { + LogUtils.sendWarning("here"); + return false; + } if (FailsafeManager.getInstance().triggeredFailsafe.isPresent()) return false; if (GameStateHandler.getInstance().getServerClosingSeconds().isPresent()) { diff --git a/src/main/java/com/jelly/farmhelperv2/handler/MacroHandler.java b/src/main/java/com/jelly/farmhelperv2/handler/MacroHandler.java index 7f3179b3..66703e1b 100644 --- a/src/main/java/com/jelly/farmhelperv2/handler/MacroHandler.java +++ b/src/main/java/com/jelly/farmhelperv2/handler/MacroHandler.java @@ -326,6 +326,7 @@ public void onChatMessageReceived(ClientChatReceivedEvent event) { if (!message.contains(":") && GameStateHandler.getInstance().inGarden()) { if (message.equals("Your spawn location has been set!")) { PlayerUtils.setSpawnLocation(); + PestFarmer.instance.wasSpawnChanged = false; for (Rewarp rewarp : FarmHelperConfig.rewarpList) { if (mc.thePlayer.getDistance(rewarp.x, rewarp.y, rewarp.z) < 2) { LogUtils.sendWarning("Spawn location is close to the rewarp location! Removing it from the list..."); diff --git a/src/main/java/com/jelly/farmhelperv2/macro/AbstractMacro.java b/src/main/java/com/jelly/farmhelperv2/macro/AbstractMacro.java index d03d89cc..521f4f22 100644 --- a/src/main/java/com/jelly/farmhelperv2/macro/AbstractMacro.java +++ b/src/main/java/com/jelly/farmhelperv2/macro/AbstractMacro.java @@ -7,7 +7,6 @@ import com.jelly.farmhelperv2.feature.FeatureManager; import com.jelly.farmhelperv2.feature.impl.DesyncChecker; import com.jelly.farmhelperv2.feature.impl.LagDetector; -import com.jelly.farmhelperv2.feature.impl.PestFarmer; import com.jelly.farmhelperv2.feature.impl.PestsDestroyer; import com.jelly.farmhelperv2.handler.GameStateHandler; import com.jelly.farmhelperv2.handler.MacroHandler; @@ -163,7 +162,6 @@ public void onTick() { return; } - if (getRotation().isRotating()) { if (!mc.gameSettings.keyBindSneak.isKeyDown()) KeyBindUtils.stopMovement(); @@ -235,9 +233,7 @@ public void onTick() { return; } - if (!PestFarmer.instance.holdDaedalus()) { - PlayerUtils.getTool(); - } + PlayerUtils.getTool(); // Update or invoke state, based on if player is moving or not if (GameStateHandler.getInstance().canChangeDirection()) { diff --git a/src/main/java/com/jelly/farmhelperv2/pathfinder/FlyPathFinderExecutor.java b/src/main/java/com/jelly/farmhelperv2/pathfinder/FlyPathFinderExecutor.java index 549e2d9f..96b5bdf4 100644 --- a/src/main/java/com/jelly/farmhelperv2/pathfinder/FlyPathFinderExecutor.java +++ b/src/main/java/com/jelly/farmhelperv2/pathfinder/FlyPathFinderExecutor.java @@ -87,6 +87,8 @@ public static FlyPathFinderExecutor getInstance() { private boolean dontRotate = false; private final EvictingQueue lastPositions = EvictingQueue.create(100); private Position lastPosition; + @Setter + private float stoppingPositionThreshold = 0.75f; public void findPath(Vec3 pos, boolean follow, boolean smooth) { @@ -132,9 +134,11 @@ public void findPath(Vec3 pos, boolean follow, boolean smooth) { if (smooth) { finalRoute = smoothPath(finalRoute); } - this.path.clear(); - this.path.addAll(finalRoute.stream().map(vec3 -> vec3.addVector(0.5f, 0.15, 0.5)).collect(Collectors.toCollection(CopyOnWriteArrayList::new))); - state = State.PATHING; + if (!this.isDecelerating()) { + this.path.clear(); + this.path.addAll(finalRoute.stream().map(vec3 -> vec3.addVector(0.5f, 0.15, 0.5)).collect(Collectors.toCollection(CopyOnWriteArrayList::new))); + state = State.PATHING; + } LogUtils.sendDebug("Path smoothing took " + (System.currentTimeMillis() - startTime) + "ms"); if (timeoutTask != null) { timeoutTask.stop(); @@ -287,6 +291,7 @@ public void stop() { stuckBreak.reset(); stuckCheckDelay.reset(); dontRotate = false; + stoppingPositionThreshold = 0.75f; } @SubscribeEvent @@ -337,6 +342,14 @@ public void onTickNeededYaw(TickEvent.ClientTickEvent event) { KeyBindUtils.stopMovement(true); return; } + + if (state == State.DECELERATING) { + if (mc.thePlayer.motionX == 0 && mc.thePlayer.motionZ == 0 && mc.thePlayer.motionY == (mc.thePlayer.onGround ? -0.0784000015258789 : 0)) { + stop(); + } + return; + } + if (stuckBreak.isScheduled() && !stuckBreak.passed()) return; Vec3 current = mc.thePlayer.getPositionVector(); BlockPos currentPos = mc.thePlayer.getPosition(); @@ -392,7 +405,9 @@ public void onTickNeededYaw(TickEvent.ClientTickEvent event) { float distance = (float) mc.thePlayer.getPositionVector().distanceTo(targetPos); float distancePath = (float) mc.thePlayer.getPositionVector().distanceTo(lastElem); if (willArriveAtDestinationAfterStopping(lastElem) && entityVelocity < 0.15) { - stop(); + state = State.DECELERATING; + KeyBindUtils.stopMovement(true); + // stop(); return; } if ((distance < 1 && entityVelocity > 0.15) || (distancePath < 0.5 && entityVelocity < 0.15)) { @@ -400,7 +415,9 @@ public void onTickNeededYaw(TickEvent.ClientTickEvent event) { return; } } else if (willArriveAtDestinationAfterStopping(lastElem) || mc.thePlayer.getDistance(lastElem.xCoord, lastElem.yCoord, lastElem.zCoord) < 0.3) { - stop(); + state = State.DECELERATING; + KeyBindUtils.stopMovement(true); + // stop(); return; } if (!mc.thePlayer.capabilities.allowFlying) { @@ -535,7 +552,7 @@ public boolean isTping() { } private boolean willArriveAtDestinationAfterStopping(Vec3 targetPos) { - return predictStoppingPosition().distanceTo(targetPos) < 0.75; + return predictStoppingPosition().distanceTo(targetPos) < stoppingPositionThreshold; } private Vec3 predictStoppingPosition() { diff --git a/src/main/java/com/jelly/farmhelperv2/util/PlayerUtils.java b/src/main/java/com/jelly/farmhelperv2/util/PlayerUtils.java index b923670f..3f2cc34d 100644 --- a/src/main/java/com/jelly/farmhelperv2/util/PlayerUtils.java +++ b/src/main/java/com/jelly/farmhelperv2/util/PlayerUtils.java @@ -6,6 +6,8 @@ import com.jelly.farmhelperv2.failsafe.FailsafeManager; import com.jelly.farmhelperv2.handler.MacroHandler; import com.jelly.farmhelperv2.util.helper.Clock; +import com.jelly.farmhelperv2.util.AngleUtils; +import com.jelly.farmhelperv2.handler.GameStateHandler; import net.minecraft.block.*; import net.minecraft.client.Minecraft; import net.minecraft.entity.Entity; @@ -347,6 +349,9 @@ public static void setSpawnLocation() { FarmHelperConfig.spawnPosX = pos.getX(); FarmHelperConfig.spawnPosY = pos.getY(); FarmHelperConfig.spawnPosZ = pos.getZ(); + FarmHelperConfig.spawnYaw = AngleUtils.normalizeAngle(mc.thePlayer.rotationYaw); + FarmHelperConfig.spawnPitch = AngleUtils.normalizeAngle(mc.thePlayer.rotationPitch); + FarmHelperConfig.spawnPlot = GameStateHandler.getInstance().getCurrentPlot(); FarmHelper.config.save(); } From 227a890654887c7d461b5e78d31aed10024bd5b5 Mon Sep 17 00:00:00 2001 From: Osama Date: Tue, 25 Feb 2025 10:44:44 +0600 Subject: [PATCH 07/10] Improvements --- .gradle.properties.swp | Bin 0 -> 12288 bytes gradle.properties | 2 +- .../farmhelperv2/config/FarmHelperConfig.java | 10 ++++++++++ .../feature/impl/AutoSprayonator.java | 2 +- .../feature/impl/PestsDestroyer.java | 6 ++++-- .../feature/impl/ProfitCalculator.java | 9 +++++++++ .../feature/impl/VisitorsMacro.java | 7 ++----- .../jelly/farmhelperv2/macro/AbstractMacro.java | 7 ------- .../pathfinder/FlyPathFinderExecutor.java | 2 +- 9 files changed, 28 insertions(+), 17 deletions(-) create mode 100644 .gradle.properties.swp diff --git a/.gradle.properties.swp b/.gradle.properties.swp new file mode 100644 index 0000000000000000000000000000000000000000..606b0f3cfd7c3d7bcba132479f6e9f2b96c7af32 GIT binary patch literal 12288 zcmeI&Jx;?g7zSXMiHYBpq0qTb6P6Y!6BV>lL4ed!v89chCbH{bCl!c0a0iaS0k{O` z;12K^Dj|l#US3OYV#hyHo-z4GjY0RU+TuQ=w#C>@=OuC7y=}&N>1~tL^~$E6ap!g?1*XV#lUMoopxh4B&-#ZvIxXc`r%uz#P96%c^H zQh~CV)SDaZFz_3-gZ=96PJiiAOh5nv5P$##AOHafKmY=(DNy7U_D-+1Mp>s+7NHv& z1Rwwb2tWV=5P$##AOHafKmYDKI{10O)OfJi=<_CTu@N13YIK>0W36~5q`c=pHfWRZMfrR- bSCL6m>-B@yfcUVLdW literal 0 HcmV?d00001 diff --git a/gradle.properties b/gradle.properties index 93d8e548..45db43e8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,5 +4,5 @@ baseGroup=com.jelly.farmhelperv2 mcVersion=1.8.9 modid=farmhelperv2 modName=FarmHelper -version=2.9.10 +version=2.9.11.1 shouldRelease=true diff --git a/src/main/java/com/jelly/farmhelperv2/config/FarmHelperConfig.java b/src/main/java/com/jelly/farmhelperv2/config/FarmHelperConfig.java index 71e7beac..805d44e6 100644 --- a/src/main/java/com/jelly/farmhelperv2/config/FarmHelperConfig.java +++ b/src/main/java/com/jelly/farmhelperv2/config/FarmHelperConfig.java @@ -1977,6 +1977,12 @@ public static void triggerManuallyAutoPestExchange() { min = 1, max = 64 ) public static int autoSprayonatorAutoBuyAmount = 1; + + @Slider( + name = "Time to wait after entering plot before starting", category = AUTO_SPRAYONATOR, subcategory = "Auto Sprayonator", + min = 0, max = 5000, step = 100 + ) + public static int autoSprayonatorStartDelay = 0; // // @@ -2305,6 +2311,10 @@ public static void triggerManuallyAutoComposter() { name = "Reset stats between disabling", category = HUD, subcategory = "Profit Calculator" ) public static boolean resetStatsBetweenDisabling = false; + @Switch( + name = "Count Pest Drops to Profit Calculator", category = HUD, subcategory = "Profit Calculator" + ) + public static boolean profitCalcCountPestDrop = false; // @Button( // name = "Reset Profit Calculator", category = HUD, subcategory = "Profit Calculator", // text = "Reset Now", size = 2 diff --git a/src/main/java/com/jelly/farmhelperv2/feature/impl/AutoSprayonator.java b/src/main/java/com/jelly/farmhelperv2/feature/impl/AutoSprayonator.java index fd885bc7..2f7b200b 100644 --- a/src/main/java/com/jelly/farmhelperv2/feature/impl/AutoSprayonator.java +++ b/src/main/java/com/jelly/farmhelperv2/feature/impl/AutoSprayonator.java @@ -145,7 +145,7 @@ public void onTablistUpdate(UpdateTablistEvent event) { } if (!this.timer.isScheduled()) { - this.timer.schedule(5000); + this.timer.schedule(FarmHelperConfig.autoSprayonatorStartDelay); } else if (this.timer.passed()) { this.start(); } diff --git a/src/main/java/com/jelly/farmhelperv2/feature/impl/PestsDestroyer.java b/src/main/java/com/jelly/farmhelperv2/feature/impl/PestsDestroyer.java index 3de7c56e..fbe6e9b8 100644 --- a/src/main/java/com/jelly/farmhelperv2/feature/impl/PestsDestroyer.java +++ b/src/main/java/com/jelly/farmhelperv2/feature/impl/PestsDestroyer.java @@ -7,6 +7,7 @@ import com.jelly.farmhelperv2.event.SpawnParticleEvent; import com.jelly.farmhelperv2.failsafe.FailsafeManager; import com.jelly.farmhelperv2.feature.IFeature; +import com.jelly.farmhelperv2.feature.impl.PestFarmer; import com.jelly.farmhelperv2.handler.GameStateHandler; import com.jelly.farmhelperv2.handler.MacroHandler; import com.jelly.farmhelperv2.handler.RotationHandler; @@ -159,7 +160,7 @@ public void start() { lastKillTimestamp = 0; if (MacroHandler.getInstance().isMacroToggled()) { MacroHandler.getInstance().pauseMacro(); - MacroHandler.getInstance().getCurrentMacro().ifPresent(am -> am.setSavedState(Optional.empty())); +// MacroHandler.getInstance().getCurrentMacro().ifPresent(am -> am.setSavedState(Optional.empty())); KeyBindUtils.stopMovement(); } escapeState = EscapeState.NONE; @@ -1189,7 +1190,8 @@ private void finishMacro() { if (FlyPathFinderExecutor.getInstance().isPathing()) { FlyPathFinderExecutor.getInstance().stop(); } - if (MacroHandler.getInstance().isMacroToggled()) { + // bad macro design - loser + if (!PestFarmer.instance.isRunning() && MacroHandler.getInstance().isMacroToggled()) { stop(); MacroHandler.getInstance().triggerWarpGarden(true, true, false); delayClock.schedule(2_000 + Math.random() * 500); diff --git a/src/main/java/com/jelly/farmhelperv2/feature/impl/ProfitCalculator.java b/src/main/java/com/jelly/farmhelperv2/feature/impl/ProfitCalculator.java index 4f2fccf9..e02fee19 100644 --- a/src/main/java/com/jelly/farmhelperv2/feature/impl/ProfitCalculator.java +++ b/src/main/java/com/jelly/farmhelperv2/feature/impl/ProfitCalculator.java @@ -70,6 +70,7 @@ public class ProfitCalculator implements IFeature { @Getter private final Clock updateBazaarClock = new Clock(); private final Pattern regex = Pattern.compile("Dicer dropped (\\d+)x ([\\w\\s]+)!"); + private final Pattern pestPattern = Pattern.compile("You received (\\d+)x Enchanted (.+?) for killing a (\\w+)!"); public double realProfit = 0; public double realHourlyProfit = 0; @Getter @@ -374,6 +375,14 @@ public void onReceivedChat(ClientChatReceivedEvent event) { } addDroppedItem(itemDropped, amountDropped); } + + // + if (FarmHelperConfig.profitCalcCountPestDrop && message.matches("You received \\d+x Enchanted (\\w+\\s?)+!")) { + Matcher matcher = pestPattern.matcher(message); + if (matcher.find()) { + addDroppedItem(matcher.group(2), Integer.parseInt(matcher.group(1))); + } + } } private void addDroppedItem(String name, int amount) { diff --git a/src/main/java/com/jelly/farmhelperv2/feature/impl/VisitorsMacro.java b/src/main/java/com/jelly/farmhelperv2/feature/impl/VisitorsMacro.java index 50b92cd5..1134827a 100644 --- a/src/main/java/com/jelly/farmhelperv2/feature/impl/VisitorsMacro.java +++ b/src/main/java/com/jelly/farmhelperv2/feature/impl/VisitorsMacro.java @@ -158,7 +158,7 @@ public void start() { } if (MacroHandler.getInstance().isMacroToggled()) { MacroHandler.getInstance().pauseMacro(); - MacroHandler.getInstance().getCurrentMacro().ifPresent(am -> am.setSavedState(Optional.empty())); + // MacroHandler.getInstance().getCurrentMacro().ifPresent(am -> am.setSavedState(Optional.empty())); } ignoredNPCs.clear(); profitNpc = false; @@ -239,10 +239,7 @@ public boolean canEnableMacro(boolean manual, boolean withError) { if (isRunning()) return false; if (!GameStateHandler.getInstance().inGarden()) return false; if (mc.thePlayer == null || mc.theWorld == null) return false; - if (FeatureManager.getInstance().isAnyOtherFeatureEnabled()) { - LogUtils.sendWarning("here"); - return false; - } + if (FeatureManager.getInstance().isAnyOtherFeatureEnabled()) return false; if (FailsafeManager.getInstance().triggeredFailsafe.isPresent()) return false; if (GameStateHandler.getInstance().getServerClosingSeconds().isPresent()) { diff --git a/src/main/java/com/jelly/farmhelperv2/macro/AbstractMacro.java b/src/main/java/com/jelly/farmhelperv2/macro/AbstractMacro.java index 521f4f22..7728cdd2 100644 --- a/src/main/java/com/jelly/farmhelperv2/macro/AbstractMacro.java +++ b/src/main/java/com/jelly/farmhelperv2/macro/AbstractMacro.java @@ -7,7 +7,6 @@ import com.jelly.farmhelperv2.feature.FeatureManager; import com.jelly.farmhelperv2.feature.impl.DesyncChecker; import com.jelly.farmhelperv2.feature.impl.LagDetector; -import com.jelly.farmhelperv2.feature.impl.PestsDestroyer; import com.jelly.farmhelperv2.handler.GameStateHandler; import com.jelly.farmhelperv2.handler.MacroHandler; import com.jelly.farmhelperv2.handler.RotationHandler; @@ -149,12 +148,6 @@ public void onTick() { checkOnSpawnClock.schedule(5000); } - if (FarmHelperConfig.pestForceEnable && PestsDestroyer.getInstance().canEnableMacro()) { - PestsDestroyer.getInstance().start(); - LogUtils.sendDebug("Activating Pests Destroyer"); - return; - } - if (mc.thePlayer.getPosition().getY() < 0) { LogUtils.sendError("Build a wall between the rewarp point and the void to prevent falling out of the garden! Disabling the macro..."); MacroHandler.getInstance().disableMacro(); diff --git a/src/main/java/com/jelly/farmhelperv2/pathfinder/FlyPathFinderExecutor.java b/src/main/java/com/jelly/farmhelperv2/pathfinder/FlyPathFinderExecutor.java index 96b5bdf4..8f16d11b 100644 --- a/src/main/java/com/jelly/farmhelperv2/pathfinder/FlyPathFinderExecutor.java +++ b/src/main/java/com/jelly/farmhelperv2/pathfinder/FlyPathFinderExecutor.java @@ -344,7 +344,7 @@ public void onTickNeededYaw(TickEvent.ClientTickEvent event) { } if (state == State.DECELERATING) { - if (mc.thePlayer.motionX == 0 && mc.thePlayer.motionZ == 0 && mc.thePlayer.motionY == (mc.thePlayer.onGround ? -0.0784000015258789 : 0)) { + if (Math.abs(mc.thePlayer.motionX) <= 0.05 && Math.abs(mc.thePlayer.motionZ) <= 0.05 && mc.thePlayer.motionY == (mc.thePlayer.onGround ? -0.0784000015258789 : 0)) { stop(); } return; From 4a1359f419c1abdc03fa0548a44faad2591a99aa Mon Sep 17 00:00:00 2001 From: Osama Date: Tue, 25 Feb 2025 11:06:57 +0600 Subject: [PATCH 08/10] Fixed ProfitCalc Dicer Bug & Added Pest Drops to Profit Calc --- .gradle.properties.swp | Bin 12288 -> 0 bytes .../feature/impl/.ProfitCalculator.java.swp | Bin 0 -> 36864 bytes .../feature/impl/ProfitCalculator.java | 48 +++++++++--------- 3 files changed, 24 insertions(+), 24 deletions(-) delete mode 100644 .gradle.properties.swp create mode 100644 src/main/java/com/jelly/farmhelperv2/feature/impl/.ProfitCalculator.java.swp diff --git a/.gradle.properties.swp b/.gradle.properties.swp deleted file mode 100644 index 606b0f3cfd7c3d7bcba132479f6e9f2b96c7af32..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI&Jx;?g7zSXMiHYBpq0qTb6P6Y!6BV>lL4ed!v89chCbH{bCl!c0a0iaS0k{O` z;12K^Dj|l#US3OYV#hyHo-z4GjY0RU+TuQ=w#C>@=OuC7y=}&N>1~tL^~$E6ap!g?1*XV#lUMoopxh4B&-#ZvIxXc`r%uz#P96%c^H zQh~CV)SDaZFz_3-gZ=96PJiiAOh5nv5P$##AOHafKmY=(DNy7U_D-+1Mp>s+7NHv& z1Rwwb2tWV=5P$##AOHafKmYDKI{10O)OfJi=<_CTu@N13YIK>0W36~5q`c=pHfWRZMfrR- bSCL6m>-B@yfcUVLdW diff --git a/src/main/java/com/jelly/farmhelperv2/feature/impl/.ProfitCalculator.java.swp b/src/main/java/com/jelly/farmhelperv2/feature/impl/.ProfitCalculator.java.swp new file mode 100644 index 0000000000000000000000000000000000000000..e1e4aebe85b17d463ae1d67acd62589788fbbb5e GIT binary patch literal 36864 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 literal 0 HcmV?d00001 diff --git a/src/main/java/com/jelly/farmhelperv2/feature/impl/ProfitCalculator.java b/src/main/java/com/jelly/farmhelperv2/feature/impl/ProfitCalculator.java index e02fee19..f2863493 100644 --- a/src/main/java/com/jelly/farmhelperv2/feature/impl/ProfitCalculator.java +++ b/src/main/java/com/jelly/farmhelperv2/feature/impl/ProfitCalculator.java @@ -329,22 +329,25 @@ public void onReceivedChat(ClientChatReceivedEvent event) { if (event.type != 0 || event.message == null) return; String message = StringUtils.stripControlCodes(event.message.getUnformattedText()); - if (message.contains(":") || !message.contains("coins")) return; - if (((message.startsWith("[Bazaar] Claimed ") || message.startsWith("You collected ")) && message.contains("coins from selling")) || message.startsWith("[Bazaar] Sold ")) { - Matcher matcher = coinsPattern.matcher(message); - if (matcher.find()) { - String coinsFound = matcher.group(1); - try { - double coins = Double.parseDouble(coinsFound.replace(",", "")); - realProfit -= coins; - } catch (NumberFormatException e) { - LogUtils.sendDebug("Failed to parse coins from message: " + e.getMessage()); + if (message.contains(":")) return; + if (message.contains("coins")) { + if (((message.startsWith("[Bazaar] Claimed ") || message.startsWith("You collected ")) && message.contains("coins from selling")) || message.startsWith("[Bazaar] Sold ")) { + Matcher matcher = coinsPattern.matcher(message); + if (matcher.find()) { + String coinsFound = matcher.group(1); + try { + double coins = Double.parseDouble(coinsFound.replace(",", "")); + realProfit -= coins; + } catch (NumberFormatException e) { + LogUtils.sendDebug("Failed to parse coins from message: " + e.getMessage()); + } + LogUtils.sendWarning("Selling crops in bazaar or auction house may break the profit calculator! Pause the macro before taking any action!"); } - LogUtils.sendWarning("Selling crops in bazaar or auction house may break the profit calculator! Pause the macro before taking any action!"); } - } - if (message.contains("Sold") || message.contains("[Auction]")) return; + // if (message.contains("Sold") || message.contains("[Auction]")) return; + return; + } Optional optional = rngToCountList.stream().filter(message::contains).findFirst(); if (optional.isPresent()) { @@ -357,15 +360,12 @@ public void onReceivedChat(ClientChatReceivedEvent event) { String itemDropped; int amountDropped; Matcher matcher = regex.matcher(message); - if (matcher.find()) { - amountDropped = Integer.parseInt(matcher.group(1)); - if (matcher.group(2).contains("Melon")) { - itemDropped = "Melon"; - } else if (matcher.group(2).contains("Pumpkin")) { - itemDropped = "Pumpkin"; - } else { - return; - } + if (!matcher.find()) return; + amountDropped = Integer.parseInt(matcher.group(1)); + if (matcher.group(2).contains("Melon")) { + itemDropped = "Melon"; + } else if (matcher.group(2).contains("Pumpkin")) { + itemDropped = "Pumpkin"; } else { return; } @@ -376,11 +376,11 @@ public void onReceivedChat(ClientChatReceivedEvent event) { addDroppedItem(itemDropped, amountDropped); } - // if (FarmHelperConfig.profitCalcCountPestDrop && message.matches("You received \\d+x Enchanted (\\w+\\s?)+!")) { Matcher matcher = pestPattern.matcher(message); if (matcher.find()) { - addDroppedItem(matcher.group(2), Integer.parseInt(matcher.group(1))); + addDroppedItem(matcher.group(2), Integer.parseInt(matcher.group(1)) * 160); + LogUtils.sendDebug("Added " + matcher.group(2) + ", killed " + matcher.group(3)); } } } From 6bbfa235e51617a1b0e3b76626f954b9d5a71190 Mon Sep 17 00:00:00 2001 From: Osama Date: Tue, 25 Feb 2025 11:20:09 +0600 Subject: [PATCH 09/10] Stopped pausing timer while killing pest if pest drop is being counted --- .../feature/impl/.PestsDestroyer.java.swp | Bin 0 -> 98304 bytes .../feature/impl/.ProfitCalculator.java.swp | Bin 36864 -> 0 bytes .../feature/impl/PestsDestroyer.java | 6 ++++++ 3 files changed, 6 insertions(+) create mode 100644 src/main/java/com/jelly/farmhelperv2/feature/impl/.PestsDestroyer.java.swp delete mode 100644 src/main/java/com/jelly/farmhelperv2/feature/impl/.ProfitCalculator.java.swp diff --git a/src/main/java/com/jelly/farmhelperv2/feature/impl/.PestsDestroyer.java.swp b/src/main/java/com/jelly/farmhelperv2/feature/impl/.PestsDestroyer.java.swp new file mode 100644 index 0000000000000000000000000000000000000000..57deea9b925bb011ac7fe3fca647c4609fa2bb9c GIT binary patch literal 98304 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
9@9c zxjDr9xla+-GuirMy(C*@0qD2WRt{?srSKo|<1GUva%4&=k53kLWd(25?lNgqGD)&U zRGb-DU=`MC=Wc{@_w zTq}r9ok^Je?b3&iY(kum1Rm6s#(cMpnM>gG1U%=kYo`uEvbnY zvy=*k26%#F+|=J*B~Zv58PiMfW!dir(~dUIk(uXLqOr0f`_K-RXw^fdLHTFMQ&LS} ztkRK3*;%Y3o|I|ptQ@95}WWI6b@4c7pSgIZnMAp;#M1lS(LhFzDWT^8W%RzX9i^;SyCh?~U)jm1!b;tI^ovOWjfC~) zYNsSb3l_*OtLc?pR{NEczm!2fRkn{YawHtzuke88sh}EoJY}NHV$M?i$m4mY6LnnA z!igSqa&}zN41xMo8Tm(L>||w=N{x7o3SON#QPzXoL3VSyT}UNhmy77WDD?b7YbP39hPh_im=(Q-Tu zAz1_yls@Vi^6}S4LG&K}m5@B9n6em=){q|&5d1SvAOlZgG`8p0ZnKG$&fYwsYLX{9 zdxhCOz~*yrI>;F^uKJ%9&dK-{47NXZIOd(Pf_a?ol821T!8}ff^EhqFL-LVNac!%< z(GpI?e^LF}s_e*)p+hu`JjNAV7R1Cw^eXZjyvlCA-QsC`wHq)eEctfyNC zC?HI$*wjh7gtNLXKgQIX@bMv5ckximcM^y77P)&D8zW5@IEukLlxSh*|Br%EpEQbm z{EciHq{BnrnjS}_g~Y5hBg@S~I?@04qwyXRy%+so&i~&=*S{C&py!_i*MI}y|Dfl8 z8N3V3fu8{P1m8pN|4;BnFath;zP|&07Cal>{u$uu;41I~bo}=MS<`^{@|Hr{+(eqD%E5Mi0^*;&T3Vs3n8#?~G!5c)^2aDjo z;N|H2KL@@^eV2jM`=Hdlmygu|;eQWc57Y;|%IJcKt$f*i_7@$^XS0elGfs$dU?nRC zyn5-{m`ptWd@|NH$OEzdc=)9yHKt^HJ^}Vifc{vaO*(zLDDo|1ft#vcb@uiu31y3* zKfJ|Sw@98LLrS7QJum%AgII*}2qGiWUSbffi#^(vnIv_)u5Jm`Fef6PGtgN1Q|waqk9CbrPZPJViGv z>5pv6?79VecR6XyeCC%w8`G}sxef=S)wFB3?6yqHQ7SF3rYO`1DwHUFQEpO0z6Ex} z7*$q-pr_CEHcQ$ZQmT~g`O!+p9r9(;Q*)#H!ir-WR0!+_GtS{wTsstf!di#1BJE8p z-KG70WNYbG4b?3L@!*XGT^G|MHV3lz%)T!HawTQo;*9+}F_oH};vCWaL35U{zkDqI zvb-3W!_^KTI$66MXD6XFv3f!~A!a#0F*lTN-r`WmxV2*_Q7jbOTZp>ixT_vnlQ^z4 z=+tnvoO}^Z&%=q9ge@EWycQ3Ma=v>Rl}lfrsw4kIZ7YOcUJ3+u6`sZPjbT{6cGCm9>D^RM0Ro0qorSiO z>IDmyUMISXPG%#W1eZF1|zlB(>njrAo9RU0CC)VFQQY6{@XQgS>W@$lN74Y*Pa(vZl5Y zS|igX2@*xw|77_`WH3^-mTD8$qPvr_;s@UL$9^F(xWYwb&a#Amkx}+l*yb*IV=ckh53KY5<@~=-iVlqaU+3#D z(EVla|4YFA!N<`3WxxM#0y+QhW*|0!!{EW-8`uEe2VMf64$gu_a3#0`d=Z<#`@uWF z6Tvw61@I#51HS^!f+`Syfq%kA@DD)l1^itg`vOjZ8E{YVA+ZktxfierjsZFM?`Oe1 z!B?>v$X@?9f|r8-4qgD3z&`K*a4&FA@F8poudwY3a!=qPa1Zde*cM(3ehbK*fiqwj z>;n%2|AxKc13=FGe-Dto1KZ#UAP4RbUXKmpkHM?K(?JEC1PSny;K#xJ!8frZ|sc=iOC&Q+J(M2P(upe=EVOtN0e24Mj1~=cV{h&k_2{TfJFD zCV1ar*DGRMk9^CCF6!u>z*&G^k4|+8tIiyAuf0vy->|k=<}Hb5Ij+RPKSgz%gtH(w z$np&TyKkKJzroO|nG=Z0`EqD&E#p8|Y{z|-l#L^}pj6cwgR5YfxG+E~nYXLZBC9v(P@Z6>D!7SA z>BV;=cASkcSNr^2JR?q!h7vpSq$kr7$~sJ&aykU_aWp|7tdFXaT%eFv@6-Guc?t(i_z%A7rqcIG z9QpWb6s(P8t%pl-j?xz@$q_BB!~$ozj!beh#7JgxcF9|sP}rDC#Yb-kBqRZ2k(P>7sH#tmS<_dMKLHM4D-b_!k>XiOcY*208jBz(tO}Pb7 za=Ev{vUSTEemDcSP}1#!9WC4y+x2tM*B?*Ap_HrS8d<(~jA zNO=9Zw8o`IJ$GRfTFLtV!_oO)ZtMRy@%LxZ`9A~}z{A1)z<1H}KM#H%JRW=wz5cx* z0qzZC{r{Wb8$fjZ_W|(-xCJ~G90dK~i|F_t10Mvh0b&DqE;tS3F2HMnoDJ|P(e=R{ zK+XVs7Pt+_*#M6K|B9~vx8Nh-!$ABA&H%X+@E_6b<-Gr=ftx`b$T@#616lBGbojS` zX9GE-|9;?e=jy$7!TngdG)cQ z92PY&I6O3b?CN9Jh{@Yy@n-a#<@l5~_ui_faZ4Yv{Eo1aagc4HiZoi`7HzhJ%BI}N zb!XEEY*cLx`T`Rmr&cZ>8$&yI74hA^;Ad_@h2%yEOFJ@i50wJ%pG4< zbkm__hE#&rp!rh~%7!e%CEUVt_V%V+LuTaAbq1Dc$eOa%(IMtDpzInsRdS3uayOc8 zFDZ0y0*rOca7oDrzI%RL`Ju)BEmdN#I;&18WbYFOQ*K12sr`E+O}i%p$J_WDE6Cut z>bB^Uy6BHTjyw%Nk*AvwSRMLbZXP(`ZypuNy~C&bwyzfHDC@55@3suN*zLqe*plU( zwXc5JgE`86IR9o#$xMHCDU$>IEWxa{u6&%zSz@IXh?3 zU!`xiZI@)VZC_HB6$G`RM%NuFl|PGR_HFSVA5|6(`q{W;ZQ%>^iqwr;$Ii+_ zTXMTVz6zH?hLzpe(c^C=6*KdqnaRXuJnXkB)zcYkB||Oj>XLA_`JB}^yhD#flaCy2 z5R;$~gj>|dtYq=+o<@KpD|$$9Pk!FO5ME; zNKmn+7V+7+Etf*eMnEARgP|`yn@w%bQ{~!=4SrwXXe`gseADVc0&Di~Q*`4W*?r2k zST-mN(VW_oFXs$-U*R(zX9QNkIAX%G?`>7A$phiSM{Sp_{9F(meT91aJX5mw0xMm@ z-BYkBtQp5kPP@-IAq*#nIRvwY+C3Fr+c`BIye>x$vApHky)ym@Z*Ot$w)QG$q0Y@T z-J#yY>V=m69H#&|TG=ZU*i*jZYL~?BU&2cP5lw_Ey)Napxn?@~HeKRrTVJ_al#S#K z>*zJvQZ6Gtr>Al`gSw56C+BRdjI+k(Y@X_mb*y(CwW7Qe4CpMqc?;v4nDvJEK5vL# zbah!WmLpI-ehPu|9gKAh%YgbsSrNVhV`wkgGG))vhBET6##LLLUn1j-Nb1DpvO4EB zkO<_wA$G*ymVOoxa&-eKkR&C|ys~f4x$W_GM$WCT9(z(ofesZ>!nVcV38cOYC$4}Ij z7W0**#ng6oGSwliquIGsYpgP|nyQa>mWT42%aaS)CGxe?DJ(5!8s&w}wWXoe%JhgT z*G^%vw6%14cCc7mn9HA@7%ZGVQO%E~Rx9P?*0 zL&+oA#Z%k)+Nq(;PN|Z~of?Ej!nwlEmd-R&I`ar+`oCWD&){ds* zoS#tLTJ1MG;&f}$bJ_7z=d!utb~;xaOn0K1G<77sv)Ym7T&m3vWXI2fDSCFSYm<(Z=Bp?2r%&Cjn{z2gGt^Q8nVpG^rS;LZrS;;`%+AP8 zdORt#8qQCqk1nmB+Rp5399_z745SyAc9wFp8~Mfb4xl+RmHZ;jTbroS6>9m~{Lz%v zU0^kuv^H2RO_KKM*)_%LQ!T5hu-Bs!8+nL_%|OB7pUh@{Xn3tOwb02g(2Y+oY|`beA!cf}Q(Bz2hYsBh7k2!# zJdv9lsAm1opj&;Rv#f@TkxF4|cAz-kIO}%hg`Mfz;3nOBy-3@Y#)h}x)w89^g`=t* zbH|40+D9{s>4By7^guqhAYJ`Pdh$dyEA5|4(ii4w|D_|@@#GNQ{@hY6J-C!hp3Boe z^6R73B`A{}r_bby^rz%tetdK-wJJl~$m+@|zUl5Or@FRiy3t-czb4(F+m3XyIYykh zs3uJv$>fp)nekIc)47dv`P>q5P7P%z(~SP<;iX)@n%;pWhE7zMDqXw!d|`58t8gTf zSsvP4Tdo!F)?Gf6JF%8sq;BI26*}`!dT61xG<51*x;8(UsU>-mSt7K|R1NmBhJ-O} z-L6bmLrZk!%=)RF^kR~sdtxnJ%dBPAM+Wla3u_G4olI>W8Wd#~9?Z&cwvKd@D^j=F zwag?uF-f0Tr_TuQuTRwS6~oNjtz9ea@_DuC4!pNRTQK!xqNiqtq7#%cJ(wM@B0?UokzSd68iK?I;|`NdlF4*wCySt!Sv)nAAD@Ri*VgH| z)r>P?8fEDA^3d=O6IdrdG||qVPVF#Z->q90IeM5$6s|8GO|R$IGC2gX_2iDU9=|sj zxjIa=!%MaNT6*yW?-5MLm$u>Zqv;`f%=ki$)`dfm$JdM0cXc4W#~zDze|{ZSsYeVV z#epszwv)+?R;eBxGry4;M~)azb(TbK6xm`Z*0Ihudi?I) zqzshGe56DDcG5c;RK!yq)TJF{WZ1h(vmz%?o?s#>ZDeyJNAu&W+t3BIQDku9 zu2KSxaWXXupius{ox!q0>p>^g{ml%8^o81ZF|nO?2?WCc&Y0rF6XZ1vS+5|NBt@5hz6sn zkNV=<*D9=()7Bl2af992IqX+Fq-?)L-2aAS9Nn|U(XaL?r=>=$5JPh2jBxw3S~e0* zZ7s`wBKv`R_NjkP*M&7?E=$gqeOt`lEvmD+T9q>yr7-d>mb;j&rCm^Y0`1}>QOMxk zty>6td3eLSrqrja*`0YMl*z5lX({XEJz23&)#(`cyt8P`s;*qdRxasac-+j0vz_?! z?{OhVCy_ShM7~Kb!dNZWi=9(jWjQjEyppxeHZC)J%;~%~+4R29B#q(gIsUGb$!3y! zE3j=qXPd9O`ymIjC)FCpj66ytGvj+pZ(pUAYrxRK0oBhT{$Ii$;V02g<;^mu9c-8f z2zl*e_sH?sIy}ZYv@X`<8ql&eINRQ#3+|oZf!-up=#Syvb-z=M4yeDwsbfp`oSY~9 zKpmLtb==XB7=T`Its|U?ax4Y4=wKiLN zQ>H`W6(H`zrlj3t>)awc^%Y+NDL)gVIO_P@)2*g*NU(3n4d$WVSxKuuZ!oM$%L{#% zm9swW-aF-HD_QOfH7I=!S8j)`#gjt$$B#2mHybQeX6p> zjT+(vT&|>4tcTfrW4Q?E)p;2Z{PDd6^5u>t8PT1>J*r=-! z<6ODOycu^#59``w=XVc_(r!_$Vg@|Z+}Fahc8~y_AjU# zH;TlTkFS)G9%ph2yZHLaTKh7G=Cki#{#>bcd__{-!OJ0>60uoWu2k7uz-FdGwc6N5 zrKPUkV)&aNx~Y0AYLJNA4LLlXt%a4dNaC^5mYn|{J5eY$mLJnn{x|eWLoEt*PP?df zq`!nIT-a)r{at!orK^(V_yW%JLnb5Yt~;1i3_F57}YtK3iCl0hM!n zaDF@wPO`d;E%F=1y9*K|^;j(W{}m{pQ=*5W|4;BGd;gyeZUs3o2;}_#&!X$g9RRNb z6W~7J_2~P*4xR+A2H!#Fza5l72K;Yy`(Fh$Aa?+M8J+%hpb8!azKu@*8Sp;vGO!Kg zp1)D>ef0ZxgAFhZt^yxHr+*H(7JLrf{m;Rlf*ZkC(bGQ)ZU-6gQ{YbY^$y5`aj+lU z2mC#H``du{?VkaU0ph3sQSc=2XmDTfbz4Ul`p6vtQ6Gyz!vFe&TA!{xo1B|ZC(oou z#%8nbOzlmfH&)la5LRaibq)PGf#T`yN8XJ5eC>U6QN+L3Wed zQc~m7Nptf^;OOQRmBk#dhh{Y&|0Ege&v`YOl)ZG>Y;Io#UlELZX7>UNVybW87I*Xg0TnXq&> z-K`f-XGceU`>Sa?alf_%b^FN5ETvtoc6|?0`+s01Mzo@MGXh=>K(ewt$aF-@_*GLGVT(=lCsvYe5{yy8l07ACNQrw!j#8H24g*ftLe0vrq01JOmyF z?hU?*jo`1qtH5)?lYsaD{497Swt{n@0LFpbD=0MmNEe$ylr7=>pUXht{RlrWpcyUf zK~9x;_C7ca@AgTTrd0=Lr6ITzPEt^sV|FH)IU{>z=luOe0z~MHKBK9B9wXkd`=BUGD!UBInlcrMvx4&eq*qpBGm0=f{a zrvc1ujq&8%$(|d-ToCh9DPr^+c^e>{R_MeTLU<%hK8YkBXVbm))BJBB_3nouc#{wU zhFGPCgAsHZyOu6cGQ}{`4CV?;al*$G$dVk3eAWi^&}+XTzNdl(3Z?Jy)p7N=ltvbG zT5AE*wGLoz^59CG4lT)zY_%I`zNKbkxy(Lb3W7fb{s^;M^|~`1=?LUC$W+6G7npoP@Cv<@(1`H2HqxST4)o10FY1ji;++VTF!KmJLwE&N)RhpJWUyvvrgX-%aNB_@Yj zL#;ZM)iN`y(Vmi<<_M{IG)+8_v7s94VBMAgT?WHVAc^nFdlG0b`5277l83Qy(kQBc zqh*{2LT61Vo>bhZ_^D@RjGo?x_By?B{k&n);;E^*1D(Jvd6@L(Htp7<5#JY-D~V=y z@rm#))=5jrXK!gsj6lKlICc22ytF>n_@vBjK^F@h#GJ3ZjjETt6XxhiH;{m#1sAB| z@s!|Kcs{}kM zw8CrSlA7upvRvZ!3auci)|A1dPXfxvUsh9V_(NE+BE`pWk~)HXcOiki?j}rLT5?ES zGHMBv_&;XmlrR^-Yd?x52hsl@jlx;C_5U<~KMS2-&i=a&><3>(=l^Tb`@t>Xi68^y zF2Mf*{t!GL6v4;Q^OwO9a0U1t`u*p?d%*920{A)bMfCdL0xRGI7z95C{vEykPVfg{ z9`u9zfN!ANKN)1fQ6Rd$+zt3@PyoZ=ztHL541Ni0f>{s)-$Jh!UH^mNNuU6-U?2E9 z^!itUUk6Pv3LXO<3jQ1T0J{A%zy!EI_z!gZ+rbcc2>3p96WY~!()0aHWc~7q23`EG z0{+!oD=X^!TbzVgYdVZub*0S^EKWoW>oK|UQBE3}u|o=U z-khyxja63rO{e`K>SGKWZ*12^ZSmX1%5D4ioGiL`J2TKaVkBa%OckMJQ>L73F>RIQ z@cL%L>)mZ?gy>oulXEr-U@Hjj6wt{>7sj{C!6af!R04UL7(LK?dlBu-94xm3mz(in zqsXNX!SSc#zd#MgbLAlE$w}maK3xUreNc=n zFw>n(Othy)6JiHMZnNWy;%a{pBDOC`lB#{3BO!A$7ol~J?X`8UG3rYZMm}}pPQ+<2 zjTLp+pJD6?P|j1~Fh}?rIP8kj-ehkPy0NC42&MTUfI zqpzD8iOG*dosm3TfeYoU?k8#qf91{?1+2Y{?N-sv?-IYh{VjFe5tFs=d zWuSgGpRj~>!D5e+W&#cDvHW?DLY21ge)iNZ5;3})95r!Xpo%$#lZtU#3X z*^#Q!#%&F1kO|c`pf&YL_TG=Vwq3@3&$!i9=ax*&iARxAD$qsrVl$|Hl|b||?!@$x ztoP@pl4r)IvvV-$-n4zzeYy>XdlI0{l@E3#bAiL%s;m4PNHi#!g;Nt!J4du~tKP6W zYL?CC(s8oOa;ieHZC#+-=jE2@MvdT@=m_#AQ0|D<3m0Fds;^3rAKgBNJ*MYpJN_C112|Zni_l2R05XUyr$)p@LRm{BwaPH$4G}a1zSa z+;yYIEl3~a?zsaiSo)F;7o+sBm3GZfN7#FjQ zp5#JMA(1i0t_xV^+@qR8@-pTVSu%;SCvvDPWNnd|YR=l&>u0q&%o)z zP3N=m&)1uM3tWR7Y;G>ENk;B&o)rCGJ~`1z+5bPo*9JQO3>XID|KAVZgueeYFbf_G zzJ;DIcL07CyaddEdx93a{@2m%KLy?oUIm^2hQQ_E$H2$X@oxvO1k2zEkh1{p4a5gP zbpIEC6>t(<1CD{OqvL-ZycfI&{1T{wQ{YB$Igs-K-T;0JEP#FBGVmSrf4TQh&H{WE z_+_vJ9u58+-9HC@fUds^{sF!I$w1Bp_#Qg^`@x@p=YbAb1uI|#+!MSP+C2rV0HLFB zj`w5k4P9pBy=~#}W+i`fG9A*ebqTy)K8)2Gn=miyLXG8hJVnzDP6o-IEjPn_WVjWy z+x5}G+*O~|7Y|#PxA!c_nF%F1L=a179vx9a1P0v5)e@bWeEWKzRtpRo%N}h3I*YEt zh7RN_L!@wIIpfLE3Y$t^RCbrB0YWEDB)Q;a0s}_5nN-IdHG;d9#k%3Y1x7NktT#hq ztvMave=v58Ya|2D^Q=gBxe7*?L4WsB7OsYwZ zZW{uXZrf)H@0L-e?#;=h3I&sp?5LbRS|Qiua3`+s8S*)z>PY4x#Qap^>{QcOw3wA;7(|PM} za~Yz9PpMijT|KZ-rN>;m)I2aN?P9s_rHE0wq1_MkLjLZC{Jm39bRbOHR+A>nYkdo}~-LmV30ml-fZ>H;6_cT|n7v}0F4MYe7 z^0-G?pqCQ-5M_WKi__!W-(za-oG&`2VOAIJ+1E>A7k#YiCDW+UNBW0v5|V&Xr)NuG z`2;&u*IO8cF2TV=8=bBDd6i7;aH%gWckC^BC0Nb0T#z?7ya!34%SgWxJ;(XW-KbBh zxmB$N5NljEKzn?b@oe*zy%=$7rMSTLxPeFX{}?*|_2{jl|Bv$ZY4rWy1#94Ez;B@M zUjgKte>v-~1#SW-!F$p7N5TEUpP}172TX!TgYTis-wA#j+y-jkI`AMMd-+q~k>CN~ zpV8gl1)d8A!6U&p(cA9;uLjQqqR(Fk_JcV1Ji5E=@0YXv-vY$%Uvzp|>put%fcK-< zKMxea=g{r{6g(f?0)7(wD>{A^41hPH%U=ax3py}UMgdW`Qz3tI_D!aER7cuh#Kcvj1mZsYOP-@Pe$_vR{iN=q+$ugAN zA~G_KbE)U!ZVHR^y17)`z1|S&a7Z-Q_~_O}iPLw54jVSgN*TM3uc2}{4?1IwMzh4} zW}3h48*3R^l?tY-@BKE*ClaE|_$sgWG+{^t`SfOB@tb%G^^Q}c7>5ROmP(_ZAgRWN ztU=3(;{_)`L3-S;Cicn)q7D60yOax0{ErK#`Qq{nK-ehO;xuT6VZHcGUoRZ)npZ;O`4lzFr zG^o>IS>0-?2`nC&ccQh{*s7LP zta98_ir63y#DmnQL z7Am<89diq7OJe#>JibzG6x#b^@lIhI!4F4(_FBSwnlz&5Py#=LgG|$Q&_hFV?nWr+ zRRlfC4!mBu+syOAH(mH%UQ1DLh*iS*$V;2(n9*Ffd8j_*Av^8irLbNZj3B$IWhEn1 z64Jh|0ngHRnuU&B98$JS#%SRM?h_%;gA93%4MduDqiG*}tCxzpEuSbE$c+ghoD>s< zQprj$F1H!zHnz1XIU1Y{ye}-d)bPUAwTNM8O{u&pg*PqAF;eGJAZH=PDhLjVx)^bm z$0~;8L{79=D^?+uf$R9XK6d0P^~Zr5q;nbimMVZ#bK?1C7{(Rds>x2d6(2O^E8J}J z(jgAu5&a+4zHh?T|5N<^33UE0{+|LL0dEFk7gz^ba03t@fDdB}cs|I3t&IxE}O_ze4vHAOEkQ_se~Lw}2;t z40sTD19pIU@EGt-X!9u`XZbx72(6O9{RndeKNn&%lkVJ0{D7e^SOoJ}V}2@ewTmLX z1>WK&s%o;{uCzPRV~!g}kM}0F^_DBnnM&LtjaGu!4+jwdL%~toXKBPvV|Rhi6u42v2};p{>KL@NX@dDsCoq zmx10KL8{mbJ2*Caty=1#HNv1Q>B^^bkxZ6- zQL|mP?P+1ssQ)A)y<~+37h$zo3eG6ww*eS!9%h0>@Sc=zPc|{fTzG-2-4W$6v`_aT zSt<~1F-0v5*;$Xru96#UO#Heh(n(QGz0bDs8Ba`>ID0dNsL-S3_I9~kpRl_yTjSY` zEf-72kEp7cMZ*A}J1u7peV*(sH8PV;-gIeYc^&*5a7L+wy-Z;)t2ds(9aPgvwoSAf z4NIc7d^1G>PKc-_HaEOA&sle}>cLU#s|PswrDMJ7U~lM;?eL?|o2~b69~WpNVPxoD zeK?n=YZ-^aJh%ot1biD?z^A}F!ArqYKmm+{p9KGkUEnXko52gg^TDryr-B*qSnvoS zc7qRrJHS(b>=`%&4uVI3?_(p7I|SvtfOms8fTw{|;Njq_*bCkXo(*mSi(mnaf_sBM z$8I3|2L1?4gD+w;_!#&#@J#Sza2wbFSAuV2L-;KC1b8WUHh2mc1qtx;;7iySJ`O$v zUI$(b#P{GVSO%xTA~*sb0pzTK2Z9HHFJObX1H2u`J%vvPYe4K1<6u7!JH@@hhp^U8PXKcNz_mcy^eaX?g-l)h?!wE%_3e_H*HnI8_QzCO>ZN-Xv2tLs@8a}Mm;UZ& ziCV_Yc9DC`7qRr3dW6}f*XX9Z#O=$6^{IUv@RzL1^|gvFas9aFAxWPQ*Ui$VMIfSg zxa*#UP&tsKo491foX+N6j{!y+HISXPUZPWySpGDEvauww2V%N|nqnyLEz}-k>F!zX zffILQzCe*eYdvbA)7je@xRiNsiF<9mS|=5Qne|+m-Sy+WC0ssRuD27LIC!%??uM9i zyLDnl9wm~Qah+cHifrzFmeYq^&P;*ydpY_`G{zsR#-%eBq6?~VtRfwofU z?YS1qu>NQ5{j=<$xk8gRfh^9!vZ2JhOKi$|I#+DczrFLVzgzl$Nw%t&Ytv#YQLM5z z&>LUE$b7nsJWokyFw?eJ52(vAWel|;Gg~-wX9U|WFR$U2!0&ii4tV_I>vQzGP3$(I z11+Rzp^-}*s}`LU7uU*lDVrk%G8#17ElIMa`@hsuK2CvD5{0I^7%5yL=1)U;q%4}x z5eps8)|q&RC9CT)`pEh}>TcgjTmPTt?|(t(KL=Jo7F-G5j-I~)PJmmUv80X~9${wA;mP5{~4-vAE*;{X42 zAnW@7f!_TW;B{aPh=2dzplAO!crp+l|0Cct=+CbPF91&k8{ibU54y`G>~=jchyd+H=4 zcbJyo(r)?SNE17pk-P~?-8!^<2lDN9;gWIe zkXCT+pi&Y8BBCCc)jW^*92#*XmV2$1x9xP3&iupJR(gJuj{VYHFgeO4i;C z*>k#Pnwy_W?R;aV@0^sONS{!N=b4<{H4SxEe7xGIui_jS^a`|(OqIx{Pk|j^Ia=han3A_6-X5JE+YGYjpqYa5d+X4rw z;SQxv@#scl?>v=js1q4vkK};Zph6>3sZnq1HnakVgq__=>P(#W(I(cSn4T%EL=9uM zPBt)6+9mGopu$|kKAXZlfkGrq_soh-{zNX;CuBsmqL9oEx|@HTo0I&d8iNd&H9eCf zFM_hM)V3@0n|Q$HXya8HlAwu`X=l8jBSuEpJcv$fLa>gG<1V{j6U zEiAdsO1)jJb3!}%oZ=))xU)LY?wXWDLo5_N6v<61Rfe`P&&plKSyR*4+<5o9Ib(N9 zdC6ncId$uJzhzNhwjG%mP>0)N){>;ifc?@(_ZSydd63Iz`}@%W`dj_``*a!fx1r6# z%8r>6x=G5CJfiKc9yGE`Og6|c2GllX?`V_@jT&s5<+ByeHZ!uYw9xLvF-DF1$)W_? zu=myl%DDa!rMElLI2B6{R5|GAmP4XKS{>N3RVu@!q3;U)Z&ms~YI@&Kiw?{B|8c(l z41K={lHdS%DEK(KzO4T*fidts^!=BCO>hw07yKOwy$5Uq(f$7ueg7Z9pMyG>2M+^( zjn4lfAZPxMfp4Mn|0Z|@kaPVX4qlDE{{rwBa3^~H?}4X*IdB8G3_J&2|0WOzpG2>J z1(*X@fbXHt%bEQz1(To;yaV0+h2R!Y28Y0JQ}3&R)c;{Z1N$S?F@3s>ZNh(AIx)9` z@H=C^eNs+PZ+FkTG48AKmL}ox#@1P$&f{2eR^7*&uGCelOMZ9tacMmmiu=4p*MFM_ z40#(RN$8mJz3Zks38bYJOS=hbb8=&H*x_H|c|YO>Wm!VC8AbLRRb|y5 z(j}Shu5IVHD^K`rU-yJrQ*W@?h{e);MZDB7x&d|@wFA|3^HC*P z!_>spFzhvp4Mtw!B=JlFZufIiC6?*qAG0ybvO%sa7rL7Sb)CR&Yau$E{`OTrA5>`IR#N<1IPDprP-*dr|u!p#=XCiyYQN!w8z;ZXD?mpGV1SWwlbvS zTgA~S$ahzjMgoKrGi~*jkov<|=o@is4e7+EmDnZ&rQv11t4t@fndsphO-B4Vd*vSi z#2iBfNKA~Rrjz4+y2Re^XtJ6UBva2VN?jkz>5&2PNGE{o+BT2TYF_E3X(K$gdSln_ z6IW>c)0?RL-Bj~hgB3aJFmIil?m)BVx=GYts%EW=nbQ#Z__N0pAIje}E_NNw{4>ZN zrT#AN(a|HuE;6huq1t+cC>Z7&NQA7$^Bj+0-S7>lBH@B%kG7~!2Yl9mNK_y54~5#HuYcO zglLwEe$zdk<}cp>(5Q?1Wz<2z;sFvddh67rp4JHg3uQd~ne9;v2NHwBBI9^;MGhN~ zs>=GmsJ(~eAN2nTzP^gS{}u3B@ERcd0L}n83*a8$W$6FE4%Wa?@NjSs@R!&C-VDSp zFb3`g-j5yNh2R!Y0fRv92M~Y%+dvVV0&+LNORxnLz?I-%um#)+-T~eYZUi60F7Vet z&ix+%e~E42`QQ||FZc{L0r3y`C=maEf5I;CM_?PIz(c`zunl|xd>*_BoB;Qdzp)R< zIe`C;O`r|r4!?haCLacW3>1AdjZNR`m=OC^3WxGH*k?TG#l*sL%YWjdErjkz4p1|9 zM1XwMoGm5kI=kqic4txv^+RF9YofZBF6WPqj8X!VT=zI-RLBrujJg**ZkGVT^Gklm>!!|V- zuQ`_7OlF4Yqo;fwPz2H4ObI^UVxMa1IzT)F0E9Q#Fcf4r3pT zZDWv+l~^~9-MqzIg-N|x!l{=-J*KwQZZ-Qs+rAajXk3ssWAjLRRuY#U7CRo{*V3|% ziIZuum0ig++H>VHhAoMsEE9%a(s zh0q*_EX}bmSTr@}7&jdB+H4}8gp#!ejzB3q;vcAofw%*1=?)e^s)>ccy9dPz+NiR>^m?uOvsXh8?BF^U^dq@4ZoexI~o>eIaZh zjk3=~4_p^Sn-fd8iKG`ym+qT~q*~|6W*37ZKHG;391OTuT`iM9FSOo8Kr@pr!m1VO*8kuYB*>>T0Z~kbGoZXYy<`X=ah71SC2D-n~ V9EJhk(CtXm*{|XEtuoIT{~yedz0Uvu literal 0 HcmV?d00001 diff --git a/src/main/java/com/jelly/farmhelperv2/feature/impl/.ProfitCalculator.java.swp b/src/main/java/com/jelly/farmhelperv2/feature/impl/.ProfitCalculator.java.swp deleted file mode 100644 index e1e4aebe85b17d463ae1d67acd62589788fbbb5e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36864 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 diff --git a/src/main/java/com/jelly/farmhelperv2/feature/impl/PestsDestroyer.java b/src/main/java/com/jelly/farmhelperv2/feature/impl/PestsDestroyer.java index fbe6e9b8..917df84b 100644 --- a/src/main/java/com/jelly/farmhelperv2/feature/impl/PestsDestroyer.java +++ b/src/main/java/com/jelly/farmhelperv2/feature/impl/PestsDestroyer.java @@ -162,6 +162,9 @@ public void start() { MacroHandler.getInstance().pauseMacro(); // MacroHandler.getInstance().getCurrentMacro().ifPresent(am -> am.setSavedState(Optional.empty())); KeyBindUtils.stopMovement(); + if (FarmHelperConfig.profitCalcCountPestDrop) { + MacroHandler.getInstance().getMacroingTimer().resume(); + } } escapeState = EscapeState.NONE; rotationState = RotationState.NONE; @@ -1195,6 +1198,9 @@ private void finishMacro() { stop(); MacroHandler.getInstance().triggerWarpGarden(true, true, false); delayClock.schedule(2_000 + Math.random() * 500); + if (FarmHelperConfig.profitCalcCountPestDrop) { + MacroHandler.getInstance().getMacroingTimer().pause(); + } } else { stop(); } From 42a4dacbac854d42890894be4b98120f490d8149 Mon Sep 17 00:00:00 2001 From: Osama Date: Tue, 25 Feb 2025 11:23:24 +0600 Subject: [PATCH 10/10] Sorry .swp file --- .../feature/impl/.PestsDestroyer.java.swp | Bin 98304 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/main/java/com/jelly/farmhelperv2/feature/impl/.PestsDestroyer.java.swp diff --git a/src/main/java/com/jelly/farmhelperv2/feature/impl/.PestsDestroyer.java.swp b/src/main/java/com/jelly/farmhelperv2/feature/impl/.PestsDestroyer.java.swp deleted file mode 100644 index 57deea9b925bb011ac7fe3fca647c4609fa2bb9c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 98304 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
9@9c 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 V9EJhk(CtXm*{|XEtuoIT{~yedz0Uvu