Conversation
…in and world selection
This commit adds actions for the Gold sink, Crystal throne, and Demonic throne. While players basically never build these items during normal gameplay, it can be useful for calculating xp gains during temporary game modes where gp is plentiful. (Leagues and Grid Master, for instance)
The canvas position doesn't really need to be computed, using the cross product of the projected points also works
# Conflicts: # runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java
WalkthroughThis pull request introduces comprehensive updates spanning both the RuneLite API and client. The API additions include click action constants, new world entity and menu action enums, additional tile object accessors, world view orientation methods, and model face color data. The client changes refactor GPU rendering components from static to instance-based, implement a new Break Handler v2 feature with profile-based login and world selection, extend microbot plugin management with version tracking and repository support, add sailing-related content to multiple plugins and skill calculators, and expand world map functionality with mooring locations and level requirements. Possibly related PRs
Pre-merge checks and finishing touches❌ Failed checks (2 warnings, 1 inconclusive)
✨ 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: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
runelite-client/pom.xml (1)
472-472: Remove extraneous character that corrupts XML syntax.Line 472 contains "§y" after the closing tag, which will cause XML parsing failures during the Maven build.
Apply this diff to fix the XML corruption:
- <exclude>META-INF/*.DSA</exclude>§y + <exclude>META-INF/*.DSA</exclude>runelite-client/src/main/java/net/runelite/client/plugins/implings/ImplingsOverlay.java (1)
44-67: Guard againstnulllocalPlayer before region check
rendernow unconditionally callsclient.getLocalPlayer().getWorldLocation().getRegionID(), which will throw an NPE when the overlay renders while no player is present (e.g., login screen, world hop in progress). This is a new, earlier dereference compared to the existing usage indrawSpawn.Consider caching and null‑checking the player first:
- public Dimension render(Graphics2D graphics) - { - if (client.getLocalPlayer().getWorldLocation().getRegionID() != PURO_PURO) - { - return null; - } + public Dimension render(Graphics2D graphics) + { + if (client.getLocalPlayer() == null + || client.getLocalPlayer().getWorldLocation().getRegionID() != PURO_PURO) + { + return null; + }You could also cache
localPlayerin a local variable to avoid repeated calls and use it indrawSpawnas well, but the main concern is avoiding the potential NPE.runelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginManager.java (1)
1010-1027: Inconsistent logic:remove()method contains copy-paste errors frominstall().The error messages on lines 1012, 1018, and 1022-1027 reference "install" but this is the
remove()method. Additionally, theisDisable()check on line 1022 prevents removal of disabled plugins, which is counterintuitive—users should be able to remove plugins regardless of their disabled status.public void remove(MicrobotPluginManifest manifest) { if (manifest == null || !manifestMap.containsValue(manifest)) { - log.error("Can't install plugin: unable to identify manifest"); + log.error("Can't remove plugin: unable to identify manifest"); return; } final String internalName = manifest.getInternalName(); if (internalName == null || internalName.isEmpty()) { - log.error("Cannot install plugin: internal name is null or empty"); + log.error("Cannot remove plugin: internal name is null or empty"); return; } - if (manifest.isDisable()) { - log.warn("Cannot install plugin '{}' ({}): This plugin has been disabled upstream by the developers. " + - "This usually means the plugin is no longer functional, has security issues, or has been deprecated.", - manifest.getDisplayName(), internalName); - return; - } + // Note: Disabled plugins should still be removable
🧹 Nitpick comments (1)
runelite-client/src/main/java/net/runelite/client/plugins/itemstats/special/SpicyStew.java (1)
63-74: Update yellow spice comment to match updated skill listYellow spices now correctly boost
Stats.SAILINGin code, but the block comment still lists only Prayer, Agility, Thieving, Slayer, and Hunter. Consider adding Sailing to the comment so the documented mapping matches the implementation.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
runelite-client/src/main/resources/net/runelite/client/plugins/microbot/shortestpath/ships.tsvis excluded by!**/*.tsvrunelite-client/src/main/resources/net/runelite/client/plugins/microbot/shortestpath/transports.tsvis excluded by!**/*.tsv
📒 Files selected for processing (44)
runelite-api/src/main/java/net/runelite/api/Constants.java(1 hunks)runelite-api/src/main/java/net/runelite/api/DynamicObject.java(1 hunks)runelite-api/src/main/java/net/runelite/api/MenuAction.java(2 hunks)runelite-api/src/main/java/net/runelite/api/Model.java(1 hunks)runelite-api/src/main/java/net/runelite/api/TileObject.java(1 hunks)runelite-api/src/main/java/net/runelite/api/WorldEntity.java(1 hunks)runelite-api/src/main/java/net/runelite/api/WorldEntityConfig.java(1 hunks)runelite-api/src/main/java/net/runelite/api/WorldView.java(2 hunks)runelite-api/src/main/java/net/runelite/api/hooks/DrawCallbacks.java(1 hunks)runelite-client/pom.xml(1 hunks)runelite-client/src/main/java/net/runelite/client/plugins/blastfurnace/BarsOres.java(1 hunks)runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CrypticClue.java(1 hunks)runelite-client/src/main/java/net/runelite/client/plugins/entityhider/EntityHiderConfig.java(3 hunks)runelite-client/src/main/java/net/runelite/client/plugins/gpu/FacePrioritySorter.java(6 hunks)runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java(5 hunks)runelite-client/src/main/java/net/runelite/client/plugins/gpu/SceneUploader.java(2 hunks)runelite-client/src/main/java/net/runelite/client/plugins/gpu/VAO.java(2 hunks)runelite-client/src/main/java/net/runelite/client/plugins/gpu/Zone.java(2 hunks)runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java(1 hunks)runelite-client/src/main/java/net/runelite/client/plugins/implings/ImplingsOverlay.java(2 hunks)runelite-client/src/main/java/net/runelite/client/plugins/itemstats/special/SpicyStew.java(1 hunks)runelite-client/src/main/java/net/runelite/client/plugins/itemstats/stats/Stats.java(1 hunks)runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java(3 hunks)runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Config.java(1 hunks)runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Overlay.java(1 hunks)runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Plugin.java(1 hunks)runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Script.java(1 hunks)runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2State.java(1 hunks)runelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginClient.java(4 hunks)runelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginManager.java(16 hunks)runelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginManifest.java(3 hunks)runelite-client/src/main/java/net/runelite/client/plugins/microbot/ui/MicrobotPluginHubPanel.java(6 hunks)runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/tileobject/Rs2TileObjectModel.java(1 hunks)runelite-client/src/main/java/net/runelite/client/plugins/poh/PohPlugin.java(1 hunks)runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/skills/ConstructionAction.java(3 hunks)runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/skills/FletchingAction.java(5 hunks)runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/WoodcuttingPlugin.java(1 hunks)runelite-client/src/main/java/net/runelite/client/plugins/worldmap/MapPoint.java(1 hunks)runelite-client/src/main/java/net/runelite/client/plugins/worldmap/MooringLocation.java(1 hunks)runelite-client/src/main/java/net/runelite/client/plugins/worldmap/WorldMapConfig.java(1 hunks)runelite-client/src/main/java/net/runelite/client/plugins/worldmap/WorldMapPlugin.java(6 hunks)runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java(4 hunks)runelite-client/src/main/java/net/runelite/client/util/GameEventManager.java(3 hunks)runelite-client/src/test/java/net/runelite/client/plugins/loottracker/LootTrackerPluginTest.java(1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.java
📄 CodeRabbit inference engine (AGENTS.md)
**/*.java: Keep indentation with tabs, follow the brace placement already inMicrobotPlugin.java, and prefer lines under 120 characters
UseUpperCamelCasefor types,lowerCamelCasefor members, and prefix configuration interfaces with the plugin name (e.g.,ExampleConfig)
Rely on Lombok for boilerplate where already adopted
Files:
runelite-api/src/main/java/net/runelite/api/TileObject.javarunelite-api/src/main/java/net/runelite/api/Model.javarunelite-client/src/main/java/net/runelite/client/plugins/itemstats/stats/Stats.javarunelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.javarunelite-client/src/test/java/net/runelite/client/plugins/loottracker/LootTrackerPluginTest.javarunelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CrypticClue.javarunelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/skills/ConstructionAction.javarunelite-api/src/main/java/net/runelite/api/WorldView.javarunelite-api/src/main/java/net/runelite/api/WorldEntityConfig.javarunelite-client/src/main/java/net/runelite/client/plugins/gpu/FacePrioritySorter.javarunelite-api/src/main/java/net/runelite/api/hooks/DrawCallbacks.javarunelite-client/src/main/java/net/runelite/client/plugins/implings/ImplingsOverlay.javarunelite-client/src/main/java/net/runelite/client/plugins/woodcutting/WoodcuttingPlugin.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/util/tileobject/Rs2TileObjectModel.javarunelite-client/src/main/java/net/runelite/client/plugins/worldmap/WorldMapConfig.javarunelite-client/src/main/java/net/runelite/client/plugins/itemstats/special/SpicyStew.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginManifest.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Overlay.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2State.javarunelite-client/src/main/java/net/runelite/client/plugins/entityhider/EntityHiderConfig.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Config.javarunelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.javarunelite-api/src/main/java/net/runelite/api/DynamicObject.javarunelite-client/src/main/java/net/runelite/client/plugins/gpu/Zone.javarunelite-client/src/main/java/net/runelite/client/plugins/poh/PohPlugin.javarunelite-client/src/main/java/net/runelite/client/util/GameEventManager.javarunelite-client/src/main/java/net/runelite/client/plugins/worldmap/WorldMapPlugin.javarunelite-api/src/main/java/net/runelite/api/MenuAction.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Plugin.javarunelite-api/src/main/java/net/runelite/api/Constants.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginManager.javarunelite-client/src/main/java/net/runelite/client/plugins/gpu/VAO.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginClient.javarunelite-client/src/main/java/net/runelite/client/plugins/worldmap/MooringLocation.javarunelite-client/src/main/java/net/runelite/client/plugins/gpu/SceneUploader.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Script.javarunelite-api/src/main/java/net/runelite/api/WorldEntity.javarunelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.javarunelite-client/src/main/java/net/runelite/client/plugins/blastfurnace/BarsOres.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/ui/MicrobotPluginHubPanel.javarunelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.javarunelite-client/src/main/java/net/runelite/client/plugins/worldmap/MapPoint.javarunelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/skills/FletchingAction.java
runelite-client/src/test/java/**/*.java
📄 CodeRabbit inference engine (AGENTS.md)
runelite-client/src/test/java/**/*.java: Tests mirror sources inrunelite-client/src/test/java
Write JUnit 4 tests (junit:4.12) under matching package paths inrunelite-client/src/test/java
Use Mockito (mockito-core:3.1.0) for client services; rely onguice-testlibwhen event bus wiring is involved
Files:
runelite-client/src/test/java/net/runelite/client/plugins/loottracker/LootTrackerPluginTest.java
runelite-client/src/test/java/**/*Test.java
📄 CodeRabbit inference engine (AGENTS.md)
Name test classes with the
*Testsuffix and break scenarios into focused@Testmethods that assert observable client state
Files:
runelite-client/src/test/java/net/runelite/client/plugins/loottracker/LootTrackerPluginTest.java
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: Gameplay automation lives inrunelite-client/src/main/java/net/runelite/client/plugins/microbot; keep new scripts and utilities inside this plugin
Register new automation undernet.runelite.client.plugins.microbotand reuse the scheduler pattern shown inExampleScript
Files:
runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/tileobject/Rs2TileObjectModel.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginManifest.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Overlay.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2State.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Config.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Plugin.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginManager.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginClient.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Script.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/ui/MicrobotPluginHubPanel.java
runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/**/*.java
📄 CodeRabbit inference engine (AGENTS.md)
Shared helpers sit under
.../microbot/util
Files:
runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/tileobject/Rs2TileObjectModel.java
🧠 Learnings (15)
📚 Learning: 2025-11-24T19:05:32.967Z
Learnt from: CR
Repo: chsami/Microbot PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-24T19:05:32.967Z
Learning: Applies to runelite-client/src/test/java/**/*Test.java : Name test classes with the `*Test` suffix and break scenarios into focused `Test` methods that assert observable client state
Applied to files:
runelite-client/src/test/java/net/runelite/client/plugins/loottracker/LootTrackerPluginTest.java
📚 Learning: 2025-08-25T06:50:43.493Z
Learnt from: Voxsylvae
Repo: chsami/Microbot PR: 1415
File: runelite-client/src/main/java/net/runelite/client/plugins/microbot/agility/MicroAgilityPrePostScheduleRequirements.java:218-226
Timestamp: 2025-08-25T06:50:43.493Z
Learning: In MicroAgilityPrePostScheduleRequirements.java, the deprecated ItemID constants NATURERUNE and FIRERUNE should be replaced with NATURE_RUNE and FIRE_RUNE respectively when using the gameval package ItemID class.
Applied to files:
runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/skills/ConstructionAction.javarunelite-client/src/main/java/net/runelite/client/plugins/blastfurnace/BarsOres.javarunelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/skills/FletchingAction.java
📚 Learning: 2025-11-24T19:05:32.967Z
Learnt from: CR
Repo: chsami/Microbot PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-24T19:05:32.967Z
Learning: Applies to runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/**/*.java : Shared helpers sit under `.../microbot/util`
Applied to files:
runelite-client/pom.xmlrunelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginManifest.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Overlay.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Plugin.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginManager.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginClient.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Script.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/ui/MicrobotPluginHubPanel.java
📚 Learning: 2025-11-24T19:05:32.967Z
Learnt from: CR
Repo: chsami/Microbot PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-24T19:05:32.967Z
Learning: `mvn -pl runelite-client -am package` builds the client and produces `target/microbot-<version>.jar`
Applied to files:
runelite-client/pom.xmlrunelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginClient.java
📚 Learning: 2025-11-24T19:05:32.967Z
Learnt from: CR
Repo: chsami/Microbot PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-24T19:05:32.967Z
Learning: `java -jar runelite-client/target/microbot-<version>.jar` launches a locally built client for manual validation
Applied to files:
runelite-client/pom.xmlrunelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginClient.java
📚 Learning: 2025-11-24T19:05:32.967Z
Learnt from: CR
Repo: chsami/Microbot PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-24T19:05:32.967Z
Learning: Applies to pom.xml : The root `pom.xml` controls the multi-module Maven build for `cache`, `runelite-api`, `runelite-client`, `runelite-jshell`, and `runelite-maven-plugin`
Applied to files:
runelite-client/pom.xml
📚 Learning: 2025-11-24T19:05:32.967Z
Learnt from: CR
Repo: chsami/Microbot PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-24T19:05:32.967Z
Learning: Applies to runelite-client/src/main/java/net/runelite/client/plugins/microbot/**/*.java : Gameplay automation lives in `runelite-client/src/main/java/net/runelite/client/plugins/microbot`; keep new scripts and utilities inside this plugin
Applied to files:
runelite-client/pom.xmlrunelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginManifest.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Overlay.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Plugin.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginManager.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginClient.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Script.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/ui/MicrobotPluginHubPanel.java
📚 Learning: 2025-11-24T19:05:32.967Z
Learnt from: CR
Repo: chsami/Microbot PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-24T19:05:32.967Z
Learning: Applies to runelite-client/src/main/java/net/runelite/client/plugins/microbot/example/**/*.java : Runnable examples live in `.../microbot/example`
Applied to files:
runelite-client/pom.xmlrunelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Plugin.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginManager.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginClient.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Script.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/ui/MicrobotPluginHubPanel.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-11-24T19:05:32.967Z
Learnt from: CR
Repo: chsami/Microbot PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-24T19:05:32.967Z
Learning: Applies to runelite-client/src/main/java/net/runelite/client/plugins/microbot/*Plugin.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/worldmap/WorldMapConfig.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginManifest.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Overlay.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Config.javarunelite-client/src/main/java/net/runelite/client/plugins/worldmap/WorldMapPlugin.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Plugin.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginManager.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginClient.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/ui/MicrobotPluginHubPanel.java
📚 Learning: 2025-11-24T19:05:32.967Z
Learnt from: CR
Repo: chsami/Microbot PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-24T19:05:32.967Z
Learning: Applies to runelite-client/src/main/java/net/runelite/client/plugins/microbot/**/*.java : Register new automation under `net.runelite.client.plugins.microbot` and reuse the scheduler pattern shown in `ExampleScript`
Applied to files:
runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Overlay.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Plugin.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginManager.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginClient.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Script.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/ui/MicrobotPluginHubPanel.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/breakhandlerv2/BreakHandlerV2Plugin.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Script.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.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginClient.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/ui/MicrobotPluginHubPanel.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.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/externalplugins/MicrobotPluginClient.javarunelite-client/src/main/java/net/runelite/client/plugins/microbot/ui/MicrobotPluginHubPanel.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
🧬 Code graph analysis (5)
runelite-api/src/main/java/net/runelite/api/WorldView.java (1)
runelite-api/src/main/java/net/runelite/api/Constants.java (1)
Constants(33-154)
runelite-client/src/main/java/net/runelite/client/plugins/itemstats/special/SpicyStew.java (1)
runelite-client/src/main/java/net/runelite/client/plugins/itemstats/stats/Stats.java (1)
Stats(29-56)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Overlay.java (1)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerOverlay.java (1)
Slf4j(19-144)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Plugin.java (2)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Overlay.java (1)
Slf4j(20-212)runelite-client/src/main/java/net/runelite/client/plugins/Plugin.java (1)
Plugin(33-80)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/ui/MicrobotPluginHubPanel.java (1)
runelite-client/src/main/java/net/runelite/client/RuneLiteProperties.java (1)
RuneLiteProperties(35-162)
⏰ 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). (2)
- GitHub Check: Build
- GitHub Check: Build
🔇 Additional comments (5)
runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/skills/FletchingAction.java (1)
55-200: New fletching actions look consistent.The vale totem entries correctly share
ItemID.ENT_TOTEMS_LOOTand usegetNameoverrides to differentiate them. Level/XP progressions are logical, and the ATLATL crafting chain follows expected complexity scaling.runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/WoodcuttingPlugin.java (1)
566-571: LGTM!The sailing tree stump IDs are correctly added to the existing stump handling logic. They follow the established pattern where all tree stumps create TreeRespawn entries when the overlay timer script fires.
runelite-client/src/test/java/net/runelite/client/plugins/loottracker/LootTrackerPluginTest.java (1)
673-688: LGTM!The test correctly verifies the salvage loot tracking flow. The chat message format matches the SALVAGE_PATTERN, the tier extraction and capitalization logic produces the expected "Large salvage" event name, and the verification confirms the correct parameters are passed to addLoot.
runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/skills/ConstructionAction.java (2)
197-198: The XP values are correct and match official OSRS game data. Marble Wall (level 79) legitimately grants 4,000 XP while Marble Portal (level 80) grants 1,500 XP because XP scales with resource cost, not level alone—Marble Wall requires 8 marble blocks versus 3 for the portal. No issue.
207-208: Throne XP values are correct per official OSRS game data.The Crystal Throne (15,000 XP at level 95) and Demonic Throne (25,000 XP at level 99) values match official OSRS Construction data. The high XP compared to surrounding items is intentional—thrones are prestige furniture requiring Magic stones (limited resources), so their higher XP reward reflects this design. No changes needed.
| @ConfigItem( | ||
| keyName = "minPlaytime", | ||
| name = "Min Playtime (minutes)", | ||
| description = "Minimum time to play before taking a break", | ||
| position = 0, | ||
| section = breakTimingSettings | ||
| ) | ||
| @Range(min = 1, max = 600) | ||
| default int minPlaytime() { | ||
| return 45; | ||
| } | ||
|
|
||
| @ConfigItem( | ||
| keyName = "maxPlaytime", | ||
| name = "Max Playtime (minutes)", | ||
| description = "Maximum time to play before taking a break", | ||
| position = 1, | ||
| section = breakTimingSettings | ||
| ) | ||
| @Range(min = 1, max = 600) | ||
| default int maxPlaytime() { | ||
| return 90; | ||
| } | ||
|
|
||
| @ConfigItem( | ||
| keyName = "minBreakDuration", | ||
| name = "Min Break Duration (minutes)", | ||
| description = "Minimum break duration", | ||
| position = 2, | ||
| section = breakTimingSettings | ||
| ) | ||
| @Range(min = 1, max = 600) | ||
| default int minBreakDuration() { | ||
| return 5; | ||
| } | ||
|
|
||
| @ConfigItem( | ||
| keyName = "maxBreakDuration", | ||
| name = "Max Break Duration (minutes)", | ||
| description = "Maximum break duration", | ||
| position = 3, | ||
| section = breakTimingSettings | ||
| ) | ||
| @Range(min = 1, max = 600) | ||
| default int maxBreakDuration() { | ||
| return 15; | ||
| } |
There was a problem hiding this comment.
Missing validation for min/max config pairs.
The configuration allows users to set minPlaytime > maxPlaytime or minBreakDuration > maxBreakDuration. The @Range annotations only validate individual bounds (1-600), not the relational constraint that minimum should be ≤ maximum. This creates inconsistent state that will produce invalid ranges at runtime.
Consider adding validation in the plugin startup or config change handler:
if (config.minPlaytime() > config.maxPlaytime()) {
log.warn("minPlaytime ({}) > maxPlaytime ({}), adjusting...",
config.minPlaytime(), config.maxPlaytime());
// Handle the inconsistency
}
if (config.minBreakDuration() > config.maxBreakDuration()) {
log.warn("minBreakDuration ({}) > maxBreakDuration ({}), adjusting...",
config.minBreakDuration(), config.maxBreakDuration());
// Handle the inconsistency
}🤖 Prompt for AI Agents
In
runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Config.java
around lines 19-65, the min/max pairs (minPlaytime/maxPlaytime and
minBreakDuration/maxBreakDuration) can be set inconsistently because @Range only
enforces individual bounds; add validation in the plugin startup and in the
configuration change handler to check if min > max and correct it (e.g., swap
values or set the offending value to the corresponding max/min), emit a clear
warning log with both values, and ensure the corrected values are used by the
plugin going forward (persist or apply corrected values to runtime variables as
appropriate).
| // Time until break or break remaining | ||
| if (currentState == BreakHandlerV2State.WAITING_FOR_BREAK) { | ||
| long secondsUntilBreak = script.getTimeUntilBreak(); | ||
| //if (secondsUntilBreak >= 0) { | ||
| String timeStr = formatDuration(secondsUntilBreak); | ||
| panelComponent.getChildren().add(LineComponent.builder() | ||
| .left("Next break:") | ||
| .right(timeStr) | ||
| .rightColor(Color.GREEN) | ||
| .build()); | ||
| //} | ||
| } else if (BreakHandlerV2State.isBreakActive()) { | ||
| long secondsRemaining = script.getBreakTimeRemaining(); | ||
| if (secondsRemaining >= 0) { | ||
| String timeStr = formatDuration(secondsRemaining); | ||
| panelComponent.getChildren().add(LineComponent.builder() | ||
| .left("Break ends:") | ||
| .right(timeStr) | ||
| .rightColor(Color.ORANGE) | ||
| .build()); | ||
| } | ||
| } |
There was a problem hiding this comment.
Inconsistent handling of negative time values between branches.
The WAITING_FOR_BREAK branch (lines 71-79) displays time unconditionally (the >= 0 check is commented out), while the break-active branch (lines 81-89) guards display with if (secondsRemaining >= 0). This creates inconsistent behavior where negative countdowns are shown in one case but hidden in the other.
Either uncomment the guard on line 72 or remove it from line 82 to maintain consistent behavior:
if (currentState == BreakHandlerV2State.WAITING_FOR_BREAK) {
long secondsUntilBreak = script.getTimeUntilBreak();
- //if (secondsUntilBreak >= 0) {
+ if (secondsUntilBreak >= 0) {
String timeStr = formatDuration(secondsUntilBreak);
panelComponent.getChildren().add(LineComponent.builder()
.left("Next break:")
.right(timeStr)
.rightColor(Color.GREEN)
.build());
- //}
+ }
}🤖 Prompt for AI Agents
In
runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Overlay.java
around lines 69 to 90: the WAITING_FOR_BREAK branch currently formats and
displays secondsUntilBreak unconditionally while the break-active branch only
displays when secondsRemaining >= 0, causing inconsistent display of negative
times; restore the guard in the WAITING_FOR_BREAK branch (or alternatively
remove the guard in the break-active branch) so both branches behave the same —
specifically, wrap the formatting and panelComponent addition in
WAITING_FOR_BREAK with an if (secondsUntilBreak >= 0) check (or remove the if
(secondsRemaining >= 0) in the other branch if you prefer showing negatives) so
either both show or both hide negative countdowns.
| private int calculateLoginBackoffDelay(int attemptCount) { | ||
| if (attemptCount < INITIAL_FAST_RETRIES) { | ||
| return 5000; // 5 seconds for initial retries | ||
| } | ||
| // Exponential backoff: 30s * (attempt - 3) | ||
| int backoffMultiplier = attemptCount - INITIAL_FAST_RETRIES + 1; | ||
| return BACKOFF_BASE_DELAY_MS * backoffMultiplier; | ||
| } |
There was a problem hiding this comment.
Remove unreachable code in backoff calculation.
The condition attemptCount < INITIAL_FAST_RETRIES on line 384 can never be true because this method is only called when loginRetryCount >= INITIAL_FAST_RETRIES (line 341). The if-statement is dead code and should be removed. Additionally, the method's comment (lines 379-381) is misleading—the 5-second delay for the first 3 attempts is implemented in the caller (line 346), not here.
Apply this diff to remove the dead code:
- private int calculateLoginBackoffDelay(int attemptCount) {
- if (attemptCount < INITIAL_FAST_RETRIES) {
- return 5000; // 5 seconds for initial retries
- }
- // Exponential backoff: 30s * (attempt - 3)
- int backoffMultiplier = attemptCount - INITIAL_FAST_RETRIES + 1;
- return BACKOFF_BASE_DELAY_MS * backoffMultiplier;
- }
+ /**
+ * Calculate exponential backoff delay for login retries after initial fast attempts
+ * Returns: 30s, 60s, 90s, 120s, etc.
+ */
+ private int calculateLoginBackoffDelay(int attemptCount) {
+ // Exponential backoff: 30s * (attempt - 3 + 1)
+ int backoffMultiplier = attemptCount - INITIAL_FAST_RETRIES + 1;
+ return BACKOFF_BASE_DELAY_MS * backoffMultiplier;
+ }📝 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.
| private int calculateLoginBackoffDelay(int attemptCount) { | |
| if (attemptCount < INITIAL_FAST_RETRIES) { | |
| return 5000; // 5 seconds for initial retries | |
| } | |
| // Exponential backoff: 30s * (attempt - 3) | |
| int backoffMultiplier = attemptCount - INITIAL_FAST_RETRIES + 1; | |
| return BACKOFF_BASE_DELAY_MS * backoffMultiplier; | |
| } | |
| /** | |
| * Calculate exponential backoff delay for login retries after initial fast attempts | |
| * Returns: 30s, 60s, 90s, 120s, etc. | |
| */ | |
| private int calculateLoginBackoffDelay(int attemptCount) { | |
| // Exponential backoff: 30s * (attempt - 3 + 1) | |
| int backoffMultiplier = attemptCount - INITIAL_FAST_RETRIES + 1; | |
| return BACKOFF_BASE_DELAY_MS * backoffMultiplier; | |
| } |
🤖 Prompt for AI Agents
In
runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/breakhandlerv2/BreakHandlerV2Script.java
around lines 383-390, remove the unreachable if-statement that checks
attemptCount < INITIAL_FAST_RETRIES and the misleading comment; replace with a
simple backoff calculation that computes backoffMultiplier = attemptCount -
INITIAL_FAST_RETRIES + 1 and returns BACKOFF_BASE_DELAY_MS * backoffMultiplier,
and update the method comment to state it only computes exponential backoff for
attempts at or beyond INITIAL_FAST_RETRIES (the initial 5s fast retries are
handled by the caller).
| @Override | ||
| public @Nullable String getOpOverride(int index) { | ||
| return ""; | ||
| } |
There was a problem hiding this comment.
Inconsistent return value with interface contract.
The TileObject.getOpOverride(int) interface declares @Nullable String, suggesting null should be returned when no override exists. Returning "" implies an override is present but empty, which is semantically different.
@Override
public @Nullable String getOpOverride(int index) {
- return "";
+ return null;
}🤖 Prompt for AI Agents
In
runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/tileobject/Rs2TileObjectModel.java
around lines 144-147, the method getOpOverride(int) currently returns an empty
string which contradicts the interface contract that marks the return as
@Nullable; change the implementation to return null when no override exists
(instead of ""), so callers can distinguish “no override” from an empty override
string; update any unit tests or callers that incorrectly treat empty string as
null if necessary.
| EAGLE_LECTERN("Eagle Lectern", 47, 120, ItemID.POH_LECTERN_2), | ||
| SINK("Sink", 47, 300, ItemID.POH_SINK_3), | ||
| MOUNTED_MYTHICAL_CAPE("Mounted Mythical Cape", 47, 370, ItemID.POH_TROPHY_MYTHICAL_CAPE), | ||
| GOLD_SINK("Gold Sink", 47, 11144, ItemID.POH_SINK_4), |
There was a problem hiding this comment.
❓ Verification inconclusive
🏁 Script executed:
#!/bin/bash
# Search for GOLD_SINK and related construction XP values
rg -n "GOLD_SINK|11144" --type java -C 3Repository: chsami/Microbot
Length of output: 10567
🏁 Script executed:
#!/bin/bash
# Check the overall context around line 147 in ConstructionAction.java
cat -n runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/skills/ConstructionAction.java | head -200 | tail -100Repository: chsami/Microbot
Length of output: 7535
🏁 Script executed:
#!/bin/bash
# Search for any construction XP data sources or references
rg -n "POH_SINK|ItemID\.POH" --type java -C 2Repository: chsami/Microbot
Length of output: 50372
🏁 Script executed:
#!/bin/bash
# Look for external data sources or documentation about construction XP
find . -name "*.json" -o -name "*.txt" -o -name "*.md" | xargs grep -l "GOLD_SINK\|construction.*xp" 2>/dev/null | head -5Repository: chsami/Microbot
Length of output: 41
🏁 Script executed:
#!/bin/bash
# Search for any league-related information or comments about construction XP
rg -n -i "league.*gold.*sink|construction.*11144|gold.*sink.*xp" --type java -B2 -A2Repository: chsami/Microbot
Length of output: 798
🏁 Script executed:
#!/bin/bash
# Check if there are any test files or documentation that reference this value
fd -e "java" -e "md" -e "txt" | xargs rg -l "11144" 2>/dev/null | head -10Repository: chsami/Microbot
Length of output: 606
Verify GOLD_SINK XP value against official game data.
The XP value of 11144 for GOLD_SINK (level 47) is significantly inconsistent with the construction progression pattern:
- PUMP_AND_DRAIN (level 7): 100 XP
- PUMP_AND_TUB (level 27): 200 XP
- SINK (level 47): 300 XP
- GOLD_SINK (level 47): 11144 XP
This represents a 37x increase at the same level and far exceeds typical level 47 items. While GOLD_SINK appears to be League-specific content (confirmed by LEAGUE_TASK_BUILD_A_GOLD_SINK), no documentation explains this value. Confirm it matches the actual game data or correct it if it's a data entry error.
🤖 Prompt for AI Agents
In
runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/skills/ConstructionAction.java
around line 147, the GOLD_SINK entry uses XP value 11144 which is almost
certainly incorrect compared to SINK (300) and other progression items; verify
the correct XP from the official game data/config (or the game cache/item/skill
XP table) and replace 11144 with the verified value (likely 300) or the
documented league-specific value, and if the value is intentionally
league-specific add a brief inline comment referencing the source (game data key
or documentation) so future reviewers know it was validated.
| static final String CONFIG_KEY_HUNTER_AREA_TOOLTIPS = "hunterAreaTooltips"; | ||
| static final String CONFIG_KEY_FISHING_SPOT_TOOLTIPS = "fishingSpotTooltips"; | ||
| static final String CONFIG_KEY_MOORING_LOCATION_TOOLTIPS = "mooringLocationTooltips"; | ||
| static final String CONFIG_KEY_MOORING_LOCATION_LEVEL_ICON = "mooringLocationShortcutIcon"; |
There was a problem hiding this comment.
Inconsistent naming in config key string.
The config key string "mooringLocationShortcutIcon" includes the word "shortcut", but mooring locations are not shortcuts. Line 108 uses "mooringLocationTooltips" without "shortcut", and the UI description in WorldMapConfig refers to "mooring locations" or "mooring points", not shortcuts. Compare with line 101 where rare trees use "rareTreeIcon" (no "shortcut"), while line 87 correctly uses "agilityShortcutIcon" because agility shortcuts actually are shortcuts.
Apply this diff to align the naming:
- static final String CONFIG_KEY_MOORING_LOCATION_LEVEL_ICON = "mooringLocationShortcutIcon";
+ static final String CONFIG_KEY_MOORING_LOCATION_LEVEL_ICON = "mooringLocationIcon";📝 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.
| static final String CONFIG_KEY_MOORING_LOCATION_LEVEL_ICON = "mooringLocationShortcutIcon"; | |
| static final String CONFIG_KEY_MOORING_LOCATION_LEVEL_ICON = "mooringLocationIcon"; |
🤖 Prompt for AI Agents
In
runelite-client/src/main/java/net/runelite/client/plugins/worldmap/WorldMapPlugin.java
around line 109, the config key constant value "mooringLocationShortcutIcon" is
inconsistent with other keys and UI wording; change the string to
"mooringLocationIcon" to match "mooringLocationTooltips" and other icon keys,
and update any references/usages (config annotations, saved keys, and tests) to
the new key name to maintain consistency and avoid mismatches with stored
settings.
| for (WorldEntity we : wv.worldEntities()) | ||
| { | ||
| simulateGameEvents(sub); | ||
| eventBus.post(new WorldEntitySpawned(we)); | ||
| simulateGameEvents(we.getWorldView()); | ||
| } |
There was a problem hiding this comment.
Inconsistent defensive programming pattern.
The NPC and Player loops (lines 135-151) check for null elements before posting events, but the WorldEntity loop does not. Additionally, we.getWorldView() is called without verifying the result is non-null before the recursive call. If either worldEntities() returns null elements or getWorldView() returns null, this will cause a NullPointerException.
Apply this diff to align with the existing defensive pattern:
for (WorldEntity we : wv.worldEntities())
{
- eventBus.post(new WorldEntitySpawned(we));
- simulateGameEvents(we.getWorldView());
+ if (we != null)
+ {
+ eventBus.post(new WorldEntitySpawned(we));
+ WorldView worldView = we.getWorldView();
+ if (worldView != null)
+ {
+ simulateGameEvents(worldView);
+ }
+ }
}📝 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.
| for (WorldEntity we : wv.worldEntities()) | |
| { | |
| simulateGameEvents(sub); | |
| eventBus.post(new WorldEntitySpawned(we)); | |
| simulateGameEvents(we.getWorldView()); | |
| } | |
| for (WorldEntity we : wv.worldEntities()) | |
| { | |
| if (we != null) | |
| { | |
| eventBus.post(new WorldEntitySpawned(we)); | |
| WorldView worldView = we.getWorldView(); | |
| if (worldView != null) | |
| { | |
| simulateGameEvents(worldView); | |
| } | |
| } | |
| } |
🤖 Prompt for AI Agents
In runelite-client/src/main/java/net/runelite/client/util/GameEventManager.java
around lines 212 to 216, the WorldEntity loop must follow the same defensive
checks as the NPC and Player loops: skip null WorldEntity elements and check
that we.getWorldView() is non-null before calling simulateGameEvents. Update the
loop to null-check each 'we' before posting WorldEntitySpawned and only call
simulateGameEvents if we.getWorldView() != null, mirroring the existing pattern
used for NPCs/Players.
breakhandler v2