Repository navigation
Release Hub development updates for Microbot 2.6.34 - #654
Merged
Merged
Conversation
…ot NPEs (#613) isPkerAround compared the raw interacting Actor by name, which calls Actor.getName on the script thread and throws "must be called on client thread". Compare the interacting actor against the client's local player by identity instead; the previous equals check against the Rs2PlayerModel wrapper could never match. The Bankfortrip sleepUntil predicates dereferenced Rs2Equipment.get for the ring and ammo slots, which returns null until the equip lands, so each poll threw an NPE. Null-check them via small helpers. Bump revKillerPlugin to 2.0.12. Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ity is null (1.9.9) (#614) Rs2Antiban.getActivity() is null when overwriteScriptSettings makes applyMiningSetup() return early or after another script resets antiban settings, so every MINING tick threw an NPE and aborted the workflow. Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…l (2.4.3) (#615) PrayerPotionScript.run(NmzConfig) divided boosted prayer by the real prayer level with no logged-in check, throwing ArithmeticException every 600 ms while logged out or loading. Route both loops through a helper that skips drinking when the real level is not yet known, and add the missing login guard. Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
… needed (2.2.4) (#616) Rs2Slayer.getSlayerTaskProtectiveEquipment() returns null when there is no slayer task, which reached isBypassedBySlayerHelmet's switch and threw an NPE on every BankerScript loop in slayer mode. Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
… throwing (1.0.1) (#617) BankInventoryStrategy parsed the free-text "Always Drop Item ids" config with Integer::parseInt, so any item name in the list threw NumberFormatException on every loop tick with a full inventory and the script never banked or dropped. Trim each entry and keep only numeric ids. Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…619) determineState called Rs2Player.getInteracting() twice, once for the null check and again for isDead(). The target can clear between the two calls, so the second read returned null and threw an NPE. The NPC query filters in handleFighting had the same double read on n.getInteracting() before equals(). Move each check into a small helper that reads the interacting actor once and checks and uses that value. Bump SulphurNaguaPlugin to 2.0.3. Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The Jad and healer query filters called Rs2NpcModel.getName() twice, once for the null check and again for toLowerCase(). Each call is a separate client-thread read, so the second one can return null after the first passed and throw an NPE. handleHealerInteraction also called getName() on the interacting NPC with no null check. Add a nameContains helper that reads the name once, and null-check the interacting NPC's name before using it. Rs2NpcModel.matches(false, ...) is not used because it only lowercases the NPC name in exact mode, so it would not match "TzTok-Jad". Bump JadPlugin to 1.0.11. Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…t (1.8.18) (#621) Bank, furnace and anvil replay called Objects.requireNonNull on the recorded entry's widget, which is null for clicks not made on a widget. The NPE escaped before executeBankActions was cleared, so it repeated every loop. Use the widget bounds when present and a 1x1 rectangle otherwise, matching the workbench replay. Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The attackable NPC sort read npc.getInteracting() and the live NPC path distance on every comparison. NPCs that moved or retargeted mid-sort gave inconsistent keys and TimSort threw "Comparison method violates its general contract!". Compute both keys once per NPC, then sort. Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…is closed (1.0.1) (#623) BankSnapshotReader threw IllegalStateException inside the runOnClientThreadOptional callable when the bank was closed, so ClientThread logged every BankActuator poll at ERROR. The callable now returns an empty Optional and read() raises the same "Open your bank" error on the caller's thread, which ends the organizer run without client-thread error spam. Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…6) (#624) * fix(cluesolver): keep requirement banking off the client thread (1.0.6) RequirementHandlerTask ran the whole missing-item flow inside ClientThread.invokeLater, so Rs2Bank.getNearestBank planned the bank route on the client thread and threw "synchronous route planning must not run on the client thread". The onGameTick handler also opened the bank, withdrew and closed it on the client thread. Only the inventory/equipment read and item names now hop to the client thread; bank lookup, walking, opening and withdrawing run on the task executor behind a single in-flight guard. A null nearest bank fails the task instead of throwing an NPE, and the tick handler reuses the chosen bank instead of re-planning a route every tick. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV * fix(cluesolver): fail requirement task instead of hanging when walking to the bank fails Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…6.2) (#625) recoverFromPit re-queried ladder 17385 inside the 2s throttle and clicked the result unconditionally, throwing an NPE when the cache returned no ladder. Keep the ladder from the first lookup when the re-query is empty, and only start the throttle after a click actually succeeds. Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
….19) (#626) * fix(qol): parse Wintertodt energy text defensively (1.8.19) WintertodtScript read the energy widget with split("\\D+")[1], which threw ArrayIndexOutOfBoundsException when the text had no digits. Take the first run of digits instead and fall back to -1 for null or digit-less text. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV * fix(qol): read Wintertodt energy from ENERGY_TITLE widget The script read widget 25952276 (WintStatus.WARMTH_TITLE) for the boss energy, so wintertodtHp tracked the player's warmth. Read InterfaceID.WintStatus.ENERGY_TITLE instead, matching the other Wintertodt plugins, and share one compiled digit pattern. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
SafeSpot called AIOFighterPlugin.getState().equals(...) on every tick, but getState() is a raw ConfigManager read that returns null before the state is first set (startup, after reset), so the loop threw an NPE. Compare the state by identity through a small helper instead, matching LootScript and SafetyScript. Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
SandCrabScript built Rs2InventorySetup from config.inventorySetup().getName() on every loop, but inventorySetup() defaults to null, so with no setup selected (or the setup disabled) the loop threw an NPE before reaching its own "Please setup your Inventory Setup" check. Validate the configured setup first and only construct Rs2InventorySetup when inventory setups are enabled, checking DisableInventorySetup before the equipment match. Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix(nmz): guard null widgets and local player in lobby handling (2.4.4) isOutside now reads the cached Rs2Player world location instead of dereferencing getLocalPlayer() on the client thread. consumeEmptyVial skips the dream confirm when widget 129:6 is not loaded, and handleStore stops buying when the reward shop potion child is missing instead of passing null to Rs2Widget.clickWidgetFast. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV * fix(nmz): guard null local player when walking to power-up orbs Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
….8.7) (#630) * fix(woodcutting): guard null return point in overlay and walk-back (1.8.7) getReturnPoint falls back to Rs2Player.getWorldLocation(), which is null while the local player is not loaded. The overlay passed it straight into LocalPoint.fromWorld and threw an NPE every frame; walkBack dereferenced it the same way. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV * test(woodcutting): isolate overlay test from leaked static return points Other plugin tests in the full suite leave Script.initialPlayerLocation set, so getReturnPoint returned a stale non-null point in CI. Clear and restore AutoWoodcuttingScript's static return points around the render. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…4) (#631) * fix(mahoganyhomes): skip contract lookup while player location is unknown (0.0.14) getClosestContractLocation compared each office with Rs2Player.getWorldLocation(), which is null during loading or a world hop, so WorldPoint.distanceTo2D threw an NPE and failed the loop iteration. Read the player location once, return null from the helper when it is missing, and skip the tick in getNewContract. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV * fix(mahoganyhomes): skip the whole tick while player location is unknown bank() and walkToHome() pass the player location to distanceBetween and fix()/finish() read its plane, so they also threw during loading or a world hop. Return early from the loop when the location is null; the getClosestContractLocation null check stays as a second guard. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ailable (2.2.7) (#632) * fix(aiofighter): skip attack style lookup when enum or struct is unavailable (2.2.7) getWeaponTypeStyles dereferenced Microbot.getEnum and getStructComposition results without null checks; both return null when the client-thread lookup fails, throwing NPEs from the AttackStyleScript task. Return an empty style array instead so updateAttackStyle leaves the current style untouched. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV * test(aiofighter): cover null StructComposition before a named style Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…e (2.2.8) (#633) handleItemOnNpcToKill called npc.getName().equalsIgnoreCase(...) on a dead NPC interacting with the player. getName() returns null once the NPC's composition is gone during death/despawn, throwing an NPE on the AttackNpcScript thread. Move the item choice into a pure helper that returns early on a null name, and cover it with unit tests. Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
AnagramClueTask.handleDialogue passed clue.getAnswer() straight to Rs2Keyboard.typeString, which NPEs for anagrams without a challenge answer. Only type and submit when the answer is non-blank; otherwise just click through the dialogue. Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…cation (1.0.3) (#635) * fix(scurrius): tolerate inverted eat/prayer ranges and null player location (1.0.3) Order the configured min/max eat and prayer percents before picking a random threshold so min > max no longer throws IllegalArgumentException, and treat a null player location as outside the fight room during load or hop. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV * fix(scurrius): skip the tick while the player location is unknown Return early at the top of the loop when Rs2Player.getWorldLocation() is null during load or hop, so the state machine does not treat an unknown location as outside the fight room and the dodge loop does not dereference it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
getAvailableAltars cast every altar renderable to DynamicObject, throwing ClassCastException when the renderable is a plain Model. Check the type first and read the animation once. Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
#637) saveMouseClicks wrote to ~/.runelite/PlayerMonitor/click_count.log without creating the directory, which is only created by loadMouseClicks and is skipped in lite mode. Stopping the plugin then threw FileNotFoundException and aborted shutDown before the listener and script were cleaned up. Create the parent directory before writing, close the writer with try-with-resources, and catch the IOException in shutDown so cleanup runs. Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…yer gear (2.2.9) (#638) addInventorySetup("cache") registers the setup on the client thread, so the immediate lookup could miss it and pass null to setCurrentSlayerInventorySetup, which threw an NPE on getName(). Wait for the cache setup to register before looking it up, and make the setter ignore a null setup. Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…2.3) (#639) bank() iterated the shared items field while the stop path cleared it from the plugin-stop thread, throwing ConcurrentModificationException. The withdrawal list is now a local variable passed to the travel-item helpers, the merge is a static helper, and stopping the script no longer touches it. Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…widget (1.1.9) (#640) Rs2Widget.getWidget(197, 11) returns null when the reward shop child is not built yet or the shop has just closed, which threw an NPE inside waitForInventoryChanges. Return early when the container is null and skip the click and confirm when the reward item is not in the list. Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…0.4) (#641) The giant-rat query predicate called getName() twice; when the NPC despawned between the null check and toLowerCase() the second call returned null and the NPE aborted the Scurrius tick. Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ad (1.1.7) (#642) 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. Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ender (2.1.6) (#643) ThievingOverlay.render calls xpGained() every frame, which called setStartXp() and dereferenced Rs2Player.getLocalPlayer() without a null check. getLocalPlayer() returns null while the local player is missing from the player cache (login, world hop, loading), so the overlay threw an NPE on every frame. Skip the start-xp update when the local player is null and leave startXp untouched. Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…k (1.3.17) (#644) The melee rat step only opened gate 9719 when the player already stood on the x=3111 gate strip, and otherwise gated the attack on Rs2Walker.canReach, which routes through the gate transport and tolerates a 2-tile endpoint offset. Rats were clicked from outside the closed pen (spam-clicking) or the step idled. Now the attack is gated on a strict collision reachability check; when the rat is not reachable the player walks to the gate and opens it. The ranged step attacks the rat over the fence without a reachability check. Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…(1.0.5) (#645) * fix(PVirewatchKiller): skip script loop until fight area is set (1.0.5) The script loop starts with no initial delay and dereferenced plugin.fightArea before the first GameTick assigned it, and again after the plugin stop hook cleared it. Read the player location once with a null guard, snapshot fightArea and startingLocation, and return early while any of them is missing. Compare WorldPoints with equals instead of identity so the return-to-start branch is no longer always taken. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV * fix(PVirewatchKiller): skip NPC outline in overlay until fight area is set Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV * fix(PVirewatchKiller): read fight area once per frame for the tile loop Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
#647) The rev239 cache update removed PMOON_FISHING_SPOT_MULTI (51367) and moved the Moons of Peril bream spot to ObjectID.RIVER_FISHING_SPOT; the old id now belongs to a sailing gangplank, so the Fish interaction matched nothing and the resupply loop idled beside the stream forever. Target RIVER_FISHING_SPOT (the id the quest helper uses at the same stream) and stop fishing with a log line when no bream is caught for 60 seconds. Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
… and bank (0.0.15) (#649) walkToHome and bank null-checked a local copy of the current home but then re-read plugin.getCurrentHome() through isMissingItems, planksNeeded and steelBarsNeeded and for the walk target, so a contract cleared on the client thread mid-loop threw an NPE. Rs2Player.getWorldLocation() was also passed to distanceBetween unchecked. Snapshot both once, guard them in isAwayFromHome, and pass the Home through to the material helpers. Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…bleObjects (0.0.16) (#650) getFixableObjects indexed HotspotObjects.objects by Hotspot ordinal without a bounds check, so a broken hotspot 8 varbit at a 7-object home (or 7/8 at SARAH) threw ArrayIndexOutOfBoundsException and aborted the script loop. Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…andlePatch (1.2.5) (#651) * fix(FarmTreeRun): treat null object composition as empty patch in isPatchEmpty (1.2.4) Rs2GameObject.getObjectComposition is nullable and returns null on a client-thread read timeout or a null impostor while the patch object transforms after planting, which threw an NPE from handlePlantingTree. A null composition now reads as an empty patch so the post-plant wait keeps polling and planting is retried instead of the patch being skipped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV * fix(FarmTreeRun): guard null tree composition in handlePatch and skip composition read when protection is off (1.2.5) handlePatch dereferenced Rs2GameObject.findObjectComposition(...).getActions() without a null check; the composition is null on the same client-thread read failure or null impostor that caused the isPatchEmpty NPE. Return false so the loop retries on the next tick. handlePayment's protection opt-out checks no longer read the patch composition, so a transient null can no longer fall through to paying the gardener when protection is disabled. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…11) (#652) * fix(ShootingStar): close stop race on null panel and null state (1.4.11) On "Oh dear, you are dead!" the plugin called its own shutDown() directly, which removed and nulled the panel while the plugin stayed registered, so tick, event and config handlers kept queueing updatePanelList() runnables that dereferenced the null panel on the EDT. Even a runnable queued just before a normal stop read the field after removePanel() had cleared it. The script loop null-checked the static state field and then switched on it again after several client calls, so a concurrent stop that set state to null threw on ordinal(). - stop through Microbot.stopPlugin(this) so the plugin is unregistered - skip updatePanelList when there is no panel, and re-read the panel on the EDT so queued updates skip a removed panel - read state into a local once per loop iteration and switch on it - treat a missing antiban category as not busy Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV * fix(ShootingStar): reset loop state on start instead of on stop ShootingStarScript.shutdown() nulled state, currentStar and pickaxe while mainScheduledFuture.cancel(true) does not wait for a running iteration, so a loop that had already passed its null check went on to dereference the cleared fields (switch on state, currentStar in the WALKING, MINING and BANKING cases). The previous local snapshot of state only moved the NPE to the currentStar reads. - stop clearing state, currentStar and pickaxe in shutdown() - clear them at the top of run() with the other per-run resets - drop the now unneeded state snapshot in the loop - read the static state once in the overlay before rendering it Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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(). Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Releases the reviewed
developmentplugin updates to the stable Hub, alongside Microbot 2.6.34 (chsami/Microbot#2002). Every plugin also builds against the published 2.6.33 client.All 38 changes are crash fixes found in the client error telemetry. Each one bumps its plugin's version, so users are offered the update.
Included
walkToHomeand banking handle a null home. Hotspots beyond the home's object count are skipped.The open
developmentPRs are not part of this release: #596, #597, #648, #646, #618 and #593.Release commit
c418633mergesdevelopmentintomainwithout conflicts. The tree is identical todevelopment(d7f5501).Test plan
ci.ymldispatched on this branch,./gradlew clean buildagainst the published 2.6.33 client: run 39113405575 passed-PmicrobotClientPath), and the Hub tests pass: 926 tests, 0 failures, 2 skippedci.ymlre-dispatched against the published 2.6.34 client: run 39118056320 passed🤖 Generated with Claude Code
https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV