From f14c68a90e71448a9b7319db9c2507892a1c9a0d Mon Sep 17 00:00:00 2001 From: chsami <23292806+chsami@users.noreply.github.com> Date: Mon, 19 Oct 2026 06:01:06 +0200 Subject: [PATCH 1/2] fix(GotrPlugin): guard region checks against null player location (1.5.11) isInHugeMine, isInLargeMine, isOutsideBarrier and isInMainRegion dereferenced Rs2Player.getWorldLocation() without a null check, so the usePortal sleepUntil threw an NPE while the region loaded after the portal teleport. Read the location once, return false when it is null, and use its X coordinate instead of a client-thread lookup on getLocalPlayer(). Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV --- .../plugins/microbot/gotr/GotrPlugin.java | 2 +- .../plugins/microbot/gotr/GotrScript.java | 21 +++-- .../microbot/gotr/GotrRegionCheckTest.java | 80 +++++++++++++++++++ 3 files changed, 95 insertions(+), 8 deletions(-) create mode 100644 src/test/java/net/runelite/client/plugins/microbot/gotr/GotrRegionCheckTest.java diff --git a/src/main/java/net/runelite/client/plugins/microbot/gotr/GotrPlugin.java b/src/main/java/net/runelite/client/plugins/microbot/gotr/GotrPlugin.java index 3f38de67f0..a14c925fe8 100644 --- a/src/main/java/net/runelite/client/plugins/microbot/gotr/GotrPlugin.java +++ b/src/main/java/net/runelite/client/plugins/microbot/gotr/GotrPlugin.java @@ -41,7 +41,7 @@ ) @Slf4j public class GotrPlugin extends Plugin { - public static final String version = "1.5.10"; + public static final String version = "1.5.11"; @Inject private GotrConfig config; diff --git a/src/main/java/net/runelite/client/plugins/microbot/gotr/GotrScript.java b/src/main/java/net/runelite/client/plugins/microbot/gotr/GotrScript.java index dff9f6b40c..a98f377a59 100644 --- a/src/main/java/net/runelite/client/plugins/microbot/gotr/GotrScript.java +++ b/src/main/java/net/runelite/client/plugins/microbot/gotr/GotrScript.java @@ -662,20 +662,26 @@ public void shutdown() { public static boolean isOutsideBarrier() { int outsideBarrierY = 9482; - return Rs2Player.getWorldLocation().getY() <= outsideBarrierY - && Rs2Player.getWorldLocation().getRegionID() == 14484; + WorldPoint location = Rs2Player.getWorldLocation(); + return location != null + && location.getY() <= outsideBarrierY + && location.getRegionID() == 14484; } public static boolean isInLargeMine() { int largeMineX = 3637; - return Rs2Player.getWorldLocation().getRegionID() == 14484 - && Microbot.getClientThread().invoke(() -> Microbot.getClient().getLocalPlayer().getWorldLocation().getX()) >= largeMineX; + WorldPoint location = Rs2Player.getWorldLocation(); + return location != null + && location.getRegionID() == 14484 + && location.getX() >= largeMineX; } public boolean isInHugeMine() { int hugeMineX = 3594; - return Rs2Player.getWorldLocation().getRegionID() == 14484 - && Microbot.getClientThread().invoke(() -> Microbot.getClient().getLocalPlayer().getWorldLocation().getX()) <= hugeMineX; + WorldPoint location = Rs2Player.getWorldLocation(); + return location != null + && location.getRegionID() == 14484 + && location.getX() <= hugeMineX; } static boolean isActiveAltarRenderable(Renderable renderable) { @@ -701,7 +707,8 @@ public boolean isInMiniGame() { } public static boolean isInMainRegion() { - return Rs2Player.getWorldLocation().getRegionID() == 14484; + WorldPoint location = Rs2Player.getWorldLocation(); + return location != null && location.getRegionID() == 14484; } public static int getStartTimer() { diff --git a/src/test/java/net/runelite/client/plugins/microbot/gotr/GotrRegionCheckTest.java b/src/test/java/net/runelite/client/plugins/microbot/gotr/GotrRegionCheckTest.java new file mode 100644 index 0000000000..38b53c3ccc --- /dev/null +++ b/src/test/java/net/runelite/client/plugins/microbot/gotr/GotrRegionCheckTest.java @@ -0,0 +1,80 @@ +package net.runelite.client.plugins.microbot.gotr; + +import net.runelite.api.coords.WorldPoint; +import net.runelite.client.plugins.microbot.util.player.Rs2Player; +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mockStatic; + +class GotrRegionCheckTest +{ + private final GotrScript script = new GotrScript(); + + @Test + void unknownLocationIsInNoArea() + { + try (MockedStatic player = mockStatic(Rs2Player.class)) + { + player.when(Rs2Player::getWorldLocation).thenReturn(null); + + assertFalse(script.isInHugeMine()); + assertFalse(GotrScript.isInLargeMine()); + assertFalse(GotrScript.isOutsideBarrier()); + assertFalse(GotrScript.isInMainRegion()); + } + } + + @Test + void hugeMineIsDetected() + { + try (MockedStatic player = mockStatic(Rs2Player.class)) + { + player.when(Rs2Player::getWorldLocation).thenReturn(new WorldPoint(3590, 9500, 0)); + + assertTrue(script.isInHugeMine()); + assertFalse(GotrScript.isInLargeMine()); + assertTrue(GotrScript.isInMainRegion()); + } + } + + @Test + void largeMineIsDetected() + { + try (MockedStatic player = mockStatic(Rs2Player.class)) + { + player.when(Rs2Player::getWorldLocation).thenReturn(new WorldPoint(3640, 9500, 0)); + + assertTrue(GotrScript.isInLargeMine()); + assertFalse(script.isInHugeMine()); + } + } + + @Test + void outsideBarrierIsDetected() + { + try (MockedStatic player = mockStatic(Rs2Player.class)) + { + player.when(Rs2Player::getWorldLocation).thenReturn(new WorldPoint(3615, 9480, 0)); + + assertTrue(GotrScript.isOutsideBarrier()); + assertTrue(GotrScript.isInMainRegion()); + } + } + + @Test + void otherRegionIsInNoArea() + { + try (MockedStatic player = mockStatic(Rs2Player.class)) + { + player.when(Rs2Player::getWorldLocation).thenReturn(new WorldPoint(3222, 3218, 0)); + + assertFalse(script.isInHugeMine()); + assertFalse(GotrScript.isInLargeMine()); + assertFalse(GotrScript.isOutsideBarrier()); + assertFalse(GotrScript.isInMainRegion()); + } + } +} From b7c08ae09d2531526f7a55aed2f84e9179cdd2c1 Mon Sep 17 00:00:00 2001 From: chsami <23292806+chsami@users.noreply.github.com> Date: Mon, 19 Oct 2026 06:04:33 +0200 Subject: [PATCH 2/2] fix(GotrPlugin): skip loop tick while player location is unknown The region predicates now return false for a null location, so the main loop read the region-load window after a portal teleport or altar trip as "not in the minigame" and could click the barrier or reset plugin state. Bail out of the iteration until Rs2Player.getWorldLocation() is known. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV --- .../client/plugins/microbot/gotr/GotrScript.java | 5 +++++ .../plugins/microbot/gotr/GotrRegionCheckTest.java | 12 ++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/main/java/net/runelite/client/plugins/microbot/gotr/GotrScript.java b/src/main/java/net/runelite/client/plugins/microbot/gotr/GotrScript.java index a98f377a59..83fbb05d39 100644 --- a/src/main/java/net/runelite/client/plugins/microbot/gotr/GotrScript.java +++ b/src/main/java/net/runelite/client/plugins/microbot/gotr/GotrScript.java @@ -126,6 +126,7 @@ public boolean run(GotrConfig config) { try { if (!Microbot.isLoggedIn()) return; if (!super.run()) return; + if (!isPlayerLocationKnown()) return; long startTime = System.currentTimeMillis(); if (!initCheck) { @@ -706,6 +707,10 @@ public boolean isInMiniGame() { return elementalRuneWidget != null; } + static boolean isPlayerLocationKnown() { + return Rs2Player.getWorldLocation() != null; + } + public static boolean isInMainRegion() { WorldPoint location = Rs2Player.getWorldLocation(); return location != null && location.getRegionID() == 14484; diff --git a/src/test/java/net/runelite/client/plugins/microbot/gotr/GotrRegionCheckTest.java b/src/test/java/net/runelite/client/plugins/microbot/gotr/GotrRegionCheckTest.java index 38b53c3ccc..1e2a2b46b7 100644 --- a/src/test/java/net/runelite/client/plugins/microbot/gotr/GotrRegionCheckTest.java +++ b/src/test/java/net/runelite/client/plugins/microbot/gotr/GotrRegionCheckTest.java @@ -24,6 +24,18 @@ void unknownLocationIsInNoArea() assertFalse(GotrScript.isInLargeMine()); assertFalse(GotrScript.isOutsideBarrier()); assertFalse(GotrScript.isInMainRegion()); + assertFalse(GotrScript.isPlayerLocationKnown()); + } + } + + @Test + void knownLocationLetsLoopDecide() + { + try (MockedStatic player = mockStatic(Rs2Player.class)) + { + player.when(Rs2Player::getWorldLocation).thenReturn(new WorldPoint(3222, 3218, 0)); + + assertTrue(GotrScript.isPlayerLocationKnown()); } }