Skip to content

fix(TowerOfLifeCC): run summon query on client thread (1.1.5) - #653

Merged
chsami merged 1 commit into
developmentfrom
claude/err-toweroflife-getinteracting-off-client-thread
Oct 18, 2026
Merged

chsami merged 1 commit into
developmentfrom
claude/err-toweroflife-getinteracting-off-client-thread

Conversation

@chsami

@chsami chsami commented Oct 18, 2026

Copy link
Copy Markdown
Owner

Problem

Client error telemetry group 2590 (6 occurrences, Microbot 2.6.33, TowerOfLifeCC 1.1.4, thread TowerOfLifeCCScript-N) reports:

java.lang.IllegalStateException: must be called on client thread
  Actor.getInteracting
  TowerOfLifeCCScript.lambda$HandleCreature$1:410
  AbstractEntityQueryable.nearest:175
  TowerOfLifeCCScript.lambda$HandleCreature$2:411
  Global.sleepUntil:176
  TowerOfLifeCCScript.HandleCreature:408

Each poll inside the 5s sleepUntil throws, so summoned-creature detection never succeeds while it fails.

Root cause

The summon query in HandleCreature filters with raw npc.getNpc().getInteracting(), which asserts the client thread. It skips the thread-safe Rs2ActorModel.getInteracting() wrapper. .nearest() evaluates that predicate on the script executor thread.

Change

  • Moved the query into a package-private findSummonedCreature(). The filter is unchanged, and the method now ends with .nearestOnClientThread(), the existing client helper (Microbot.getClientThread().invoke(() -> nearest())). This runs the filter and the distance pass in one client-thread hop.
  • sleepUntil calls the new method. If the invoke fails it returns null, which keeps polling, the same as the old "not found yet" behaviour.
  • Bumped TowerOfLifeCCPlugin version from 1.1.4 to 1.1.5.

Validation

  • New TowerOfLifeCCSummonQueryTest (3 cases) uses a mocked NPC whose getInteracting() throws unless it is reached through the client-thread path. The cases: the query uses nearestOnClientThread and never calls nearest(); a creature targeting the local player is accepted; a creature targeting another actor is rejected.
  • Putting the old .nearest() back makes all 3 tests fail with the production IllegalStateException.
  • PluginManifestVersionTest passed, and build -PpluginList=TowerOfLifeCCPlugin succeeded.
  • No other query in the plugin has the same defect. The only other query is a tile-object query that makes no actor calls.

Known gaps

  • The test stubs nearestOnClientThread itself, so it checks which method is called and does not exercise the real client-thread hop.
  • No live in-game run at Tower of Life.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV

The summoned-creature lookup filtered NPCs on Actor.getInteracting(),
which asserts the client thread, but the query was evaluated by
nearest() on the script executor inside sleepUntil, throwing
IllegalStateException "must be called on client thread" and never
detecting the summoned creature. Evaluate it with nearestOnClientThread().

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