From 3515049ccdc580e103c4d4e099064c3dcbd43281 Mon Sep 17 00:00:00 2001 From: g-mason0 <19415334+g-mason0@users.noreply.github.com> Date: Thu, 2 Oct 2025 12:53:53 -0400 Subject: [PATCH 1/6] chore(shortest-path): add varbits for stronghold of security portal varbits --- .../microbot/shortestpath/teleportation_portals.tsv | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/microbot/shortestpath/teleportation_portals.tsv b/runelite-client/src/main/resources/net/runelite/client/plugins/microbot/shortestpath/teleportation_portals.tsv index 0f5c84c6f7a..71c42019479 100644 --- a/runelite-client/src/main/resources/net/runelite/client/plugins/microbot/shortestpath/teleportation_portals.tsv +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/microbot/shortestpath/teleportation_portals.tsv @@ -87,10 +87,10 @@ 3097 3508 1 3157 9818 0 Use;Clan Cup portal;27094 1 3157 9818 0 3097 3508 1 Use;Clan Cup portal;27095 1 2040 5240 0 2021 5223 0 Use;Portal;19005 1 -1863 5239 0 1914 5222 0 Use;Portal;20786 1 -2120 5257 0 2146 5287 0 Use;Portal;23707 1 -2119 5258 0 2146 5287 0 Use;Portal;23707 1 -2121 5258 0 2146 5287 0 Use;Portal;23707 1 +1863 5239 0 1914 5222 0 Use;Portal;20786 2309=1 1 +2120 5257 0 2146 5287 0 Use;Portal;23707 2310=1 1 +2119 5258 0 2146 5287 0 Use;Portal;23707 2311=1 1 +2121 5258 0 2146 5287 0 Use;Portal;23707 2312=1 1 2119 5258 0 2146 5287 0 Use;Portal;23707 1 2121 5258 0 2146 5287 0 Use;Portal;23707 1 2364 5212 0 2341 5219 0 Use;Portal;23922 1 From ec277772b7e42bc535330218674024c38989a10f Mon Sep 17 00:00:00 2001 From: g-mason0 <19415334+g-mason0@users.noreply.github.com> Date: Thu, 2 Oct 2025 13:07:05 -0400 Subject: [PATCH 2/6] fix(Rs2RunePouch): use new loadout widgets --- .../microbot/util/inventory/Rs2RunePouch.java | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/inventory/Rs2RunePouch.java b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/inventory/Rs2RunePouch.java index acf96baee99..2a1514ae6a8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/inventory/Rs2RunePouch.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/inventory/Rs2RunePouch.java @@ -1,7 +1,9 @@ package net.runelite.client.plugins.microbot.util.inventory; +import java.awt.Rectangle; import lombok.Getter; import lombok.Setter; +import net.runelite.api.MenuAction; import net.runelite.api.Varbits; import net.runelite.api.events.VarbitChanged; import net.runelite.api.events.WidgetLoaded; @@ -12,6 +14,8 @@ import net.runelite.client.plugins.microbot.util.Global; import net.runelite.client.plugins.microbot.util.bank.Rs2Bank; import net.runelite.client.plugins.microbot.util.magic.Runes; +import net.runelite.client.plugins.microbot.util.menu.NewMenuEntry; +import net.runelite.client.plugins.microbot.util.misc.Rs2UiHelper; import net.runelite.client.plugins.microbot.util.widget.Rs2Widget; import java.util.*; @@ -42,10 +46,10 @@ public class Rs2RunePouch }; private static final int BANK_PARENT_ID = InterfaceID.BANKSIDE; - private static final int RUNEPOUCH_ROOT_CHILD_ID = 19; - private static final int RUNEPOUCH_CLOSE_CHILD_ID = 22; - private static final int RUNEPOUCH_DEPOSIT_ALL_CHILD_ID = 20; - private static final List RUNEPOUCH_LOADOUT_WIDGETS = Arrays.asList(28, 30, 32, 34); + private static final int RUNEPOUCH_ROOT_CHILD_ID = 19; // Validated + private static final int RUNEPOUCH_CLOSE_CHILD_ID = 22; // Validated + private static final int RUNEPOUCH_DEPOSIT_ALL_CHILD_ID = 20; // Validated + private static final List RUNEPOUCH_LOADOUT_WIDGETS = Arrays.asList(34, 38, 41, 44, 46, 48, 50, 52, 54, 56); // New Loadout Child IDs @Getter private static final List slots = new ArrayList<>(); @@ -427,8 +431,12 @@ private static boolean coreLoad(Map requiredRunes) if (loadoutMap.equals(requiredRunes)) { - int widgetIndex = RUNEPOUCH_LOADOUT_WIDGETS.get(entry.getKey()); - Rs2Widget.clickWidget(BANK_PARENT_ID, (widgetIndex + 1)); + final int widgetIndex = RUNEPOUCH_LOADOUT_WIDGETS.get(entry.getKey()); + Widget parentLoadoutWidget = Rs2Widget.getWidget(BANK_PARENT_ID, widgetIndex); + Widget loadWidget = Rs2Widget.findWidget("Load", List.of(parentLoadoutWidget.getStaticChildren())); + Rectangle loadBounds = loadWidget.getBounds(); + NewMenuEntry menuEntry = new NewMenuEntry("Load", "", 1, MenuAction.CC_OP, -1, loadWidget.getId(), false); + Microbot.doInvoke(menuEntry, loadBounds != null && Rs2UiHelper.isRectangleWithinCanvas(loadBounds) ? loadBounds : Rs2UiHelper.getDefaultRectangle()); Global.sleepUntil(() -> getRunes().entrySet().stream().allMatch(e -> requiredRunes.getOrDefault(e.getKey(), 0) <= e.getValue())); return closeRunePouch(); } From 0770346a27ddd5297abca1e6e5bc7cd5630d85e7 Mon Sep 17 00:00:00 2001 From: g-mason0 <19415334+g-mason0@users.noreply.github.com> Date: Thu, 2 Oct 2025 13:43:32 -0400 Subject: [PATCH 3/6] chore(Rs2RunePouch): AI is actually stupid --- .../plugins/microbot/util/inventory/Rs2RunePouch.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/inventory/Rs2RunePouch.java b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/inventory/Rs2RunePouch.java index 2a1514ae6a8..bf69a4c4873 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/inventory/Rs2RunePouch.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/inventory/Rs2RunePouch.java @@ -433,7 +433,17 @@ private static boolean coreLoad(Map requiredRunes) { final int widgetIndex = RUNEPOUCH_LOADOUT_WIDGETS.get(entry.getKey()); Widget parentLoadoutWidget = Rs2Widget.getWidget(BANK_PARENT_ID, widgetIndex); + if (parentLoadoutWidget == null || parentLoadoutWidget.getStaticChildren() == null) + { + Microbot.log("Failed to find loadout widget for index: " + widgetIndex, Level.WARNING); + break; + } Widget loadWidget = Rs2Widget.findWidget("Load", List.of(parentLoadoutWidget.getStaticChildren())); + if (loadWidget == null) + { + Microbot.log("Failed to find 'Load' child widget in loadout index: " + widgetIndex, Level.WARNING); + break; + } Rectangle loadBounds = loadWidget.getBounds(); NewMenuEntry menuEntry = new NewMenuEntry("Load", "", 1, MenuAction.CC_OP, -1, loadWidget.getId(), false); Microbot.doInvoke(menuEntry, loadBounds != null && Rs2UiHelper.isRectangleWithinCanvas(loadBounds) ? loadBounds : Rs2UiHelper.getDefaultRectangle()); From 0faaa9288e4266fc81a04914bcfa9431050832f9 Mon Sep 17 00:00:00 2001 From: chsami Date: Sat, 4 Oct 2025 14:41:34 +0200 Subject: [PATCH 4/6] fix: remove deprecated --- .../runelite/client/plugins/microbot/util/walker/Rs2Walker.java | 1 - 1 file changed, 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/walker/Rs2Walker.java b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/walker/Rs2Walker.java index f92dece79c8..dc72d46cec4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/walker/Rs2Walker.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/walker/Rs2Walker.java @@ -2008,7 +2008,6 @@ public static boolean isInArea(WorldPoint... worldPoints) { * @param range an int of range to which the boundaries will be drawn in a square, * @return true if the player's current location is within the specified area, false otherwise */ - @Deprecated(since = "1.5.5", forRemoval = true) public static boolean isInArea(WorldPoint centerOfArea, int range) { WorldPoint seCorner = new WorldPoint(centerOfArea.getX() + range, centerOfArea.getY() - range, centerOfArea.getPlane()); WorldPoint nwCorner = new WorldPoint(centerOfArea.getX() - range, centerOfArea.getY() + range, centerOfArea.getPlane()); From 31469f453a278e63440551f7a9199dd87191b1e9 Mon Sep 17 00:00:00 2001 From: chsami Date: Sun, 5 Oct 2025 04:14:37 +0200 Subject: [PATCH 5/6] refactor: streamline keyboard event handling and improve focus management in Rs2Keyboard --- .../microbot/util/keyboard/Rs2Keyboard.java | 195 +++++++----------- 1 file changed, 74 insertions(+), 121 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/keyboard/Rs2Keyboard.java b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/keyboard/Rs2Keyboard.java index 1040b291402..9189db44a17 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/keyboard/Rs2Keyboard.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/keyboard/Rs2Keyboard.java @@ -3,172 +3,125 @@ import net.runelite.client.plugins.microbot.Microbot; import net.runelite.client.plugins.microbot.util.Global; +import javax.swing.*; import java.awt.*; import java.awt.event.KeyEvent; -import static java.awt.event.KeyEvent.CHAR_UNDEFINED; -import net.runelite.client.plugins.microbot.util.math.Rs2Random; - /** * Utility class for simulating keyboard input. */ -public class Rs2Keyboard -{ - +public final class Rs2Keyboard { /** - * Gets the current game canvas. - * - * @return the game canvas + * Private constructor to prevent instantiation. */ - private static Canvas getCanvas() - { - return Microbot.getClient().getCanvas(); - } + private Rs2Keyboard() {} /** - * Executes a given action with the canvas temporarily made focusable if it wasn't already. - * This ensures key events are properly dispatched to the game client. - * - * @param action the code to run while the canvas is focusable + * Get the game canvas. + * @return */ - private static void withFocusCanvas(Runnable action) - { - Canvas canvas = getCanvas(); - boolean originalFocus = canvas.isFocusable(); - if (!originalFocus) canvas.setFocusable(true); - - try - { - action.run(); - } - finally - { - if (!originalFocus) canvas.setFocusable(false); - } - } + private static Canvas canvas() { return Microbot.getClient().getCanvas(); } /** - * Dispatches a low-level KeyEvent to the canvas after a specified delay. - * - * @param id the KeyEvent type (e.g. KEY_TYPED, KEY_PRESSED, etc.) - * @param keyCode the key code from {@link KeyEvent} - * @param keyChar the character to type, if applicable - * @param delay the delay in milliseconds before the event time is set + * Run an action with the canvas focused, restoring previous focus state afterwards. + * @param action */ - private static void dispatchKeyEvent(int id, int keyCode, char keyChar, int delay) - { - KeyEvent event = new KeyEvent( - getCanvas(), - id, - System.currentTimeMillis() + delay, - 0, - keyCode, - keyChar - ); - getCanvas().dispatchEvent(event); + private static void withFocusedCanvas(Runnable action) { + Canvas c = canvas(); + boolean wasFocusable = c.isFocusable(); + boolean hadFocus = c.isFocusOwner(); + if (!wasFocusable) c.setFocusable(true); + if (!hadFocus) c.requestFocusInWindow(); + try { action.run(); } + finally { + if (!wasFocusable) c.setFocusable(false); + } } /** - * Types out a string character-by-character using KEY_TYPED events. - * Each character is sent with a short randomized delay and sleep between characters. - * - * @param word the string to type into the game + * Post an event to the AWT event queue. + * @param e */ - public static void typeString(final String word) - { - withFocusCanvas(() -> { - for (char c : word.toCharArray()) - { - int delay = Rs2Random.between(20, 200); - dispatchKeyEvent(KeyEvent.KEY_TYPED, KeyEvent.VK_UNDEFINED, c, delay); - Global.sleep(100, 200); - } - }); + private static void post(KeyEvent e) { + // Safe from any thread; posts into AWT event queue + Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(e); } /** - * Simulates pressing a single character using a KEY_TYPED event. - * - * @param key the character to press + * Fire a keyboard event on the canvas. + * @param id + * @param keyCode + * @param keyChar */ - public static void keyPress(final char key) - { - withFocusCanvas(() -> { - int delay = Rs2Random.between(20, 200); - dispatchKeyEvent(KeyEvent.KEY_TYPED, KeyEvent.VK_UNDEFINED, key, delay); - }); + private static void fire(int id, int keyCode, char keyChar) { + long now = System.currentTimeMillis(); + KeyEvent e = new KeyEvent(canvas(), id, now, 0, keyCode, keyChar); + if (SwingUtilities.isEventDispatchThread()) { + // Dispatch directly if on EDT + canvas().dispatchEvent(e); + } else { + post(e); + } } /** - * Simulates holding the Shift key using a KEY_PRESSED event. + * Type a string into the focused canvas, one character at a time. + * @param s */ - public static void holdShift() - { - withFocusCanvas(() -> { - int delay = Rs2Random.between(20, 200); - dispatchKeyEvent(KeyEvent.KEY_PRESSED, KeyEvent.VK_SHIFT, CHAR_UNDEFINED, delay); + public static void typeString(String s) { + withFocusedCanvas(() -> { + for (char ch : s.toCharArray()) { + // For printable characters, send TYPED only + fire(KeyEvent.KEY_TYPED, KeyEvent.VK_UNDEFINED, ch); + Global.sleep(30, 80); + } }); } /** - * Simulates releasing the Shift key using a KEY_RELEASED event. + * Hold a key down on the focused canvas. + * @param keyCode */ - public static void releaseShift() - { - withFocusCanvas(() -> { - int delay = Rs2Random.between(20, 200); - dispatchKeyEvent(KeyEvent.KEY_RELEASED, KeyEvent.VK_SHIFT, CHAR_UNDEFINED, delay); - }); + public static void keyHold(int keyCode) { + withFocusedCanvas(() -> fire(KeyEvent.KEY_PRESSED, keyCode, KeyEvent.CHAR_UNDEFINED)); } /** - * Simulates holding down a key using a KEY_PRESSED event. - * - * @param key the key code from {@link KeyEvent} + * Release a key on the focused canvas. + * @param keyCode */ - public static void keyHold(int key) - { - withFocusCanvas(() -> - dispatchKeyEvent(KeyEvent.KEY_PRESSED, key, CHAR_UNDEFINED, 0) - ); + public static void keyRelease(int keyCode) { + withFocusedCanvas(() -> fire(KeyEvent.KEY_RELEASED, keyCode, KeyEvent.CHAR_UNDEFINED)); } /** - * Simulates releasing a key using a KEY_RELEASED event. - * - * @param key the key code from {@link KeyEvent} + * Press (hold and release) a key on the focused canvas. + * @param keyCode */ - public static void keyRelease(int key) - { - withFocusCanvas(() -> { - int delay = Rs2Random.between(20, 200); - dispatchKeyEvent(KeyEvent.KEY_RELEASED, key, CHAR_UNDEFINED, delay); + public static void keyPress(int keyCode) { + withFocusedCanvas(() -> { + fire(KeyEvent.KEY_PRESSED, keyCode, KeyEvent.CHAR_UNDEFINED); + Global.sleep(20, 40); // real delay to preserve ordering + fire(KeyEvent.KEY_RELEASED, keyCode, KeyEvent.CHAR_UNDEFINED); }); } /** - * Simulates pressing and releasing a key in quick succession. - * - * @param key the key code from {@link KeyEvent} + * Press (hold and release) a key on the focused canvas, with a character. */ - public static void keyPress(int key) - { - keyHold(key); - keyRelease(key); - } + public static void holdShift() { keyHold(KeyEvent.VK_SHIFT); } + public static void releaseShift() { keyRelease(KeyEvent.VK_SHIFT); } /** - * Simulates pressing the Enter key. - * If the player is not logged in, this uses KEY_TYPED to avoid auto-login triggers. + * Press (hold and release) the Enter key on the focused canvas. */ - public static void enter() - { - // this is to avoid automatically login with jagex account when you are on the login screen - if (!Microbot.isLoggedIn()) { - dispatchKeyEvent(KeyEvent.KEY_TYPED, KeyEvent.VK_UNDEFINED, '\n', 0); - return; - } - - keyPress(KeyEvent.VK_ENTER); + public static void enter() { + withFocusedCanvas(() -> { + fire(KeyEvent.KEY_PRESSED, KeyEvent.VK_ENTER, KeyEvent.CHAR_UNDEFINED); + Global.sleep(20, 40); + fire(KeyEvent.KEY_TYPED, KeyEvent.VK_UNDEFINED, '\n'); + Global.sleep(5, 10); + fire(KeyEvent.KEY_RELEASED, KeyEvent.VK_ENTER, KeyEvent.CHAR_UNDEFINED); + }); } -} \ No newline at end of file +} From f3b267baa0235bf94a7aad2cf44371957ae221eb Mon Sep 17 00:00:00 2001 From: chsami Date: Sun, 5 Oct 2025 04:18:55 +0200 Subject: [PATCH 6/6] feat: bump 2.0.1 --- runelite-client/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/pom.xml b/runelite-client/pom.xml index 9a8b53c4276..7d58256e577 100644 --- a/runelite-client/pom.xml +++ b/runelite-client/pom.xml @@ -41,7 +41,7 @@ nogit false false - 2.0.16.1 + 2.0.17 nogit