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..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 @@ -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(breakEndTime)) { + 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,14 @@ private void handleBreakRequested() { } } + /** + * 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(); + } + /** * 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..36406b75fb5 --- /dev/null +++ b/runelite-client/src/test/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2DeferralTest.java @@ -0,0 +1,38 @@ +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 java.time.Instant; + +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(null)); + } + + @Test + public void doesNotDeferNewBreakWhenPluginLockIsReleased() { + BreakHandlerScript.setLockState(false); + + assertFalse(BreakHandlerV2Script.shouldDeferRequestedBreak(null)); + } + + @Test + public void doesNotDeferActiveNoLogoutBreakWhenPluginLockIsHeld() { + BreakHandlerScript.setLockState(true); + + assertFalse(BreakHandlerV2Script.shouldDeferRequestedBreak(Instant.now())); + } +}