Conversation
Inventory items are already using a contains check. This allows the bug fix form !1574 to also work with equipped items.
fix(WebWalker): fix action matching for equipment items
…and avoid index out of bounds
WalkthroughThis pull request updates the microbot version from 2.0.34 to 2.0.35 in the build configuration. It includes several code-level modifications across multiple utility and management classes: adjustments to login flow initialization in AutoLoginScript, refinements to plugin stop handling with EDT context awareness in MicrobotPluginManager, broadened equipment action matching logic in Rs2Equipment, improved null-safety in Rs2RunePouch's varbit handler, and simplified active profile retrieval in LoginManager. Additionally, a comment modification appears in ConfigManager. Possibly related PRs
Note: The ConfigManager comment change appears to introduce a typo ("profautoogile" instead of "profile"), and the AutoLoginScript modification removes a LOGIN_SCREEN state check before login initiation, which may warrant verification of intended behavior. Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✨ Finishing touches
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
runelite-client/pom.xml(1 hunks)runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java(1 hunks)runelite-client/src/main/java/net/runelite/client/plugins/microbot/accountselector/AutoLoginScript.java(22 hunks)runelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginManager.java(1 hunks)runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/equipment/Rs2Equipment.java(1 hunks)runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/inventory/Rs2RunePouch.java(1 hunks)runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/security/LoginManager.java(2 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/**/*.java
📄 CodeRabbit inference engine (AGENTS.md)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/**/*.java: Place all gameplay automation code under runelite-client/src/main/java/net/runelite/client/plugins/microbot
Prefix configuration interfaces with the plugin name (e.g., ExampleConfig) within microbot plugins
Files:
runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/inventory/Rs2RunePouch.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/util/security/LoginManager.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginManager.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/util/equipment/Rs2Equipment.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/accountselector/AutoLoginScript.java
runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/**/*.java
📄 CodeRabbit inference engine (AGENTS.md)
Put shared helpers under .../microbot/util
Files:
runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/inventory/Rs2RunePouch.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/util/security/LoginManager.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/util/equipment/Rs2Equipment.java
**/*.java
📄 CodeRabbit inference engine (AGENTS.md)
**/*.java: Use tabs for indentation, follow the brace placement style exemplified in MicrobotPlugin.java, and keep lines under 120 characters
Use UpperCamelCase for types and lowerCamelCase for members
Files:
runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/inventory/Rs2RunePouch.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/util/security/LoginManager.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginManager.javarunelite-client/src/main/java/net/runelite/client/config/ConfigManager.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/util/equipment/Rs2Equipment.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/accountselector/AutoLoginScript.java
**/pom.xml
📄 CodeRabbit inference engine (AGENTS.md)
Target Java 11 via maven-compiler-plugin using 11 in all module POMs
Files:
runelite-client/pom.xml
runelite-client/src/main/java/net/runelite/client/plugins/microbot/@(!(util|example))/**/*.java
📄 CodeRabbit inference engine (AGENTS.md)
For new automation scripts, reuse the scheduler pattern demonstrated in ExampleScript
Files:
runelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginManager.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/accountselector/AutoLoginScript.java
🧠 Learnings (2)
📚 Learning: 2025-10-16T17:14:29.778Z
Learnt from: CR
PR: chsami/Microbot#0
File: AGENTS.md:0-0
Timestamp: 2025-10-16T17:14:29.778Z
Learning: Applies to runelite-client/src/main/java/net/runelite/client/plugins/microbot/**/*.java : Place all gameplay automation code under runelite-client/src/main/java/net/runelite/client/plugins/microbot
Applied to files:
runelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginManager.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/accountselector/AutoLoginScript.java
📚 Learning: 2025-10-16T17:14:29.778Z
Learnt from: CR
PR: chsami/Microbot#0
File: AGENTS.md:0-0
Timestamp: 2025-10-16T17:14:29.778Z
Learning: Applies to runelite-client/src/main/java/net/runelite/client/plugins/microbot/MicrobotPlugin.java : When adding panel controls or overlays, update the Microbot navigation panel setup in MicrobotPlugin and provide default config values
Applied to files:
runelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginManager.java
🧬 Code graph analysis (1)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/accountselector/AutoLoginScript.java (1)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/player/Rs2Player.java (1)
Rs2Player(53-1799)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Build
| log.info("Login screen detected, initiating login"); | ||
| initiateLogin(config); | ||
| transitionToState(LoginState.ATTEMPTING_LOGIN); | ||
| } |
There was a problem hiding this comment.
State no longer “waits” and log claims detection without a check
In WAITING_FOR_LOGIN_SCREEN you initiate login unconditionally and log “Login screen detected” without verifying GameState.LOGIN_SCREEN. Either rename the state or reintroduce the check.
- log.info("Login screen detected, initiating login");
- initiateLogin(config);
- transitionToState(LoginState.ATTEMPTING_LOGIN);
+ if (Microbot.getClient() != null && Microbot.getClient().getGameState() == GameState.LOGIN_SCREEN) {
+ log.info("Login screen detected, initiating login");
+ initiateLogin(config);
+ transitionToState(LoginState.ATTEMPTING_LOGIN);
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| log.info("Login screen detected, initiating login"); | |
| initiateLogin(config); | |
| transitionToState(LoginState.ATTEMPTING_LOGIN); | |
| } | |
| if (Microbot.getClient() != null && Microbot.getClient().getGameState() == GameState.LOGIN_SCREEN) { | |
| log.info("Login screen detected, initiating login"); | |
| initiateLogin(config); | |
| transitionToState(LoginState.ATTEMPTING_LOGIN); | |
| } | |
| } |
🤖 Prompt for AI Agents
In
runelite-client/src/main/java/net/runelite/client/plugins/microbot/accountselector/AutoLoginScript.java
around lines 108 to 111, the code logs "Login screen detected" and calls
initiateLogin(config) unconditionally while the state is
WAITING_FOR_LOGIN_SCREEN; reintroduce an explicit check for
client.getGameState() == GameState.LOGIN_SCREEN (or equivalent game-state
accessor) before logging, calling initiateLogin(config), and transitioning to
LoginState.ATTEMPTING_LOGIN, so only when the client is actually on the login
screen perform those actions; alternatively, if the design intent was to always
run immediately, rename the state to reflect that behavior (e.g.,
READY_TO_LOGIN) and remove the misleading log message.
| ConfigProfile activeProfile = LoginManager.getActiveProfile(); | ||
| boolean isMemberFromProfile = activeProfile != null && activeProfile.isMember(); | ||
| boolean isLocalPlayerAvailable = Microbot.getClient()!=null && Microbot.getClient().getLocalPlayer() != null; | ||
| boolean isMemberFromClient = Microbot.getClient()!=null && Microbot.getClient().getLocalPlayer() != null ? Rs2Player.isMember() : false; | ||
| log.error("Preferred world {} is not accessible,\n\t ->check if we have member access set in profile(current value {}), or when logged in, have we member access ? (LocalPlayer? {}, isMember? {})", | ||
| config.usePreferredWorld(), isMemberFromProfile, isLocalPlayerAvailable, isMemberFromClient); | ||
| boolean isLocalPlayerAvailable = Microbot.getClient() != null && Microbot.getClient().getLocalPlayer() != null; | ||
| boolean isMemberFromClient = Microbot.getClient() != null && Microbot.getClient().getLocalPlayer() != null ? Rs2Player.isMember() : false; | ||
| log.error("Preferred world {} is not accessible,\n\t ->check if we have member access set in profile(current value {}), or when logged in, have we member access ? (LocalPlayer? {}, isMember? {})", | ||
| config.usePreferredWorld(), isMemberFromProfile, isLocalPlayerAvailable, isMemberFromClient); | ||
| } |
There was a problem hiding this comment.
Wrong value in “Preferred world {}” log placeholder
You pass config.usePreferredWorld() (boolean) where the world id is expected; use config.world().
- } else {
+ } else {
ConfigProfile activeProfile = LoginManager.getActiveProfile();
boolean isMemberFromProfile = activeProfile != null && activeProfile.isMember();
boolean isLocalPlayerAvailable = Microbot.getClient() != null && Microbot.getClient().getLocalPlayer() != null;
boolean isMemberFromClient = Microbot.getClient() != null && Microbot.getClient().getLocalPlayer() != null ? Rs2Player.isMember() : false;
- log.error("Preferred world {} is not accessible,\n\t ->check if we have member access set in profile(current value {}), or when logged in, have we member access ? (LocalPlayer? {}, isMember? {})",
- config.usePreferredWorld(), isMemberFromProfile, isLocalPlayerAvailable, isMemberFromClient);
+ log.error("Preferred world {} is not accessible,\n\t ->check if we have member access set in profile(current value {}), or when logged in, have we member access ? (LocalPlayer? {}, isMember? {})",
+ config.world(), isMemberFromProfile, isLocalPlayerAvailable, isMemberFromClient);
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| ConfigProfile activeProfile = LoginManager.getActiveProfile(); | |
| boolean isMemberFromProfile = activeProfile != null && activeProfile.isMember(); | |
| boolean isLocalPlayerAvailable = Microbot.getClient()!=null && Microbot.getClient().getLocalPlayer() != null; | |
| boolean isMemberFromClient = Microbot.getClient()!=null && Microbot.getClient().getLocalPlayer() != null ? Rs2Player.isMember() : false; | |
| log.error("Preferred world {} is not accessible,\n\t ->check if we have member access set in profile(current value {}), or when logged in, have we member access ? (LocalPlayer? {}, isMember? {})", | |
| config.usePreferredWorld(), isMemberFromProfile, isLocalPlayerAvailable, isMemberFromClient); | |
| boolean isLocalPlayerAvailable = Microbot.getClient() != null && Microbot.getClient().getLocalPlayer() != null; | |
| boolean isMemberFromClient = Microbot.getClient() != null && Microbot.getClient().getLocalPlayer() != null ? Rs2Player.isMember() : false; | |
| log.error("Preferred world {} is not accessible,\n\t ->check if we have member access set in profile(current value {}), or when logged in, have we member access ? (LocalPlayer? {}, isMember? {})", | |
| config.usePreferredWorld(), isMemberFromProfile, isLocalPlayerAvailable, isMemberFromClient); | |
| } | |
| ConfigProfile activeProfile = LoginManager.getActiveProfile(); | |
| boolean isMemberFromProfile = activeProfile != null && activeProfile.isMember(); | |
| boolean isLocalPlayerAvailable = Microbot.getClient() != null && Microbot.getClient().getLocalPlayer() != null; | |
| boolean isMemberFromClient = Microbot.getClient() != null && Microbot.getClient().getLocalPlayer() != null ? Rs2Player.isMember() : false; | |
| log.error("Preferred world {} is not accessible,\n\t ->check if we have member access set in profile(current value {}), or when logged in, have we member access ? (LocalPlayer? {}, isMember? {})", | |
| config.world(), isMemberFromProfile, isLocalPlayerAvailable, isMemberFromClient); | |
| } |
🤖 Prompt for AI Agents
In
runelite-client/src/main/java/net/runelite/client/plugins/microbot/accountselector/AutoLoginScript.java
around lines 256 to 262, the log message passes config.usePreferredWorld() (a
boolean) into the "Preferred world {}" placeholder when it should pass the
configured world id; replace the boolean argument with config.world() so the
placeholder shows the world id, keeping the rest of the log arguments unchanged.
| default: | ||
| // fallback to legacy behavior | ||
| targetWorld = LoginManager.getRandomWorld(Rs2Player.isMember()); | ||
| if(!Rs2WorldUtil.canAccessWorld(targetWorld)) { | ||
| targetWorld = LoginManager.getRandomWorld(Rs2Player.isMember()); | ||
| if (!Rs2WorldUtil.canAccessWorld(targetWorld)) { | ||
| log.warn("Randomly selected world {} is not accessible, using default world {}", targetWorld, config.world()); | ||
| targetWorld = config.world(); | ||
| } | ||
| } | ||
| break; |
There was a problem hiding this comment.
Default selection ignores membersOnly config
Fallback uses Rs2Player.isMember(), which may be unavailable pre-login and contradicts config.membersOnly(). Use the computed membersOnly.
- // fallback to legacy behavior
- targetWorld = LoginManager.getRandomWorld(Rs2Player.isMember());
+ // fallback to legacy behavior
+ targetWorld = LoginManager.getRandomWorld(membersOnly);
if (!Rs2WorldUtil.canAccessWorld(targetWorld)) {
log.warn("Randomly selected world {} is not accessible, using default world {}", targetWorld, config.world());
targetWorld = config.world();
}🤖 Prompt for AI Agents
In
runelite-client/src/main/java/net/runelite/client/plugins/microbot/accountselector/AutoLoginScript.java
around lines 301 to 308, the default fallback randomly selects a world using
Rs2Player.isMember() which may be unavailable before login and ignores the
already computed membersOnly setting; change the call to
LoginManager.getRandomWorld(...) to pass the precomputed membersOnly boolean
(the variable you computed earlier in the method) instead of
Rs2Player.isMember(), and keep the subsequent canAccessWorld check and logging
(adjust log text if needed to reference membersOnly) so the fallback respects
the configured members-only behavior.
| public static void onVarbitChanged(VarbitChanged ev) { | ||
| assert Microbot.getClient().isClientThread(); | ||
|
|
||
| for (int i = 0; i < NUM_SLOTS; i++) { | ||
| if (i >= slots.size()) { | ||
| break; // avoid index out of bounds | ||
| } | ||
|
|
||
| PouchSlot slot = slots.get(i); | ||
| if (slot == null) { | ||
| continue; // skip null entries | ||
| } | ||
|
|
||
| int varbitId = ev.getVarbitId(); | ||
| int value = ev.getValue(); | ||
|
|
||
| if (varbitId == RUNE_VARBITS[i]) { | ||
| slot.setRune(Runes.byVarbitId(value)); | ||
| break; | ||
| } | ||
| if (varbitId == AMOUNT_VARBITS[i]) { | ||
| slot.setQuantity(value); | ||
| break; | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Fix missed updates when slots aren’t pre-sized
Breaking when slots.size() < NUM_SLOTS skips handling for valid varbit changes; also tolerating null slots hides the underlying init issue. Pre-size the slots list and remove the early break/null path.
public static void onVarbitChanged(VarbitChanged ev) {
assert Microbot.getClient().isClientThread();
+ // Ensure slots are initialized to NUM_SLOTS so varbit updates never get skipped
+ while (slots.size() < NUM_SLOTS) {
+ slots.add(new PouchSlot(null, 0));
+ }
+
for (int i = 0; i < NUM_SLOTS; i++) {
- if (i >= slots.size()) {
- break; // avoid index out of bounds
- }
-
- PouchSlot slot = slots.get(i);
- if (slot == null) {
- continue; // skip null entries
- }
+ PouchSlot slot = slots.get(i);
int varbitId = ev.getVarbitId();
int value = ev.getValue();
if (varbitId == RUNE_VARBITS[i]) {
slot.setRune(Runes.byVarbitId(value));
break;
}
if (varbitId == AMOUNT_VARBITS[i]) {
slot.setQuantity(value);
break;
}
}
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| public static void onVarbitChanged(VarbitChanged ev) { | |
| assert Microbot.getClient().isClientThread(); | |
| for (int i = 0; i < NUM_SLOTS; i++) { | |
| if (i >= slots.size()) { | |
| break; // avoid index out of bounds | |
| } | |
| PouchSlot slot = slots.get(i); | |
| if (slot == null) { | |
| continue; // skip null entries | |
| } | |
| int varbitId = ev.getVarbitId(); | |
| int value = ev.getValue(); | |
| if (varbitId == RUNE_VARBITS[i]) { | |
| slot.setRune(Runes.byVarbitId(value)); | |
| break; | |
| } | |
| if (varbitId == AMOUNT_VARBITS[i]) { | |
| slot.setQuantity(value); | |
| break; | |
| } | |
| } | |
| } | |
| public static void onVarbitChanged(VarbitChanged ev) { | |
| assert Microbot.getClient().isClientThread(); | |
| // Ensure slots are initialized to NUM_SLOTS so varbit updates never get skipped | |
| while (slots.size() < NUM_SLOTS) { | |
| slots.add(new PouchSlot(null, 0)); | |
| } | |
| for (int i = 0; i < NUM_SLOTS; i++) { | |
| PouchSlot slot = slots.get(i); | |
| int varbitId = ev.getVarbitId(); | |
| int value = ev.getValue(); | |
| if (varbitId == RUNE_VARBITS[i]) { | |
| slot.setRune(Runes.byVarbitId(value)); | |
| break; | |
| } | |
| if (varbitId == AMOUNT_VARBITS[i]) { | |
| slot.setQuantity(value); | |
| break; | |
| } | |
| } | |
| } |
🤖 Prompt for AI Agents
In
runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/inventory/Rs2RunePouch.java
around lines 88 to 113, the onVarbitChanged loop currently breaks when
slots.size() < NUM_SLOTS and tolerates null slot entries, which causes missed
updates; pre-size and initialize the slots list to NUM_SLOTS (populate with
PouchSlot instances or placeholders) at construction/initialization so
slots.get(i) is always valid, remove the early break when i >= slots.size(),
remove the null-skip branch (or replace it with a defensive initialization if
still null), and stop using break after handling a varbit so the method can
process both rune and amount varbit changes for all relevant slots (use
continue/return only where appropriate).
2.0.35
Login fixes, Profile Fixes,