Skip to content

fix(antiban): prevent action-cooldown stall when play-style tick intervals cross#1795

Open
pjmarz wants to merge 2 commits into
chsami:developmentfrom
pjmarz:fix/antiban-playstyle-tick-bounds
Open

fix(antiban): prevent action-cooldown stall when play-style tick intervals cross#1795
pjmarz wants to merge 2 commits into
chsami:developmentfrom
pjmarz:fix/antiban-playstyle-tick-bounds

Conversation

@pjmarz

@pjmarz pjmarz commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Summary

With "Use Non-Linear Intervals" enabled (which the per-skill antiban setup templates turn on by default), PlayStyle.evolvePlayStyle() random-walks primaryTickInterval and secondaryTickInterval independently, so over time they can cross (primary greater than secondary). Once that happens, PlayStyle.getRandomTickInterval() calls ThreadLocalRandom.nextInt(origin, bound) with origin above bound and throws on every stat change:

java.lang.IllegalArgumentException: bound must be greater than origin
    at java.base/java.util.concurrent.ThreadLocalRandom.nextInt(ThreadLocalRandom.java:337)
    at net.runelite.client.plugins.microbot.util.antiban.enums.PlayStyle.getRandomTickInterval(PlayStyle.java:114)
    at net.runelite.client.plugins.microbot.util.antiban.Rs2Antiban.performActionCooldown(Rs2Antiban.java:297)
    at net.runelite.client.plugins.microbot.util.antiban.Rs2Antiban.actionCooldown(Rs2Antiban.java:277)
    at net.runelite.client.plugins.microbot.util.antiban.AntibanPlugin.onStatChanged(AntibanPlugin.java:345)

Captured live on 2.6.5 while high alching.

The impact is worse than the exception: performActionCooldown() sets Microbot.pauseAllScripts = true BEFORE computing the interval, and actionCooldownActive = true only after. The throw lands between the two, so the cooldown clearer (AntibanPlugin.performActionBreak, gated on actionCooldownActive) never runs and every running script stays frozen until the interval random-walk happens to uncross (observed multi-minute stalls). Any script using a templated antiban setup is exposed.

Fix

  1. PlayStyle.getRandomTickInterval(): order the bounds with min/max before calling nextInt(lo, hi + 1), so crossed intervals can never throw.
  2. Rs2Antiban.performActionCooldown(): compute the interval first, then set pauseAllScripts and actionCooldownActive together, so no exception path can leave scripts paused with nothing to release them.
  3. New regression test PlayStyleRandomTickIntervalTest forces the crossed-interval state (which deterministically threw before the fix) plus the equal-bounds edge case.

Testing

  • ./gradlew :client:runUnitTests --tests "*PlayStyleRandomTickIntervalTest" passes (failed before the fix).
  • ./gradlew :client:compileJava green.
  • Patched client boots and runs clean; normal action-cooldown pause and resume behavior unchanged.
  • Workaround for affected users until this lands: disable "Use Non-Linear Intervals" in the Antiban panel.

🤖 Generated with Claude Code

…rvals cross

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 9, 2026 23:03

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds a defensive fix and regression coverage for a cooldown stall caused by crossed tick-interval bounds, and adjusts cooldown pausing to avoid leaving scripts paused if interval computation fails.

Changes:

  • Harden PlayStyle#getRandomTickInterval() by ordering bounds before calling ThreadLocalRandom.nextInt.
  • Add a regression test covering crossed/equal tick interval bounds.
  • Move pauseAllScripts activation to occur after TIMEOUT is computed.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
runelite-client/src/test/java/net/runelite/client/plugins/microbot/util/antiban/enums/PlayStyleRandomTickIntervalTest.java Adds regression test that reproduces crossed-bound intervals and asserts no exception + valid range.
runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/antiban/enums/PlayStyle.java Prevents IllegalArgumentException by defensively ordering interval bounds before random selection.
runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/antiban/Rs2Antiban.java Reorders pause flag setting to occur after interval computation to reduce “paused with no countdown” failure mode.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +114 to +119
// primaryTickInterval and secondaryTickInterval drift independently in evolvePlayStyle()
// and can cross (primary > secondary). nextInt(origin, bound) requires bound > origin, so
// order the bounds defensively to avoid IllegalArgumentException.
int lo = Math.min(primaryTickInterval, secondaryTickInterval);
int hi = Math.max(primaryTickInterval, secondaryTickInterval);
return ThreadLocalRandom.current().nextInt(lo, hi + 1);
Comment on lines +35 to +37
PlayStyle style = PlayStyle.values()[0];
int origPrimary = getInterval(style, "primaryTickInterval");
int origSecondary = getInterval(style, "secondaryTickInterval");
Comment on lines +40 to +45
setInterval(style, "primaryTickInterval", 10);
setInterval(style, "secondaryTickInterval", 5);
for (int i = 0; i < 10_000; i++) {
int v = style.getRandomTickInterval();
assertTrue("interval " + v + " must fall within [5,10]", v >= 5 && v <= 10);
}
Comment on lines 298 to 303
// Pause and set the active flag together, only after TIMEOUT is computed. If computing the
// interval ever throws, scripts must not be left paused with no countdown to clear them.
if (Rs2AntibanSettings.universalAntiban)
Microbot.pauseAllScripts.compareAndSet(false, true);

Rs2AntibanSettings.actionCooldownActive = true;
@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 580cde0e-47c9-4dda-834b-9e8e986d6ecc

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

This PR adds defensive interval bound ordering to PlayStyle.getRandomTickInterval() to prevent IllegalArgumentException when primaryTickInterval and secondaryTickInterval cross or drift independently. A regression test covers the crossing and equal-bounds cases using reflection to control interval values. Additionally, Rs2Antiban.performActionCooldown() is refactored to delay the pause-all-scripts flag update until after TIMEOUT is computed, preventing scripts from being left paused if interval calculation fails.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title directly and specifically describes the main fix: preventing action-cooldown stalls caused by play-style tick interval crossing.
Description check ✅ Passed The description comprehensively explains the problem, the root cause, the fixes applied, and testing performed, all directly related to the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

…rate comment

Addresses Copilot review feedback on chsami#1795.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@pjmarz

pjmarz commented Jun 9, 2026

Copy link
Copy Markdown
Contributor Author

Addressed: the inclusive upper bound is computed in long so Integer.MAX_VALUE cannot overflow, the test pins PlayStyle.MODERATE instead of values()[0], and the reorder comment now describes the conditional pause plus unconditional flag precisely. On the enum-state mutation concern: the intervals are restored in a finally block and the unit-test suite runs single-threaded; noted in the test.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants