Skip to content

Comments

2.1.0 - setup new api#1608

Merged
chsami merged 53 commits intodevelopmentfrom
GameObjects
Dec 27, 2025
Merged

2.1.0 - setup new api#1608
chsami merged 53 commits intodevelopmentfrom
GameObjects

Conversation

@chsami
Copy link
Owner

@chsami chsami commented Nov 16, 2025

2.1.0

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 16, 2025

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.

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

Walkthrough

This PR performs a comprehensive system refactoring that removes all scheduler documentation files, eliminates the Rs2 Cache Debugger plugin entirely, replaces the legacy RS2 cache system with Rs2PlayerStateCache, introduces new entity query APIs (IEntity, IEntityQueryable, AbstractEntityQueryable), adds cache-based queryables for NPCs, players, tile items, and tile objects, removes SchedulableExamplePlugin and related schedulable example classes, deletes SchedulerConfig and SchedulerInfoOverlay, updates MicrobotPluginManager error handling, and bumps the microbot version from 2.0.41 to 2.1.0.

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.75% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title '2.1.0 - setup new api' is clear and specific, describing a version release with API setup. It accurately reflects the primary changes involving new API additions and refactoring.
Description check ✅ Passed The description '2.1.0' is minimal but is related to the changeset as a version identifier matching the title. Although very brief, it conveys the version context of the pull request.

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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 17

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerScript.java (1)

897-903: Update the JavaDoc to match the implementation.

The JavaDoc comment states this method checks "both the manual lock state and any locked conditions from schedulable plugins", but the implementation only returns lockState.get(). The comment should be updated to reflect that it now only checks the manual lock state.

Apply this diff to correct the JavaDoc:

     /**
-     * Checks if the break handler is currently in a locked state.
-     * This includes both the manual lock state and any locked conditions from schedulable plugins.
+     * Checks if the break handler is currently in a manually locked state.
+     * When locked, breaks are prevented from starting.
      */
     public static boolean isLockState() {
         return lockState.get();
     }
runelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginManager.java (2)

497-545: Plugins with injection failures are still treated as successfully loaded

In instantiate, if Guice throws ExecutionError (e.g., due to NoClassDefFoundError) or any other Exception during injector creation, you:

  • Log the error and delete the JAR, but
  • Still fall through, log "Loaded plugin {}" and return the plugin instance.

That leaves a plugin with a null/invalid injector registered as “loaded”, which contradicts the intent of marking such plugins incompatible and cleaning them up.

Consider rethrowing PluginInstantiationException after deleting the JAR so callers can skip adding the plugin:

         try {
             Injector parent = Microbot.getInjector();
             ...
             Injector pluginInjector = parent.createChildInjector(pluginModule);
             System.out.println(pluginInjector.getClass().getSimpleName());
             plugin.setInjector(pluginInjector);
-        } catch (com.google.common.util.concurrent.ExecutionError e) {
+        } catch (com.google.common.util.concurrent.ExecutionError e) {
             // Guice/Guava wraps NoClassDefFoundError here
             Throwable cause = e.getCause();
             if (cause instanceof NoClassDefFoundError) {
                 log.error("Missing class while loading plugin {}: {}", clazz.getSimpleName(), cause.toString());
             } else {
                 log.error("Error while loading plugin {}: {}", clazz.getSimpleName(), e.toString(), e);
             }
 
             File jar = getPluginJarFile(plugin.getClass().getSimpleName());
             if (jar != null) {
                 jar.delete();
             }
-        } catch (Exception ex) {
-            log.error("Incompatible plugin found: " + clazz.getSimpleName());
-            File jar = getPluginJarFile(plugin.getClass().getSimpleName());
-            jar.delete();
-        }
-
-        log.debug("Loaded plugin {}", clazz.getSimpleName());
-        return plugin;
+            throw new PluginInstantiationException(e);
+        } catch (Exception ex) {
+            log.error("Incompatible plugin found: " + clazz.getSimpleName());
+            File jar = getPluginJarFile(plugin.getClass().getSimpleName());
+            jar.delete();
+            throw new PluginInstantiationException(ex);
+        }
+
+        log.debug("Loaded plugin {}", clazz.getSimpleName());
+        return plugin;

This keeps the “incompatible/missing class” paths consistent with upstream error-handling semantics.


1001-1053: Removal log message says “Added plugin”

In remove(MicrobotPluginManifest manifest), after successfully removing and deleting the plugin, the log still says:

log.info("Added plugin {} to installed list", manifest.getDisplayName());

which contradicts the operation being performed.

Consider updating it to reflect removal:

-        log.info("Added plugin {} to installed list", manifest.getDisplayName());
+        log.info("Removed plugin {} from installed list", manifest.getDisplayName());
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cb33886 and df95d2c.

