From 04e786eb73a87e2cb9e1dcbd716e177ec0f43121 Mon Sep 17 00:00:00 2001 From: Bizza12345 Date: Wed, 2 Sep 2026 20:30:06 +1000 Subject: [PATCH 1/2] feat(breakhandler): defer requested breaks for plugin locks --- .../breakhandlerv2/BreakHandlerV2Script.java | 17 +++++++++++ .../BreakHandlerV2DeferralTest.java | 29 +++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 runelite-client/src/test/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2DeferralTest.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Script.java b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Script.java index ce0371837b1..49a26793447 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Script.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Script.java @@ -6,6 +6,7 @@ import net.runelite.client.config.ConfigProfile; import net.runelite.client.plugins.microbot.Microbot; import net.runelite.client.plugins.microbot.Script; +import net.runelite.client.plugins.microbot.breakhandler.BreakHandlerScript; import net.runelite.client.plugins.microbot.util.discord.Rs2Discord; import net.runelite.client.plugins.microbot.util.math.Rs2Random; import net.runelite.client.plugins.microbot.util.player.Rs2Player; @@ -30,6 +31,7 @@ @Singleton @Slf4j public class BreakHandlerV2Script extends Script { + private static final long LOCK_DEFERRAL_LOG_INTERVAL_MS = 30_000L; // Instance tracking for debugging private static int instanceCounter = 0; @@ -72,6 +74,7 @@ public BreakHandlerV2Script() { // Break duration in milliseconds private long currentBreakDuration = 0; private boolean logoutBreakActive = false; + private long lastLockDeferralLogAt = 0L; private boolean longBreakDue = false; private boolean megaBreakDue = false; private volatile boolean currentBreakIsLong = false; @@ -236,6 +239,16 @@ private void handleWaitingForBreak() { * Initiates break based on configuration */ private void handleBreakRequested() { + if (shouldDeferRequestedBreak()) { + long now = System.currentTimeMillis(); + if (now - lastLockDeferralLogAt >= LOCK_DEFERRAL_LOG_INTERVAL_MS) { + log.info("[BreakHandlerV2] Break deferred while a plugin lock is active"); + lastLockDeferralLogAt = now; + } + return; + } + + lastLockDeferralLogAt = 0L; stopConfiguredPluginIfNeeded(); // If breakEndTime is already set, we're in a no-logout break waiting for it to end @@ -267,6 +280,10 @@ private void handleBreakRequested() { } } + static boolean shouldDeferRequestedBreak() { + return BreakHandlerScript.isLockState(); + } + /** * Handle INITIATING_BREAK state * Performs safety checks before logout with backoff retry diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2DeferralTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2DeferralTest.java new file mode 100644 index 00000000000..c46fa2d9bac --- /dev/null +++ b/runelite-client/src/test/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2DeferralTest.java @@ -0,0 +1,29 @@ +package net.runelite.client.plugins.microbot.breakhandler.breakhandlerv2; + +import net.runelite.client.plugins.microbot.breakhandler.BreakHandlerScript; +import org.junit.After; +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class BreakHandlerV2DeferralTest { + @After + public void clearPluginLock() { + BreakHandlerScript.setLockState(false); + } + + @Test + public void defersRequestedBreakWhilePluginLockIsHeld() { + BreakHandlerScript.setLockState(true); + + assertTrue(BreakHandlerV2Script.shouldDeferRequestedBreak()); + } + + @Test + public void proceedsWhenPluginLockIsReleased() { + BreakHandlerScript.setLockState(false); + + assertFalse(BreakHandlerV2Script.shouldDeferRequestedBreak()); + } +} From 992ee184939e178ded81ca62e1d41cc24431c696 Mon Sep 17 00:00:00 2001 From: Bizza12345 Date: Thu, 3 Sep 2026 15:11:29 +1000 Subject: [PATCH 2/2] fix(breakhandler): allow active pause breaks to complete --- .../breakhandlerv2/BreakHandlerV2Script.java | 10 +++++++--- .../BreakHandlerV2DeferralTest.java | 15 ++++++++++++--- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Script.java b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Script.java index 49a26793447..e8ec9c3ff4b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Script.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Script.java @@ -239,7 +239,7 @@ private void handleWaitingForBreak() { * Initiates break based on configuration */ private void handleBreakRequested() { - if (shouldDeferRequestedBreak()) { + if (shouldDeferRequestedBreak(breakEndTime)) { long now = System.currentTimeMillis(); if (now - lastLockDeferralLogAt >= LOCK_DEFERRAL_LOG_INTERVAL_MS) { log.info("[BreakHandlerV2] Break deferred while a plugin lock is active"); @@ -280,8 +280,12 @@ private void handleBreakRequested() { } } - static boolean shouldDeferRequestedBreak() { - return BreakHandlerScript.isLockState(); + /** + * Defers only a new break request. A non-null end time represents an active + * no-logout break whose completion must continue to be processed. + */ + static boolean shouldDeferRequestedBreak(Instant activeBreakEndTime) { + return activeBreakEndTime == null && BreakHandlerScript.isLockState(); } /** diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2DeferralTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2DeferralTest.java index c46fa2d9bac..36406b75fb5 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2DeferralTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2DeferralTest.java @@ -4,6 +4,8 @@ import org.junit.After; import org.junit.Test; +import java.time.Instant; + import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -17,13 +19,20 @@ public void clearPluginLock() { public void defersRequestedBreakWhilePluginLockIsHeld() { BreakHandlerScript.setLockState(true); - assertTrue(BreakHandlerV2Script.shouldDeferRequestedBreak()); + assertTrue(BreakHandlerV2Script.shouldDeferRequestedBreak(null)); } @Test - public void proceedsWhenPluginLockIsReleased() { + public void doesNotDeferNewBreakWhenPluginLockIsReleased() { BreakHandlerScript.setLockState(false); - assertFalse(BreakHandlerV2Script.shouldDeferRequestedBreak()); + assertFalse(BreakHandlerV2Script.shouldDeferRequestedBreak(null)); + } + + @Test + public void doesNotDeferActiveNoLogoutBreakWhenPluginLockIsHeld() { + BreakHandlerScript.setLockState(true); + + assertFalse(BreakHandlerV2Script.shouldDeferRequestedBreak(Instant.now())); } }