diff --git a/src/main/java/net/runelite/client/plugins/microbot/leaguestoolkit/AntiAfkMethod.java b/src/main/java/net/runelite/client/plugins/microbot/leaguestoolkit/AntiAfkMethod.java new file mode 100644 index 0000000000..29763dc22d --- /dev/null +++ b/src/main/java/net/runelite/client/plugins/microbot/leaguestoolkit/AntiAfkMethod.java @@ -0,0 +1,7 @@ +package net.runelite.client.plugins.microbot.leaguestoolkit; + +public enum AntiAfkMethod { + RANDOM_ARROW_KEY, + BACKSPACE, + CAMERA_ROTATION +} diff --git a/src/main/java/net/runelite/client/plugins/microbot/leaguestoolkit/LeaguesToolkitConfig.java b/src/main/java/net/runelite/client/plugins/microbot/leaguestoolkit/LeaguesToolkitConfig.java new file mode 100644 index 0000000000..0e6dbc4fb3 --- /dev/null +++ b/src/main/java/net/runelite/client/plugins/microbot/leaguestoolkit/LeaguesToolkitConfig.java @@ -0,0 +1,69 @@ +package net.runelite.client.plugins.microbot.leaguestoolkit; + +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigInformation; +import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.ConfigSection; +import net.runelite.client.config.Range; + +@ConfigGroup("LeaguesToolkit") +@ConfigInformation("
A grab-bag of Leagues-focused utilities. Start with Anti-AFK to keep long, " + + "auto-banking skilling sessions from getting logged out.
") +public interface LeaguesToolkitConfig extends Config { + + @ConfigSection( + name = "Anti-AFK", + description = "Prevents the idle-timeout logout during long AFK sessions", + position = 0 + ) + String antiAfkSection = "antiAfkSection"; + + @ConfigItem( + keyName = "enableAntiAfk", + name = "Enable anti-AFK", + description = "Periodically triggers input to reset the idle timer so you never get logged out", + position = 0, + section = antiAfkSection + ) + default boolean enableAntiAfk() { + return true; + } + + @ConfigItem( + keyName = "antiAfkMethod", + name = "Input method", + description = "What kind of input to send. Random arrow keys look most natural.", + position = 1, + section = antiAfkSection + ) + default AntiAfkMethod antiAfkMethod() { + return AntiAfkMethod.RANDOM_ARROW_KEY; + } + + @Range(min = 50, max = 5000) + @ConfigItem( + keyName = "antiAfkBufferMin", + name = "Trigger buffer min (ticks)", + description = "Minimum ticks before the client's AFK threshold at which to fire input", + position = 2, + section = antiAfkSection + ) + default int antiAfkBufferMin() { + return 500; + } + + @Range(min = 50, max = 5000) + @ConfigItem( + keyName = "antiAfkBufferMax", + name = "Trigger buffer max (ticks)", + description = "Maximum ticks before the client's AFK threshold at which to fire input", + position = 3, + section = antiAfkSection + ) + default int antiAfkBufferMax() { + return 1500; + } +} diff --git a/src/main/java/net/runelite/client/plugins/microbot/leaguestoolkit/LeaguesToolkitPlugin.java b/src/main/java/net/runelite/client/plugins/microbot/leaguestoolkit/LeaguesToolkitPlugin.java new file mode 100644 index 0000000000..bbec460109 --- /dev/null +++ b/src/main/java/net/runelite/client/plugins/microbot/leaguestoolkit/LeaguesToolkitPlugin.java @@ -0,0 +1,45 @@ +package net.runelite.client.plugins.microbot.leaguestoolkit; + +import com.google.inject.Provides; +import lombok.extern.slf4j.Slf4j; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.microbot.PluginConstants; + +import javax.inject.Inject; + +@PluginDescriptor( + name = PluginConstants.DV + "Leagues Toolkit", + description = "Quality-of-life utilities for Leagues (anti-AFK, and more to come)", + tags = {"leagues", "microbot", "utility", "afk"}, + version = LeaguesToolkitPlugin.version, + minClientVersion = "2.0.13", + enabledByDefault = PluginConstants.DEFAULT_ENABLED, + isExternal = PluginConstants.IS_EXTERNAL +) +@Slf4j +public class LeaguesToolkitPlugin extends Plugin { + public static final String version = "1.0.0"; + + @Inject + private LeaguesToolkitConfig config; + + @Inject + private LeaguesToolkitScript leaguesToolkitScript; + + @Provides + LeaguesToolkitConfig provideConfig(ConfigManager configManager) { + return configManager.getConfig(LeaguesToolkitConfig.class); + } + + @Override + protected void startUp() { + leaguesToolkitScript.run(config); + } + + @Override + protected void shutDown() { + leaguesToolkitScript.shutdown(); + } +} diff --git a/src/main/java/net/runelite/client/plugins/microbot/leaguestoolkit/LeaguesToolkitScript.java b/src/main/java/net/runelite/client/plugins/microbot/leaguestoolkit/LeaguesToolkitScript.java new file mode 100644 index 0000000000..fafd6f3760 --- /dev/null +++ b/src/main/java/net/runelite/client/plugins/microbot/leaguestoolkit/LeaguesToolkitScript.java @@ -0,0 +1,62 @@ +package net.runelite.client.plugins.microbot.leaguestoolkit; + +import lombok.extern.slf4j.Slf4j; +import net.runelite.client.plugins.microbot.Microbot; +import net.runelite.client.plugins.microbot.Script; +import net.runelite.client.plugins.microbot.util.camera.Rs2Camera; +import net.runelite.client.plugins.microbot.util.keyboard.Rs2Keyboard; +import net.runelite.client.plugins.microbot.util.math.Rs2Random; +import net.runelite.client.plugins.microbot.util.player.Rs2Player; + +import java.awt.event.KeyEvent; +import java.util.concurrent.TimeUnit; + +@Slf4j +public class LeaguesToolkitScript extends Script { + + private static final int[] ARROW_KEYS = { + KeyEvent.VK_LEFT, KeyEvent.VK_RIGHT, KeyEvent.VK_UP, KeyEvent.VK_DOWN + }; + + public boolean run(LeaguesToolkitConfig config) { + mainScheduledFuture = scheduledExecutorService.scheduleWithFixedDelay(() -> { + try { + if (!super.run()) return; + if (!Microbot.isLoggedIn()) return; + + if (config.enableAntiAfk()) { + runAntiAfk(config); + } + } catch (Exception ex) { + log.error("LeaguesToolkitScript loop error", ex); + } + }, 0, 1000, TimeUnit.MILLISECONDS); + return true; + } + + private void runAntiAfk(LeaguesToolkitConfig config) { + int minBuffer = Math.min(config.antiAfkBufferMin(), config.antiAfkBufferMax()); + int maxBuffer = Math.max(config.antiAfkBufferMin(), config.antiAfkBufferMax()); + long buffer = Rs2Random.between(minBuffer, maxBuffer); + + if (!Rs2Player.checkIdleLogout(buffer)) return; + + switch (config.antiAfkMethod()) { + case BACKSPACE: + Rs2Keyboard.keyPress(KeyEvent.VK_BACK_SPACE); + break; + case CAMERA_ROTATION: + Rs2Camera.setYaw(Rs2Random.between(0, 2047)); + break; + case RANDOM_ARROW_KEY: + default: + Rs2Keyboard.keyPress(ARROW_KEYS[Rs2Random.between(0, ARROW_KEYS.length - 1)]); + break; + } + } + + @Override + public void shutdown() { + super.shutdown(); + } +} diff --git a/src/main/resources/net/runelite/client/plugins/microbot/leaguestoolkit/docs/README.md b/src/main/resources/net/runelite/client/plugins/microbot/leaguestoolkit/docs/README.md new file mode 100644 index 0000000000..224c1e9d6e --- /dev/null +++ b/src/main/resources/net/runelite/client/plugins/microbot/leaguestoolkit/docs/README.md @@ -0,0 +1,16 @@ +# Leagues Toolkit + +Quality-of-life utilities for OSRS Leagues. + +## Features + +### Anti-AFK +Prevents the idle-timeout logout during long AFK skilling sessions (e.g. mining with the auto-bank relic where inventory never fills and no interaction happens between rock respawns). Periodically triggers a configurable input right before the client's AFK threshold so the session stays alive indefinitely. + +Configurable: +- **Input method** — random arrow key (default, most natural), backspace, or camera yaw rotation +- **Trigger buffer min/max** — how many ticks before the idle-timeout to fire input (randomized between min and max) + +## Roadmap + +More Leagues-focused utilities planned. Open an issue or PR with ideas.