📒 Files selected for processing (79)
  • docs/scheduler/README.md (0 hunks)
  • docs/scheduler/api/schedulable-plugin.md (0 hunks)
  • docs/scheduler/combat-lock-examples.md (0 hunks)
  • docs/scheduler/condition-manager.md (0 hunks)
  • docs/scheduler/conditions/location-conditions.md (0 hunks)
  • docs/scheduler/conditions/logical-conditions.md (0 hunks)
  • docs/scheduler/conditions/npc-conditions.md (0 hunks)
  • docs/scheduler/conditions/resource-conditions.md (0 hunks)
  • docs/scheduler/conditions/skill-conditions.md (0 hunks)
  • docs/scheduler/conditions/time-conditions.md (0 hunks)
  • docs/scheduler/defining-conditions.md (0 hunks)
  • docs/scheduler/event/plugin-schedule-entry-finished-event.md (0 hunks)
  • docs/scheduler/event/plugin-schedule-entry-soft-stop-event.md (0 hunks)
  • docs/scheduler/plugin-schedule-entry-merged.md (0 hunks)
  • docs/scheduler/plugin-writers-guide.md (0 hunks)
  • docs/scheduler/predicate-condition-examples.md (0 hunks)
  • docs/scheduler/roadmap.md (0 hunks)
  • docs/scheduler/schedulable-example-plugin.md (0 hunks)
  • docs/scheduler/scheduler-plugin.md (0 hunks)
  • docs/scheduler/tasks/README.md (0 hunks)
  • docs/scheduler/tasks/enhanced-schedulable-plugin-api.md (0 hunks)
  • docs/scheduler/tasks/plugin-writers-guide.md (0 hunks)
  • docs/scheduler/tasks/requirements-integration.md (0 hunks)
  • docs/scheduler/tasks/requirements-system.md (0 hunks)
  • docs/scheduler/tasks/task-management-system.md (0 hunks)
  • docs/scheduler/user-guide.md (0 hunks)
  • runelite-client/pom.xml (1 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/Microbot.java (3 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/MicrobotConfig.java (0 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/MicrobotOverlay.java (0 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/MicrobotPlugin.java (2 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/Script.java (0 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/rs2cachedebugger/GroundItemFilterPreset.java (0 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/rs2cachedebugger/NpcFilterPreset.java (0 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/rs2cachedebugger/ObjectFilterPreset.java (0 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/rs2cachedebugger/RenderStyle.java (0 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/rs2cachedebugger/Rs2CacheDebuggerConfig.java (0 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/rs2cachedebugger/Rs2CacheDebuggerGroundItemOverlay.java (0 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/rs2cachedebugger/Rs2CacheDebuggerInfoPanel.java (0 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/rs2cachedebugger/Rs2CacheDebuggerNpcOverlay.java (0 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/rs2cachedebugger/Rs2CacheDebuggerObjectOverlay.java (0 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/rs2cachedebugger/Rs2CacheDebuggerPlugin.java (0 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/schedulable/example/LocationStartNotificationOverlay.java (0 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/schedulable/example/README.md (0 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/schedulable/example/SchedulableExampleConfig.java (0 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/schedulable/example/SchedulableExampleOverlay.java (0 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/schedulable/example/SchedulableExamplePlugin.java (0 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/schedulable/example/SchedulableExamplePrePostScheduleRequirements.java (0 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/schedulable/example/SchedulableExamplePrePostScheduleTasks.java (0 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/schedulable/example/SchedulableExampleScript.java (0 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/schedulable/example/enums/SpellbookOption.java (0 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/schedulable/example/enums/UnifiedLocation.java (0 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/AbstractEntityQueryable.java (1 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/IEntity.java (1 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/IEntityQueryable.java (1 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/actor/Rs2ActorModel.java (1 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/NpcApiExample.java (1 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/Rs2NpcCache.java (1 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/Rs2NpcQueryable.java (1 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/models/Rs2NpcModel.java (1 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/PlayerApiExample.java (1 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/Rs2PlayerCache.java (1 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/Rs2PlayerQueryable.java (1 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/models/Rs2PlayerModel.java (1 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/playerstate/Rs2PlayerStateCache.java (1 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileitem/Rs2TileItemCache.java (1 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileitem/Rs2TileItemQueryable.java (1 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileitem/TileItemApiExample.java (1 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileitem/models/Rs2TileItemModel.java (1 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileobject/Rs2TileObjectCache.java (1 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileobject/Rs2TileObjectQueryable.java (1 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileobject/models/Rs2TileObjectModel.java (1 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileobject/models/TileObjectType.java (1 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerOverlay.java (1 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerScript.java (1 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/example/ExampleScript.java (2 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginManager.java (3 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/pluginscheduler/SchedulerConfig.java (0 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/pluginscheduler/SchedulerInfoOverlay.java (0 hunks)
💤 Files with no reviewable changes (51)
  • docs/scheduler/user-guide.md
  • docs/scheduler/conditions/logical-conditions.md
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/schedulable/example/SchedulableExampleOverlay.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/MicrobotConfig.java
  • docs/scheduler/conditions/resource-conditions.md
  • docs/scheduler/conditions/time-conditions.md
  • docs/scheduler/scheduler-plugin.md
  • docs/scheduler/README.md
  • docs/scheduler/defining-conditions.md
  • docs/scheduler/event/plugin-schedule-entry-soft-stop-event.md
  • docs/scheduler/schedulable-example-plugin.md
  • docs/scheduler/plugin-writers-guide.md
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/schedulable/example/enums/UnifiedLocation.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/schedulable/example/SchedulableExamplePrePostScheduleTasks.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/rs2cachedebugger/Rs2CacheDebuggerInfoPanel.java
  • docs/scheduler/tasks/requirements-system.md
  • docs/scheduler/event/plugin-schedule-entry-finished-event.md
  • docs/scheduler/conditions/location-conditions.md
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/pluginscheduler/SchedulerConfig.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/rs2cachedebugger/Rs2CacheDebuggerGroundItemOverlay.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/schedulable/example/SchedulableExamplePlugin.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/schedulable/example/LocationStartNotificationOverlay.java
  • docs/scheduler/tasks/enhanced-schedulable-plugin-api.md
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/pluginscheduler/SchedulerInfoOverlay.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/schedulable/example/README.md
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/rs2cachedebugger/RenderStyle.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/schedulable/example/SchedulableExamplePrePostScheduleRequirements.java
  • docs/scheduler/api/schedulable-plugin.md
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/MicrobotOverlay.java
  • docs/scheduler/tasks/README.md
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/rs2cachedebugger/Rs2CacheDebuggerObjectOverlay.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/rs2cachedebugger/Rs2CacheDebuggerConfig.java
  • docs/scheduler/tasks/task-management-system.md
  • docs/scheduler/combat-lock-examples.md
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/Script.java
  • docs/scheduler/roadmap.md
  • docs/scheduler/tasks/plugin-writers-guide.md
  • docs/scheduler/tasks/requirements-integration.md
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/rs2cachedebugger/Rs2CacheDebuggerPlugin.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/rs2cachedebugger/GroundItemFilterPreset.java
  • docs/scheduler/conditions/skill-conditions.md
  • docs/scheduler/plugin-schedule-entry-merged.md
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/rs2cachedebugger/Rs2CacheDebuggerNpcOverlay.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/rs2cachedebugger/NpcFilterPreset.java
  • docs/scheduler/predicate-condition-examples.md
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/rs2cachedebugger/ObjectFilterPreset.java
  • docs/scheduler/conditions/npc-conditions.md
  • docs/scheduler/condition-manager.md
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/schedulable/example/SchedulableExampleConfig.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/schedulable/example/enums/SpellbookOption.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/schedulable/example/SchedulableExampleScript.java
🧰 Additional context used
📓 Path-based instructions (6)
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/externalplugins/MicrobotPluginManager.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileobject/Rs2TileObjectQueryable.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/Rs2NpcCache.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerOverlay.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileobject/models/TileObjectType.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileitem/Rs2TileItemQueryable.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileitem/Rs2TileItemCache.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/Rs2NpcQueryable.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/AbstractEntityQueryable.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/PlayerApiExample.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerScript.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileobject/models/Rs2TileObjectModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileobject/Rs2TileObjectCache.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/models/Rs2PlayerModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/IEntity.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/playerstate/Rs2PlayerStateCache.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileitem/models/Rs2TileItemModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/Rs2PlayerQueryable.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/NpcApiExample.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/IEntityQueryable.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/actor/Rs2ActorModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileitem/TileItemApiExample.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/MicrobotPlugin.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/models/Rs2NpcModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/Rs2PlayerCache.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/example/ExampleScript.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/Microbot.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/externalplugins/MicrobotPluginManager.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileobject/Rs2TileObjectQueryable.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/Rs2NpcCache.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerOverlay.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileobject/models/TileObjectType.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileitem/Rs2TileItemQueryable.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileitem/Rs2TileItemCache.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/Rs2NpcQueryable.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/AbstractEntityQueryable.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/PlayerApiExample.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerScript.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileobject/models/Rs2TileObjectModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileobject/Rs2TileObjectCache.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/models/Rs2PlayerModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/IEntity.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/playerstate/Rs2PlayerStateCache.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileitem/models/Rs2TileItemModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/Rs2PlayerQueryable.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/NpcApiExample.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/IEntityQueryable.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/actor/Rs2ActorModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileitem/TileItemApiExample.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/MicrobotPlugin.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/models/Rs2NpcModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/Rs2PlayerCache.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/example/ExampleScript.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/Microbot.java
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.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileobject/Rs2TileObjectQueryable.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/Rs2NpcCache.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerOverlay.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileobject/models/TileObjectType.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileitem/Rs2TileItemQueryable.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileitem/Rs2TileItemCache.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/Rs2NpcQueryable.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/AbstractEntityQueryable.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/PlayerApiExample.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerScript.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileobject/models/Rs2TileObjectModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileobject/Rs2TileObjectCache.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/models/Rs2PlayerModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/IEntity.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/playerstate/Rs2PlayerStateCache.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileitem/models/Rs2TileItemModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/Rs2PlayerQueryable.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/NpcApiExample.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/IEntityQueryable.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/actor/Rs2ActorModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileitem/TileItemApiExample.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/models/Rs2NpcModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/Rs2PlayerCache.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/MicrobotPlugin.java

📄 CodeRabbit inference engine (AGENTS.md)

When adding panel controls or overlays, update the Microbot navigation panel setup in MicrobotPlugin and provide default config values

Files:

  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/MicrobotPlugin.java
runelite-client/src/main/java/net/runelite/client/plugins/microbot/example/**/*.java

📄 CodeRabbit inference engine (AGENTS.md)

Keep runnable examples under .../microbot/example

Files:

  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/example/ExampleScript.java
🧠 Learnings (17)
📚 Learning: 2025-10-16T17:14:29.778Z
Learnt from: CR
Repo: chsami/Microbot PR: 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.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/Rs2NpcCache.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerOverlay.java
  • runelite-client/pom.xml
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/PlayerApiExample.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerScript.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileobject/models/Rs2TileObjectModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileobject/Rs2TileObjectCache.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/models/Rs2PlayerModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/IEntity.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/playerstate/Rs2PlayerStateCache.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileitem/models/Rs2TileItemModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/NpcApiExample.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/actor/Rs2ActorModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileitem/TileItemApiExample.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/MicrobotPlugin.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/models/Rs2NpcModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/Rs2PlayerCache.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/example/ExampleScript.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/Microbot.java
📚 Learning: 2025-10-16T17:14:29.778Z
Learnt from: CR
Repo: chsami/Microbot PR: 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/util/**/*.java : Put shared helpers under .../microbot/util

Applied to files:

  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginManager.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/Rs2NpcCache.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerOverlay.java
  • runelite-client/pom.xml
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/AbstractEntityQueryable.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/PlayerApiExample.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerScript.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileobject/models/Rs2TileObjectModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileobject/Rs2TileObjectCache.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/models/Rs2PlayerModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/IEntity.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/playerstate/Rs2PlayerStateCache.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileitem/models/Rs2TileItemModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/NpcApiExample.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/IEntityQueryable.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/actor/Rs2ActorModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileitem/TileItemApiExample.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/MicrobotPlugin.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/models/Rs2NpcModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/example/ExampleScript.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/Microbot.java
📚 Learning: 2025-10-16T17:14:29.778Z
Learnt from: CR
Repo: chsami/Microbot PR: 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 : Prefix configuration interfaces with the plugin name (e.g., ExampleConfig) within microbot plugins

Applied to files:

  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginManager.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerOverlay.java
  • runelite-client/pom.xml
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/PlayerApiExample.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerScript.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileobject/models/Rs2TileObjectModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/models/Rs2PlayerModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/IEntity.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/NpcApiExample.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/IEntityQueryable.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/actor/Rs2ActorModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileitem/TileItemApiExample.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/MicrobotPlugin.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/models/Rs2NpcModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/example/ExampleScript.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/Microbot.java
📚 Learning: 2025-10-16T17:14:29.778Z
Learnt from: CR
Repo: chsami/Microbot PR: 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
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerOverlay.java
  • runelite-client/pom.xml
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerScript.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/MicrobotPlugin.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/example/ExampleScript.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/Microbot.java
📚 Learning: 2025-10-16T17:14:29.778Z
Learnt from: CR
Repo: chsami/Microbot PR: 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/@(!(util|example))/**/*.java : For new automation scripts, reuse the scheduler pattern demonstrated in ExampleScript

Applied to files:

  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginManager.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerOverlay.java
  • runelite-client/pom.xml
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/PlayerApiExample.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerScript.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/NpcApiExample.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/actor/Rs2ActorModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileitem/TileItemApiExample.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/MicrobotPlugin.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/example/ExampleScript.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/Microbot.java
📚 Learning: 2025-10-16T17:14:29.778Z
Learnt from: CR
Repo: chsami/Microbot PR: 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/example/**/*.java : Keep runnable examples under .../microbot/example

Applied to files:

  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginManager.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerOverlay.java
  • runelite-client/pom.xml
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/PlayerApiExample.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerScript.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/models/Rs2PlayerModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/NpcApiExample.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/actor/Rs2ActorModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileitem/TileItemApiExample.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/MicrobotPlugin.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/example/ExampleScript.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/Microbot.java
📚 Learning: 2025-08-23T16:17:37.615Z
Learnt from: g-mason0
Repo: chsami/Microbot PR: 1423
File: runelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginManager.java:366-389
Timestamp: 2025-08-23T16:17:37.615Z
Learning: The ScheduledExecutorService injected into MicrobotPluginManager (and other RuneLite classes) is configured as a single-threaded executor via Executors.newSingleThreadScheduledExecutor() at RuneLiteModule.java line 130, wrapped in ExecutorServiceExceptionLogger. This ensures all async tasks execute sequentially, preventing race conditions.

Applied to files:

  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginManager.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerOverlay.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerScript.java
📚 Learning: 2025-09-03T03:59:10.180Z
Learnt from: g-mason0
Repo: chsami/Microbot PR: 1462
File: runelite-client/src/main/java/net/runelite/client/plugins/microbot/ui/MicrobotPluginHubPanel.java:343-344
Timestamp: 2025-09-03T03:59:10.180Z
Learning: In MicrobotPluginManager, the public methods installPlugin(), removePlugin(), and update() already use executor.submit() internally to perform their operations asynchronously, making them non-blocking on the EDT. These are wrapper methods that delegate to the actual implementation methods (install(), remove(), refresh()) via the executor.

Applied to files:

  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginManager.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerOverlay.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerScript.java
📚 Learning: 2025-08-23T06:16:24.647Z
Learnt from: Voxsylvae
Repo: chsami/Microbot PR: 1415
File: runelite-client/src/main/java/net/runelite/client/plugins/microbot/VoxPlugins/schedulable/example/SchedulableExamplePlugin.java:275-281
Timestamp: 2025-08-23T06:16:24.647Z
Learning: In the Microbot plugin scheduler framework, when using AbstractPrePostScheduleTasks, error handling and reporting for pre-schedule and post-schedule tasks is already managed by the handlePreTaskCompletion and handlePostTaskCompletion methods. These methods automatically handle exceptions and report failures via ExecutionResult. Additional error reporting in catch blocks when calling runPreScheduleTasks() or runPostScheduleTasks() is redundant and should be avoided.

Applied to files:

  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginManager.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerScript.java
📚 Learning: 2025-09-03T04:18:27.289Z
Learnt from: g-mason0
Repo: chsami/Microbot PR: 1462
File: runelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginManager.java:985-1010
Timestamp: 2025-09-03T04:18:27.289Z
Learning: In MicrobotPluginManager, hash verification is performed during refresh() rather than download to avoid false positives. JAR files built on GitHub runners with different OS/JDK versions can produce different hashes than local builds, so comparing downloaded bytes against manifest hash would cause legitimate files to fail verification. Instead, the system saves MicrobotPluginManifest copies in installedPlugins profile key and uses verifyHash() method to compare saved local manifest hash against current authoritative manifest hash.

Applied to files:

  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginManager.java
📚 Learning: 2025-09-10T01:10:09.440Z
Learnt from: T-edit
Repo: chsami/Microbot PR: 1500
File: runelite-client/src/main/java/net/runelite/client/plugins/microbot/tempoross/TemporossScript.java:674-679
Timestamp: 2025-09-10T01:10:09.440Z
Learning: Rs2NpcModel implements the NPC interface (extends ActorModel implements NPC), so instanceof NPC returns true for Rs2NpcModel instances. When Rs2Player.getInteracting() returns Rs2NpcModel objects, they can be safely cast to NPC.

Applied to files:

  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/Rs2NpcCache.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/Rs2NpcQueryable.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/models/Rs2PlayerModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileitem/models/Rs2TileItemModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/NpcApiExample.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/actor/Rs2ActorModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/models/Rs2NpcModel.java
📚 Learning: 2025-09-10T01:10:09.440Z
Learnt from: T-edit
Repo: chsami/Microbot PR: 1500
File: runelite-client/src/main/java/net/runelite/client/plugins/microbot/tempoross/TemporossScript.java:674-679
Timestamp: 2025-09-10T01:10:09.440Z
Learning: Rs2NpcModel is an NPC class, so `instanceof NPC` returns true for Rs2NpcModel instances. When reviewing code that checks `instanceof NPC` on objects that might be Rs2NpcModel, the check will work correctly.

Applied to files:

  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/Rs2NpcCache.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/Rs2NpcQueryable.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/models/Rs2PlayerModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileitem/models/Rs2TileItemModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/NpcApiExample.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/actor/Rs2ActorModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/models/Rs2NpcModel.java
📚 Learning: 2025-08-25T07:26:53.623Z
Learnt from: Voxsylvae
Repo: chsami/Microbot PR: 1415
File: runelite-client/src/main/java/net/runelite/client/plugins/microbot/pluginscheduler/SchedulerPlugin.java:2341-2366
Timestamp: 2025-08-25T07:26:53.623Z
Learning: In SchedulerPlugin.startLoginMonitoringThread(), do not gate startup on isBreakHandlerEnabled(); rely on isOnBreak() to suppress the monitor only when a break is actually active. This avoids blocking login monitoring whenever BreakHandler is merely enabled.

Applied to files:

  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerOverlay.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerScript.java
📚 Learning: 2025-08-26T14:31:41.066Z
Learnt from: Voxsylvae
Repo: chsami/Microbot PR: 1415
File: runelite-client/src/main/java/net/runelite/client/plugins/microbot/TaF/GiantSeaweedFarmer/GiantSeaweedFarmerPlugin.java:84-103
Timestamp: 2025-08-26T14:31:41.066Z
Learning: In GiantSeaweedFarmerPlugin's post-schedule task event handler, when lockCondition is active, the event should be ignored rather than unlocking and stopping. The lock should only be released by the code that originally acquired it to maintain thread safety during critical operations.

Applied to files:

  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerOverlay.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerScript.java
📚 Learning: 2025-08-31T19:19:07.691Z
Learnt from: chsami
Repo: chsami/Microbot PR: 1455
File: runelite-client/src/main/java/net/runelite/client/plugins/microbot/MicrobotVersionChecker.java:112-132
Timestamp: 2025-08-31T19:19:07.691Z
Learning: The Microbot project uses only numeric versioning (e.g., "1.2.3") without any alphanumeric suffixes like "-beta" or "-alpha", so simple integer parsing of version segments is safe.

Applied to files:

  • runelite-client/pom.xml
📚 Learning: 2025-08-25T15:51:39.272Z
Learnt from: runsonmypc
Repo: chsami/Microbot PR: 1417
File: runelite-client/src/main/java/net/runelite/client/plugins/microbot/agility/AgilityScript.java:13-13
Timestamp: 2025-08-25T15:51:39.272Z
Learning: Both net.runelite.api.ItemID and net.runelite.api.gameval.ItemID are valid import paths in the RuneLite codebase. The microbot plugins consistently use net.runelite.api.ItemID as their established pattern.

Applied to files:

  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileitem/models/Rs2TileItemModel.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileitem/TileItemApiExample.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/MicrobotPlugin.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/example/ExampleScript.java
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/Microbot.java
📚 Learning: 2025-10-16T17:14:29.778Z
Learnt from: CR
Repo: chsami/Microbot PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-16T17:14:29.778Z
Learning: Use RuneLite’s dependency injection to share logic via util classes rather than duplicating inside scripts

Applied to files:

  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/example/ExampleScript.java
🧬 Code graph analysis (14)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileobject/Rs2TileObjectQueryable.java (3)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/AbstractEntityQueryable.java (1)
  • AbstractEntityQueryable (19-170)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileobject/models/Rs2TileObjectModel.java (1)
  • Rs2TileObjectModel (23-269)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileobject/Rs2TileObjectCache.java (1)
  • Rs2TileObjectCache (13-67)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileobject/models/TileObjectType.java (1)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/tileobject/TileObjectType.java (1)
  • TileObjectType (3-9)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileitem/Rs2TileItemQueryable.java (1)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/AbstractEntityQueryable.java (1)
  • AbstractEntityQueryable (19-170)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/Rs2NpcQueryable.java (2)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/AbstractEntityQueryable.java (1)
  • AbstractEntityQueryable (19-170)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/Rs2NpcCache.java (1)
  • Rs2NpcCache (11-41)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/PlayerApiExample.java (1)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/Rs2PlayerCache.java (1)
  • Rs2PlayerCache (12-42)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileobject/models/Rs2TileObjectModel.java (2)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/equipment/Rs2Equipment.java (1)
  • Rs2Equipment (25-392)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/menu/NewMenuEntry.java (1)
  • NewMenuEntry (11-317)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileobject/Rs2TileObjectCache.java (1)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileobject/models/Rs2TileObjectModel.java (1)
  • Rs2TileObjectModel (23-269)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/models/Rs2PlayerModel.java (3)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/actor/Rs2ActorModel.java (1)
  • Getter (16-435)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/models/Rs2NpcModel.java (1)
  • Getter (19-206)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/player/Rs2PlayerModel.java (1)
  • Getter (12-88)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileitem/models/Rs2TileItemModel.java (3)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/menu/NewMenuEntry.java (1)
  • NewMenuEntry (11-317)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/reflection/Rs2Reflection.java (1)
  • Rs2Reflection (22-131)
runelite-api/src/main/java/net/runelite/api/Perspective.java (1)
  • Perspective (62-1159)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/Rs2PlayerQueryable.java (2)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/AbstractEntityQueryable.java (1)
  • AbstractEntityQueryable (19-170)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/Rs2PlayerCache.java (1)
  • Rs2PlayerCache (12-42)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/NpcApiExample.java (1)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/Rs2NpcCache.java (1)
  • Rs2NpcCache (11-41)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/actor/Rs2ActorModel.java (2)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/models/Rs2NpcModel.java (1)
  • Getter (19-206)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/models/Rs2PlayerModel.java (1)
  • Getter (12-98)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/models/Rs2NpcModel.java (3)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/actor/Rs2ActorModel.java (1)
  • Getter (16-435)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/models/Rs2PlayerModel.java (1)
  • Getter (12-98)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/npc/Rs2NpcModel.java (1)
  • Getter (19-196)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/example/ExampleScript.java (5)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/Rs2NpcCache.java (1)
  • Rs2NpcCache (11-41)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileobject/Rs2TileObjectCache.java (1)
  • Rs2TileObjectCache (13-67)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/player/Rs2PlayerCache.java (1)
  • Rs2PlayerCache (12-42)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/Microbot.java (1)
  • Slf4j (78-784)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileitem/models/Rs2TileItemModel.java (1)
  • Slf4j (17-260)
🪛 GitHub Actions: CI
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/NpcApiExample.java

[error] 21-21: incompatible types: net.runelite.client.plugins.microbot.api.npc.models.Rs2NpcModel cannot be converted to net.runelite.client.plugins.microbot.util.npc.Rs2NpcModel


[error] 24-24: incompatible types: net.runelite.client.plugins.microbot.api.npc.models.Rs2NpcModel cannot be converted to net.runelite.client.plugins.microbot.util.npc.Rs2NpcModel


[error] 27-27: incompatible types: net.runelite.client.plugins.microbot.api.npc.models.Rs2NpcModel cannot be converted to net.runelite.client.plugins.microbot.util.npc.Rs2NpcModel


[error] 30-30: incompatible types: net.runelite.client.plugins.microbot.api.npc.models.Rs2NpcModel cannot be converted to net.runelite.client.plugins.microbot.util.npc.Rs2NpcModel


[error] 33-33: incompatible types: net.runelite.client.plugins.microbot.api.npc.models.Rs2NpcModel cannot be converted to net.runelite.client.plugins.microbot.util.npc.Rs2NpcModel


[error] 36-36: incompatible types: net.runelite.client.plugins.microbot.api.npc.models.Rs2NpcModel cannot be converted to net.runelite.client.plugins.microbot.util.npc.Rs2NpcModel


[error] 41-41: incompatible types: java.util.List<net.runelite.client.plugins.microbot.api.npc.models.Rs2NpcModel> cannot be converted to java.util.List<net.runelite.client.plugins.microbot.util.npc.Rs2NpcModel>


[error] 47-47: incompatible types: net.runelite.client.plugins.microbot.api.npc.models.Rs2NpcModel cannot be converted to net.runelite.client.plugins.microbot.util.npc.Rs2NpcModel


[error] 52-52: incompatible types: net.runelite.client.plugins.microbot.api.npc.models.Rs2NpcModel cannot be converted to net.runelite.client.plugins.microbot.util.npc.Rs2NpcModel


[error] 58-58: incompatible types: net.runelite.client.plugins.microbot.api.npc.models.Rs2NpcModel cannot be converted to net.runelite.client.plugins.microbot.util.npc.Rs2NpcModel


[error] 62-62: incompatible types: net.runelite.client.plugins.microbot.api.npc.models.Rs2NpcModel cannot be converted to net.runelite.client.plugins.microbot.util.npc.Rs2NpcModel


[error] 69-69: invalid method reference: isMoving in class net.runelite.client.plugins.microbot.util.npc.Rs2NpcModel cannot be applied to given types; expected no arguments, found Rs2NpcModel

⏰ 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

Comment on lines 53 to 76
public Q within(int distance) {
WorldPoint playerLoc = getPlayerLocation();
if (playerLoc == null) {
return null;
}

this.source = this.source
.filter(o -> o.getWorldLocation().distanceTo(playerLoc) <= distance);

return (Q) this;
}

@SuppressWarnings("unchecked")
@Override
public Q within(WorldPoint anchor, int distance) {
if (anchor == null) {
return null;
}

this.source = this.source
.filter(o -> o.getWorldLocation().distanceTo(anchor) <= distance);

return (Q) this;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Make within* always return the queryable and consistently guard null player location

There are a couple of logic inconsistencies in the query API:

  1. within(...) sometimes returns null instead of the queryable.

    • within(int distance) and within(WorldPoint anchor, int distance) return null when the player location or anchor is null, while where(...) and other filters always return (Q) this.
    • That makes chains like query().within(10).withName("Tree") blow up with an NPE if getPlayerLocation() happens to be null.
  2. Name/ID helpers assume a non‑null player location, unlike nearest/within.

    • withName, withNames, withId, and withIds all call Rs2Player.getWorldLocation() inside a distance comparator with no null check.
    • nearest()/nearest(int) explicitly bail out if the player location is null, so behavior here is inconsistent and can NPE when not logged in.

A safer, more consistent approach would be:

  • Make within(...) always return this, and if the player location/anchor is null, either:
    • leave source unchanged (no filtering), or
    • set source = Stream.empty() so downstream ops just see no results.
  • For the name/ID methods, reuse getPlayerLocation() and handle a null anchor similarly to nearest(); if there’s no location, either:
    • return the first matching entity without distance ordering, or
    • return null early without touching the stream.

For example:

    @SuppressWarnings("unchecked")
    @Override
    public Q within(int distance) {
        WorldPoint playerLoc = getPlayerLocation();
-       if (playerLoc == null) {
-           return null;
-       }
-
-       this.source = this.source
-               .filter(o -> o.getWorldLocation().distanceTo(playerLoc) <= distance);
-
-       return (Q) this;
+       if (playerLoc != null) {
+           this.source = this.source
+                   .filter(o -> o.getWorldLocation().distanceTo(playerLoc) <= distance);
+       }
+       return (Q) this;
    }

    @Override
    public E withName(String name) {
        if (name == null) return null;
-       return Microbot.getClientThread().invoke(() -> {
-           return source.filter(x -> {
+       WorldPoint playerLoc = getPlayerLocation();
+       if (playerLoc == null) return null;
+
+       return Microbot.getClientThread().invoke(() -> {
+           return source.filter(x -> {
                        String n = x.getName();
                        return n != null && n.equalsIgnoreCase(name);
                    })
-                   .min(java.util.Comparator.comparingInt(o -> o.getWorldLocation().distanceTo(Rs2Player.getWorldLocation())))
+                   .min(java.util.Comparator.comparingInt(o -> o.getWorldLocation().distanceTo(playerLoc)))
                    .orElse(null);
        });
    }

and apply the same pattern to within(WorldPoint, int), withNames, withId, and withIds.

Also applies to: 124-164

Comment on lines +233 to +236
public void setActionFrame(int frame)
{
actor.setAnimationFrame(frame);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

setActionFrame delegates to the wrong underlying method

setActionFrame(int frame) currently calls actor.setAnimationFrame(frame), so any caller intending to change the action frame will instead modify the animation frame:

@Override
public void setActionFrame(int frame)
{
    actor.setAnimationFrame(frame);
}

This is inconsistent with the Actor API and with setAnimationFrame, which already delegates to actor.setAnimationFrame.

Suggested fix:

-    public void setActionFrame(int frame)
-    {
-        actor.setAnimationFrame(frame);
-    }
+    public void setActionFrame(int frame)
+    {
+        actor.setActionFrame(frame);
+    }
🤖 Prompt for AI Agents
In
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/actor/Rs2ActorModel.java
around lines 233 to 236, setActionFrame(int frame) incorrectly delegates to
actor.setAnimationFrame(frame); change the delegation to call
actor.setActionFrame(frame) so the action frame is updated (or, if the
underlying actor API uses a different method name, call the correct actor method
for setting the action frame and ensure the method signature matches).

Comment on lines +159 to +167
public static Predicate<Rs2NpcModel> matches(boolean exact, String... names) {
return npc -> {
String npcName = npc.getName();
if (npcName == null) return false;
if (exact) npcName = npcName.toLowerCase();
final String name = npcName;
return exact ? Arrays.stream(names).anyMatch(name::equalsIgnoreCase) :
Arrays.stream(names).anyMatch(s -> name.contains(s.toLowerCase()));
};
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Partial name matching is effectively case‑sensitive on the NPC name

In matches(boolean exact, String... names):

if (exact) npcName = npcName.toLowerCase();
final String name = npcName;
return exact ? Arrays.stream(names).anyMatch(name::equalsIgnoreCase) :
        Arrays.stream(names).anyMatch(s -> name.contains(s.toLowerCase()));

For exact == false, only s is lower‑cased; name remains in its original case. This makes the substring check unintentionally case‑sensitive on the NPC name.

To make behavior consistent (case‑insensitive in both modes), consider:

-        return npc -> {
-            String npcName = npc.getName();
-            if (npcName == null) return false;
-            if (exact) npcName = npcName.toLowerCase();
-            final String name = npcName;
-            return exact ? Arrays.stream(names).anyMatch(name::equalsIgnoreCase) :
-                    Arrays.stream(names).anyMatch(s -> name.contains(s.toLowerCase()));
-        };
+        return npc -> {
+            String npcName = npc.getName();
+            if (npcName == null) {
+                return false;
+            }
+            String nameLower = npcName.toLowerCase();
+            if (exact) {
+                return Arrays.stream(names)
+                        .anyMatch(s -> nameLower.equals(s.toLowerCase()));
+            }
+            return Arrays.stream(names)
+                    .map(String::toLowerCase)
+                    .anyMatch(nameLower::contains);
+        };

This keeps exact semantics but avoids surprising case behavior in the partial‑match branch.

🤖 Prompt for AI Agents
In
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/models/Rs2NpcModel.java
around lines 159 to 167, the partial-match branch currently uses the NPC's
original case while only lower-casing the supplied names, causing unintended
case-sensitive substring checks; fix this by normalizing the NPC name to
lower-case once (after null check) into a local variable and then perform both
exact and partial comparisons against the supplied names after lower-casing them
(e.g., exact: compare name.equals(lowercasedCandidate); partial:
name.contains(lowercasedCandidate)), ensuring case-insensitive behavior in both
modes.

@@ -0,0 +1,71 @@
package net.runelite.client.plugins.microbot.api.npc;

import net.runelite.client.plugins.microbot.util.npc.Rs2NpcModel;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Wrong import causes type mismatch throughout the file.

Line 3 imports net.runelite.client.plugins.microbot.util.npc.Rs2NpcModel, but the Rs2NpcCache returns net.runelite.client.plugins.microbot.api.npc.models.Rs2NpcModel instances. This mismatch causes all 12 compilation errors reported by the pipeline.

Apply this diff to fix the import:

-import net.runelite.client.plugins.microbot.util.npc.Rs2NpcModel;
+import net.runelite.client.plugins.microbot.api.npc.models.Rs2NpcModel;
📝 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.

Suggested change
import net.runelite.client.plugins.microbot.util.npc.Rs2NpcModel;
import net.runelite.client.plugins.microbot.api.npc.models.Rs2NpcModel;
🤖 Prompt for AI Agents
In
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/NpcApiExample.java
around line 3, the file imports
net.runelite.client.plugins.microbot.util.npc.Rs2NpcModel which mismatches the
Rs2NpcCache return type; change the import to
net.runelite.client.plugins.microbot.api.npc.models.Rs2NpcModel so the types
align, update any import statement accordingly, then rebuild to confirm the 12
compilation errors are resolved.

Comment on lines 13 to 39
private static int lastUpdateNpcs = 0;
private static List<Rs2NpcModel> npcs = new ArrayList<>();

public Rs2NpcQueryable query() {
return new Rs2NpcQueryable();
}

/**
* Get all NPCs in the current scene
*
* @return Stream of Rs2NpcModel
*/
public static Stream<Rs2NpcModel> getNpcsStream() {

if (lastUpdateNpcs >= Microbot.getClient().getTickCount()) {
return npcs.stream();
}

List<Rs2NpcModel> result = Microbot.getClientThread().invoke(() -> Microbot
.getClient()
.getTopLevelWorldView()
.npcs().stream().map(Rs2NpcModel::new)
.collect(Collectors.toList()));

npcs = result;
lastUpdateNpcs = Microbot.getClient().getTickCount();
return result.stream();
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Cache may never populate on first tick due to lastUpdateNpcs initialization

With lastUpdateNpcs starting at 0 and the check lastUpdateNpcs >= Microbot.getClient().getTickCount(), a first call when getTickCount() is 0 will treat the empty cache as “fresh” and skip population, returning an empty stream even though NPCs exist.

Consider using a sentinel value or adjusting the comparison, e.g.:

-    private static int lastUpdateNpcs = 0;
+    private static int lastUpdateNpcs = -1;

This ensures the first call actually populates the cache.

🤖 Prompt for AI Agents
In
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/npc/Rs2NpcCache.java
around lines 13-39, the cache check uses lastUpdateNpcs initialized to 0 with
the condition lastUpdateNpcs >= Microbot.getClient().getTickCount(), which
causes the cache to be treated as fresh when tickCount is 0 and prevents initial
population; fix by initializing lastUpdateNpcs to a sentinel like -1 (so the
first call will populate) or change the comparison to strictly greater-than
(lastUpdateNpcs > Microbot.getClient().getTickCount()) so the first tick (0)
will not skip population.

Comment on lines 201 to 236
int index = 0;
String objName = "";
if (action != null) {
//performance improvement to only get compoisiton if action has been specified
var objComp = getObjectComposition();
String[] actions;
if (objComp.getImpostorIds() != null && objComp.getImpostor() != null) {
actions = objComp.getImpostor().getActions();
} else {
actions = objComp.getActions();
}

for (int i = 0; i < actions.length; i++) {
if (actions[i] == null) continue;
if (action.equalsIgnoreCase(Rs2UiHelper.stripColTags(actions[i]))) {
index = i;
break;
}
}

if (index == actions.length)
index = 0;

objName = objComp.getName();

// both hands must be free before using MINECART
if (objComp.getName().toLowerCase().contains("train cart")) {
Rs2Equipment.unEquip(EquipmentInventorySlot.WEAPON);
Rs2Equipment.unEquip(EquipmentInventorySlot.SHIELD);
sleepUntil(() -> Rs2Equipment.get(EquipmentInventorySlot.WEAPON) == null && Rs2Equipment.get(EquipmentInventorySlot.SHIELD) == null);
}
}

if (index == -1) {
Microbot.log("Failed to interact with object " + getId() + " " + action);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Action index sentinel logic is inconsistent and never reports “action not found”

index is initialised to 0 and only ever assigned from the loop variable i (0..actions.length - 1). That makes both:

  • if (index == actions.length) index = 0;
  • if (index == -1) { Microbot.log(...); }

effectively dead code. As a result, when action doesn’t match any of the object’s actions, index stays 0 and click("MissingAction") silently falls back to the first menu option rather than signalling failure.

If you want to detect “no matching action” explicitly, consider using a real sentinel and handling it before building the menu entry, e.g.:

-            int index = 0;
+            int index = 0;
             String objName = "";
-            if (action != null) {
+            if (action != null) {
                 //performance improvement to only get compoisiton if action has been specified
                 var objComp = getObjectComposition();
                 String[] actions;
                 if (objComp.getImpostorIds() != null && objComp.getImpostor() != null) {
                     actions = objComp.getImpostor().getActions();
                 } else {
                     actions = objComp.getActions();
                 }
-
-                for (int i = 0; i < actions.length; i++) {
+                int matchedIndex = -1;
+                for (int i = 0; i < actions.length; i++) {
                     if (actions[i] == null) continue;
                     if (action.equalsIgnoreCase(Rs2UiHelper.stripColTags(actions[i]))) {
-                        index = i;
-                        break;
+                        matchedIndex = i;
+                        break;
                     }
                 }
-
-                if (index == actions.length)
-                    index = 0;
+                if (matchedIndex == -1) {
+                    Microbot.log("Failed to interact with object " + getId() + " " + action);
+                    return false;
+                }
+                index = matchedIndex;
 
                 objName = objComp.getName();
@@
-            if (index == -1) {
-                Microbot.log("Failed to interact with object " + getId() + " " + action);
-            }
+            // at this point index is guaranteed to be a valid option index

Adjust the exact fallback behaviour if you do want unknown actions to default to the first option, but as written the current checks are inconsistent and never fire.

🤖 Prompt for AI Agents
In
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileobject/models/Rs2TileObjectModel.java
around lines 201-236, the action index uses 0 as the initial value so “no match”
is indistinguishable from matching the first action; initialize index to -1, set
index = i when a match is found in the loop (leave loop logic), remove or adjust
the meaningless check that compares index to actions.length, and after the loop
explicitly check if index == -1 to log the failure and abort/return before
building the menu entry (or, if you intentionally want to fall back to the first
option, explicitly set index = 0 in that branch so the fallback is obvious).
Ensure null/empty actions are handled and that the rest of the method uses the
updated index sentinel consistently.

Comment on lines +3 to +9
public enum TileObjectType {
GAME,
WALL,
DECORATIVE,
GROUND,
GENERIC
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Duplicate enum definition.

This enum is duplicated at runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/tileobject/TileObjectType.java with identical constants. Having two identical enums in different packages will cause type incompatibility issues when code expects one type but receives the other.

🤖 Prompt for AI Agents
In
runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/tileobject/models/TileObjectType.java
lines 3-9 there is a duplicate enum definition identical to
runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/tileobject/TileObjectType.java;
remove this duplicate file (or replace its usages) and consolidate to a single
enum to avoid type incompatibility: delete this enum, update all imports/usages
to reference the canonical TileObjectType (choose the util package or move the
enum to a common shared package), then run a project-wide import/refactor to fix
compile errors and ensure only one enum definition remains.

Comment on lines 26 to 66
public static Stream<Rs2TileObjectModel> getObjectsStream() {

if (lastUpdateObjects >= Microbot.getClient().getTickCount()) {
return tileObjects.stream();
}

Player player = Microbot.getClient().getLocalPlayer();
if (player == null) return Stream.empty();

List<Rs2TileObjectModel> result = new ArrayList<>();

var tileValues = Microbot.getClient().getTopLevelWorldView().getScene().getTiles()[Microbot.getClient().getTopLevelWorldView().getPlane()];

for (Tile[] tileValue : tileValues) {
for (Tile tile : tileValue) {
if (tile == null) continue;

if (tile.getGameObjects() != null) {
for (GameObject gameObject : tile.getGameObjects()) {
if (gameObject == null) continue;
if (gameObject.getSceneMinLocation().equals(tile.getSceneLocation())) {
result.add(new Rs2TileObjectModel(gameObject));
}
}
}
if (tile.getGroundObject() != null) {
result.add(new Rs2TileObjectModel(tile.getGroundObject()));
}
if (tile.getWallObject() != null) {
result.add(new Rs2TileObjectModel(tile.getWallObject()));
}
if (tile.getDecorativeObject() != null) {
result.add(new Rs2TileObjectModel(tile.getDecorativeObject()));
}
}
}

tileObjects = result;
lastUpdateObjects = Microbot.getClient().getTickCount();
return result.stream();
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Run scene tile traversal on the client thread to avoid race conditions

getObjectsStream reads getTopLevelWorldView().getScene().getTiles() directly from whatever thread calls it (e.g., ExampleScript’s scheduler), while other caches (like Rs2NpcCache) do this work via Microbot.getClientThread().invoke(...). That inconsistency can violate RuneLite’s client‑thread rules and cause flaky crashes or corrupted reads.

Consider moving the scene iteration into a client‑thread invocation and using its result as the cache, e.g.:

     public static Stream<Rs2TileObjectModel> getObjectsStream() {

         if (lastUpdateObjects >= Microbot.getClient().getTickCount()) {
             return tileObjects.stream();
         }

-        Player player = Microbot.getClient().getLocalPlayer();
-        if (player == null) return Stream.empty();
-
-        List<Rs2TileObjectModel> result = new ArrayList<>();
-
-        var tileValues = Microbot.getClient().getTopLevelWorldView().getScene().getTiles()[Microbot.getClient().getTopLevelWorldView().getPlane()];
-
-        for (Tile[] tileValue : tileValues) {
-            for (Tile tile : tileValue) {
-                if (tile == null) continue;
-
-                if (tile.getGameObjects() != null) {
-                    for (GameObject gameObject : tile.getGameObjects()) {
-                        if (gameObject == null) continue;
-                        if (gameObject.getSceneMinLocation().equals(tile.getSceneLocation())) {
-                            result.add(new Rs2TileObjectModel(gameObject));
-                        }
-                    }
-                }
-                if (tile.getGroundObject() != null) {
-                    result.add(new Rs2TileObjectModel(tile.getGroundObject()));
-                }
-                if (tile.getWallObject() != null) {
-                    result.add(new Rs2TileObjectModel(tile.getWallObject()));
-                }
-                if (tile.getDecorativeObject() != null)  {
-                    result.add(new Rs2TileObjectModel(tile.getDecorativeObject()));
-                }
-            }
-        }
-
-        tileObjects = result;
+        List<Rs2TileObjectModel> result = Microbot.getClientThread().invoke(() -> {
+            Player player = Microbot.getClient().getLocalPlayer();
+            if (player == null) {
+                return null;
+            }
+
+            List<Rs2TileObjectModel> tmp = new ArrayList<>();
+            var worldView = Microbot.getClient().getTopLevelWorldView();
+            var tileValues = worldView.getScene().getTiles()[worldView.getPlane()];
+
+            for (Tile[] tileRow : tileValues) {
+                for (Tile tile : tileRow) {
+                    if (tile == null) {
+                        continue;
+                    }
+
+                    if (tile.getGameObjects() != null) {
+                        for (GameObject gameObject : tile.getGameObjects()) {
+                            if (gameObject == null) {
+                                continue;
+                            }
+                            if (gameObject.getSceneMinLocation().equals(tile.getSceneLocation())) {
+                                tmp.add(new Rs2TileObjectModel(gameObject));
+                            }
+                        }
+                    }
+                    if (tile.getGroundObject() != null) {
+                        tmp.add(new Rs2TileObjectModel(tile.getGroundObject()));
+                    }
+                    if (tile.getWallObject() != null) {
+                        tmp.add(new Rs2TileObjectModel(tile.getWallObject()));
+                    }
+                    if (tile.getDecorativeObject() != null) {
+                        tmp.add(new Rs2TileObjectModel(tile.getDecorativeObject()));
+                    }
+                }
+            }
+
+            return tmp;
+        });
+
+        if (result == null) {
+            return Stream.empty();
+        }
+
+        tileObjects = result;
         lastUpdateObjects = Microbot.getClient().getTickCount();
         return result.stream();
     }

Comment on lines +64 to +67
panelComponent.getChildren().add(LineComponent.builder()
.left("Reason: Plugin Lock Condition Active")
.leftColor(Color.ORANGE)
.build());
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

Verify that manual locks are no longer supported.

The hardcoded message "Plugin Lock Condition Active" assumes only plugin-based locks exist. If BreakHandlerScript still supports manual locks, this message would be misleading when a manual lock is active.

Run the following script to check if manual lock functionality still exists in BreakHandlerScript:


🏁 Script executed:

#!/bin/bash
# Description: Search for manual lock methods and fields in BreakHandlerScript

# Search for manual lock related methods and fields
rg -nP --type=java -C5 'manual.*[Ll]ock|setLock|lockManual' runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerScript.java

Length of output: 968


Verify that manual locks are no longer supported, or fix the hardcoded message.

The javadoc at line 899 of BreakHandlerScript states the lock includes "both the manual lock state and any locked conditions from schedulable plugins." However, the overlay always displays "Plugin Lock Condition Active" regardless of lock type, which would be misleading when a manual lock is active.

🤖 Prompt for AI Agents
In
runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerOverlay.java
around lines 64-67, the overlay hardcodes "Reason: Plugin Lock Condition Active"
which mislabels manual locks; change the logic to determine the actual lock type
from the BreakHandler/BreakHandlerScript (e.g., check a provided isManualLock()
or getLockType()/getLockReason() method) and set the displayed text accordingly
— e.g., "Reason: Manual Lock Active" when a manual lock is present, otherwise
keep "Reason: Plugin Lock Condition Active"; update the leftColor if desired to
keep visual distinction.

Comment on lines 15 to 25
/**
* Performance test script for measuring GameObject composition retrieval speed.
*
* <p>
* This script runs every 5 seconds and performs the following:
* - Gets all GameObjects in the scene
* - Retrieves the ObjectComposition for each GameObject
* - Measures and logs the total time taken
* - Reports average time per object
*
* <p>
* Useful for performance profiling and optimization testing.
*/
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Update Javadoc to match the new cache‑based behavior

The class comment still describes a GameObject/ObjectComposition performance test, but the implementation now benchmarks fetching players, NPCs, tile objects, and ground items via the new caches and only logs counts + total time. It’d be less confusing to rewrite the Javadoc to reflect what the script actually does now.

🤖 Prompt for AI Agents
In
runelite-client/src/main/java/net/runelite/client/plugins/microbot/example/ExampleScript.java
around lines 15 to 25, the class Javadoc still describes a
GameObject/ObjectComposition performance test but the implementation now
benchmarks cache-based retrieval of players, NPCs, tile objects, and ground
items and logs counts plus total time; update the Javadoc to accurately describe
the current behavior: state that it runs every 5 seconds, fetches players, NPCs,
tile objects and ground items from their caches, measures total elapsed time for
the fetches, and logs the counts and total time (and remove any mention of
GameObject/ObjectComposition composition retrieval). Ensure the description is
concise, mentions it’s for performance benchmarking/profiling, and reflects the
current outputs (counts + total time).

# Conflicts:
#	runelite-client/pom.xml
…orkTree1

# Conflicts:
#	runelite-client/pom.xml
#	runelite-client/src/main/java/net/runelite/client/plugins/microbot/Microbot.java
#	runelite-client/src/main/java/net/runelite/client/plugins/microbot/example/ExampleScript.java
# Conflicts:
#	runelite-client/pom.xml
#	runelite-client/src/main/java/net/runelite/client/plugins/microbot/Microbot.java
#	runelite-client/src/main/java/net/runelite/client/plugins/microbot/example/ExampleScript.java
# Conflicts:
#	runelite-client/pom.xml
#	runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/tileobject/Rs2TileObjectModel.java
# Conflicts:
#	runelite-client/pom.xml
#	runelite-client/src/main/java/net/runelite/client/plugins/microbot/MicrobotPlugin.java
#	runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/security/LoginManager.java
# Conflicts:
#	runelite-client/pom.xml
# Conflicts:
#	runelite-client/pom.xml
#	runelite-client/src/main/java/net/runelite/client/plugins/microbot/example/ExampleScript.java
#	runelite-client/src/main/java/net/runelite/client/plugins/microbot/pluginscheduler/tasks/requirements/registry/RequirementRegistry.java
@chsami chsami merged commit 1daad97 into development Dec 27, 2025
3 checks passed
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.

1 participant