From 5c943675845d95ff582441f1ff699bfd4ba717ae Mon Sep 17 00:00:00 2001 From: Caleb Burke Date: Sat, 4 Jul 2026 18:12:16 -0700 Subject: [PATCH] healthcheck func impl --- src/client/java/skybot/SkybotClient.java | 42 +++++++++++++++++++ .../java/skybot/farmers/CarrotFarmer.java | 12 ++++++ src/client/java/skybot/farmers/Farmer.java | 5 +++ .../java/skybot/farmers/NetherwartFarmer.java | 12 ++++++ .../java/skybot/farmers/PotatoFarmer.java | 12 ++++++ .../java/skybot/farmers/WheatFarmer.java | 12 ++++++ 6 files changed, 95 insertions(+) diff --git a/src/client/java/skybot/SkybotClient.java b/src/client/java/skybot/SkybotClient.java index b71403b..c8a3506 100644 --- a/src/client/java/skybot/SkybotClient.java +++ b/src/client/java/skybot/SkybotClient.java @@ -6,10 +6,12 @@ import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderEvents; +import net.fabricmc.fabric.api.event.client.player.ClientPlayerBlockBreakEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.option.KeyBinding; import net.minecraft.client.util.InputUtil; import net.minecraft.util.Identifier; +import net.minecraft.util.math.Vec3d; import org.lwjgl.glfw.GLFW; import skybot.commands.CommandManager; @@ -24,6 +26,15 @@ public class SkybotClient implements ClientModInitializer { private static volatile Farmer activeFarmer = null; private static volatile boolean botEnabled = false; + private static long tickCount = 0; + private static final long HEALTHCHECK_INTERVAL_TICKS = 40; + + private static volatile long lastBreakTime = 0; + + private static volatile long lastMoveTime = 0; + private static Vec3d lastPosition = null; + private static final double MOVE_EPSILON_SQUARED = 1.0; + private static final KeyBinding.Category GENERAL_CATEGORY = KeyBinding.Category .create(Identifier.of("skybot", "general")); @@ -37,6 +48,14 @@ public class SkybotClient implements ClientModInitializer { return botEnabled; } + public static long getLastBreakTime() { + return lastBreakTime; + } + + public static long getLastMoveTime() { + return lastMoveTime; + } + public static String botStatus() { if (!botEnabled) { return "§cIdle"; @@ -62,6 +81,9 @@ public class SkybotClient implements ClientModInitializer { activeFarmer = strategy; botEnabled = true; + lastBreakTime = System.currentTimeMillis(); + lastMoveTime = System.currentTimeMillis(); + lastPosition = null; activeFarmer.enqueue(TASK_QUEUE); ChatMenu.send("§aFarmer started successfully.§r"); @@ -72,6 +94,9 @@ public class SkybotClient implements ClientModInitializer { public void onInitializeClient() { KeyBindingHelper.registerKeyBinding(STOP_KEY); + ClientPlayerBlockBreakEvents.AFTER + .register((world, player, pos, state) -> lastBreakTime = System.currentTimeMillis()); + WorldRenderEvents.END_MAIN.register(context -> { MinecraftClient client = MinecraftClient.getInstance(); if (client.world != null && !client.isPaused()) { @@ -91,12 +116,29 @@ public class SkybotClient implements ClientModInitializer { if (client.world != null && !client.isPaused()) { Controller.tick(client); + if (client.player != null) { + Vec3d pos = client.player.getEntityPos(); + if (lastPosition == null) { + lastPosition = pos; + lastMoveTime = System.currentTimeMillis(); + } else if (lastPosition.squaredDistanceTo(pos) > MOVE_EPSILON_SQUARED) { + lastMoveTime = System.currentTimeMillis(); + lastPosition = pos; + } + } + while (STOP_KEY.wasPressed()) { if (botEnabled) { ChatMenu.send("§cBot stopped via hotkey.§r"); stopBot(); } } + + tickCount++; + if (botEnabled && tickCount % HEALTHCHECK_INTERVAL_TICKS == 0 && !activeFarmer.healthcheck()) { + ChatMenu.send("§cHealthcheck failed, stopping bot.§r"); + stopBot(); + } } }); diff --git a/src/client/java/skybot/farmers/CarrotFarmer.java b/src/client/java/skybot/farmers/CarrotFarmer.java index 96d533d..4afa966 100644 --- a/src/client/java/skybot/farmers/CarrotFarmer.java +++ b/src/client/java/skybot/farmers/CarrotFarmer.java @@ -1,5 +1,6 @@ package skybot.farmers; +import skybot.SkybotClient; import skybot.controller.Controller; import skybot.task.HoldKeyTask; import skybot.task.PressButtonTask; @@ -9,6 +10,17 @@ import skybot.task.TaskQueue; public class CarrotFarmer implements Farmer { + private static final long HEALTHCHECK_TIMEOUT_MILLIS = 4500; + private static final long MOVEMENT_TIMEOUT_MILLIS = 5000; + + @Override + public boolean healthcheck() { + long now = System.currentTimeMillis(); + boolean brokeRecently = now - SkybotClient.getLastBreakTime() < HEALTHCHECK_TIMEOUT_MILLIS; + boolean movedRecently = now - SkybotClient.getLastMoveTime() < MOVEMENT_TIMEOUT_MILLIS; + return brokeRecently && movedRecently; + } + @Override public void enqueue(TaskQueue queue) { queue.clear(); diff --git a/src/client/java/skybot/farmers/Farmer.java b/src/client/java/skybot/farmers/Farmer.java index 3b910bc..019abd0 100644 --- a/src/client/java/skybot/farmers/Farmer.java +++ b/src/client/java/skybot/farmers/Farmer.java @@ -4,4 +4,9 @@ import skybot.task.TaskQueue; public interface Farmer { void enqueue(TaskQueue queue); + + /** Periodic sanity check while this farmer is running. Returning false stops the bot. */ + default boolean healthcheck() { + return true; + } } diff --git a/src/client/java/skybot/farmers/NetherwartFarmer.java b/src/client/java/skybot/farmers/NetherwartFarmer.java index c662457..e0e318a 100644 --- a/src/client/java/skybot/farmers/NetherwartFarmer.java +++ b/src/client/java/skybot/farmers/NetherwartFarmer.java @@ -1,5 +1,6 @@ package skybot.farmers; +import skybot.SkybotClient; import skybot.controller.Controller; import skybot.task.HoldKeyTask; import skybot.task.PressButtonTask; @@ -9,6 +10,17 @@ import skybot.task.TaskQueue; public class NetherwartFarmer implements Farmer { + private static final long HEALTHCHECK_TIMEOUT_MILLIS = 4500; + private static final long MOVEMENT_TIMEOUT_MILLIS = 5000; + + @Override + public boolean healthcheck() { + long now = System.currentTimeMillis(); + boolean brokeRecently = now - SkybotClient.getLastBreakTime() < HEALTHCHECK_TIMEOUT_MILLIS; + boolean movedRecently = now - SkybotClient.getLastMoveTime() < MOVEMENT_TIMEOUT_MILLIS; + return brokeRecently && movedRecently; + } + @Override public void enqueue(TaskQueue queue) { queue.clear(); diff --git a/src/client/java/skybot/farmers/PotatoFarmer.java b/src/client/java/skybot/farmers/PotatoFarmer.java index cacc220..f7ea27e 100644 --- a/src/client/java/skybot/farmers/PotatoFarmer.java +++ b/src/client/java/skybot/farmers/PotatoFarmer.java @@ -1,5 +1,6 @@ package skybot.farmers; +import skybot.SkybotClient; import skybot.controller.Controller; import skybot.task.HoldKeyTask; import skybot.task.PressButtonTask; @@ -9,6 +10,17 @@ import skybot.task.TaskQueue; public class PotatoFarmer implements Farmer { + private static final long HEALTHCHECK_TIMEOUT_MILLIS = 4500; + private static final long MOVEMENT_TIMEOUT_MILLIS = 5000; + + @Override + public boolean healthcheck() { + long now = System.currentTimeMillis(); + boolean brokeRecently = now - SkybotClient.getLastBreakTime() < HEALTHCHECK_TIMEOUT_MILLIS; + boolean movedRecently = now - SkybotClient.getLastMoveTime() < MOVEMENT_TIMEOUT_MILLIS; + return brokeRecently && movedRecently; + } + @Override public void enqueue(TaskQueue queue) { queue.clear(); diff --git a/src/client/java/skybot/farmers/WheatFarmer.java b/src/client/java/skybot/farmers/WheatFarmer.java index ea6a36d..48e3880 100644 --- a/src/client/java/skybot/farmers/WheatFarmer.java +++ b/src/client/java/skybot/farmers/WheatFarmer.java @@ -1,5 +1,6 @@ package skybot.farmers; +import skybot.SkybotClient; import skybot.controller.Controller; import skybot.task.HoldKeyTask; import skybot.task.PressButtonTask; @@ -9,6 +10,17 @@ import skybot.task.TaskQueue; public class WheatFarmer implements Farmer { + private static final long HEALTHCHECK_TIMEOUT_MILLIS = 4500; + private static final long MOVEMENT_TIMEOUT_MILLIS = 5000; + + @Override + public boolean healthcheck() { + long now = System.currentTimeMillis(); + boolean brokeRecently = now - SkybotClient.getLastBreakTime() < HEALTHCHECK_TIMEOUT_MILLIS; + boolean movedRecently = now - SkybotClient.getLastMoveTime() < MOVEMENT_TIMEOUT_MILLIS; + return brokeRecently && movedRecently; + } + @Override public void enqueue(TaskQueue queue) { queue.clear();