Skip to content

fix(AmmoniteCrabs): guard null local player location during hop or load (1.1.7) - #642

Merged
chsami merged 1 commit into
developmentfrom
claude/err-ammonitecrab-null-local-player-world-location
Oct 16, 2026
Merged

chsami merged 1 commit into
developmentfrom
claude/err-ammonitecrab-null-local-player-world-location

Conversation

@chsami

@chsami chsami commented Oct 16, 2026

Copy link
Copy Markdown
Owner

Problem

Client error telemetry groups 2331 and 2332 come from AmmoniteCrabPlugin 1.1.6 on Microbot 2.6.33. They had 6 occurrences in total (3 + 3) in one session, about every 5 minutes. Both are:

java.lang.NullPointerException: Cannot invoke "net.runelite.api.Player.getWorldLocation()" because the return...
  • 2331: AmmoniteCrabScript.lambda$walkBack$4:211 (inside ClientThread.invoke from Hooks.tick)
  • 2332: AmmoniteCrabScript.lambda$otherPlayerDetected$8:276 (same path)

Root cause

The script read the player position with Microbot.getClientThread().invoke(() -> Microbot.getClient().getLocalPlayer().getWorldLocation()) and never checked for null, at lines 135, 181, 211 (walkBack), 259 (resetAggro) and 276 (otherPlayerDetected). Line 49 also called getLocalPlayer().isInteracting() without a check. While the client is logging out, loading or hopping worlds, getLocalPlayer() returns null, and the lambda throws on the client thread.

Change

  • Every site now reads the location once through Rs2Player.getWorldLocation(). That call is null-safe because it uses the state cache and runOnClientThreadOptional.
  • preStateChecks only applies the "more than 10 tiles from the hop spot" rule when the location is known.
  • scanAmmoniteCrabLocation skips the tick when the location is null.
  • walkBack, resetAggro and the <= 3 check in the scan use a new helper, isWithin(WorldPoint, WorldPoint, int), which returns false for a null location.
  • otherPlayerDetected(WorldPoint) returns false for a null location.
  • The FIGHT case uses Rs2Player.isInteracting(). Its distanceTo(...) > 0 check now has the same null guard, so the fix does not leave a new NPE next to the fixed sites.
  • AmmoniteCrabPlugin is bumped from 1.1.6 to 1.1.7.

Validation

  • New AmmoniteCrabScriptTest has 3 tests: a null location is never within range, the range boundary works with real points, and otherPlayerDetected(null) returns false without asking for players. All 3 pass.
  • PluginManifestVersionTest passes.
  • ./gradlew build -x test -PpluginList=AmmoniteCrabPlugin succeeds.

Known gaps

  • The script was not run in a live client. The fix is checked only by the unit tests and by reading the code paths in the stack traces.
  • When the location is null (during a load or hop), otherPlayerDetected() returns false, so hijackTimer resets. A hop caused by a hijack can then be delayed by about one tick. This is minor and intended.
  • 14 other Hub scripts use the same unguarded pattern, 32 sites in total. SandCrabScript is a near-copy with 6 sites; others include TitheFarming, AgilityScript, DemonicGorilla, TormentedDemon, Virewatch and Vorkath. Telemetry has not reported them, so they are left for a follow-up.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV

…ad (1.1.7)

Read the player location through Rs2Player.getWorldLocation() and skip the
check when it is null, instead of dereferencing getLocalPlayer() inside
client-thread lambdas in preStateChecks, scanAmmoniteCrabLocation, walkBack,
resetAggro and otherPlayerDetected. Use Rs2Player.isInteracting() in the
FIGHT case.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV
@chsami
chsami merged commit dcfc5f0 into development Oct 16, 2026
1 check 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