From 8a87c555f60ebed0fdfe0a6a52daf01c8f17c11b Mon Sep 17 00:00:00 2001 From: irkedMATT Date: Wed, 4 Feb 2026 15:16:10 +0000 Subject: [PATCH 01/17] feat: Added bank IDs and container emptying utility Added bank IDs for locations: - SUNBLEAK_ISLAND - DEEPFIN_POINT - DEEPFIN_MINE_MID - DEEPFIN_MINE_EAST - CHARRED_ISLAND Rs2Bank API Enhancement: - Added `emptyContainers()` method to empty containers in inventory via the bank interface - Uses widget ID 786471 to trigger the empty containers action --- .../plugins/microbot/util/bank/Rs2Bank.java | 19 +++++++++++++++++++ .../microbot/util/gameobject/Rs2BankID.java | 3 ++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/bank/Rs2Bank.java b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/bank/Rs2Bank.java index 7642e76367e..7822ad33512 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/bank/Rs2Bank.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/bank/Rs2Bank.java @@ -1091,6 +1091,25 @@ public static boolean depositAll(String name) { return depositAll(name, false); } + /** + * Empty containers using the "Empty containers" button + * This button empties all containers like log baskets, herb sacks, etc. directly to the bank + * + * @return true if containers were emptied successfully, false otherwise + */ + public static boolean emptyContainers() { + Microbot.status = "Empty containers"; + if (!Rs2Bank.isOpen()) return false; + + Widget widget = Rs2Widget.getWidget(786471); // Empty containers button ID + if (widget == null) return false; + + Rs2Widget.clickWidget(widget); + sleep(1000, 2000); // Wait for containers to be emptied + + return true; + } + /** * deposit all items */ diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/gameobject/Rs2BankID.java b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/gameobject/Rs2BankID.java index 9b025bb9ed7..e20f04ab303 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/gameobject/Rs2BankID.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/gameobject/Rs2BankID.java @@ -41,6 +41,7 @@ public class Rs2BankID { 49558, 49559, 49560, 49612, 49613, 49614, 49615, 49616, 49617, 49618, 50061, 50530, 50531, 50741, 50748, 50863, 50864, 50865, 50866, 50867, 50868, 50869, 50895, 50896, 50901, 50902, 51346, 51347, 51515, 51516, 51616, 51617, 52003, 52005, 52006, 52007, 52008, 52396, 52397, 52813, 52814, 52915, 53014, 53015, 53260, 53950, 53951, 53952, 53953, 54117, 54372, 54373, 54374, 54375, - 54376, 54377, 54515, 54516, 54672, 54736, 54737, 54741, 54742, 54773, 54774, 54933, 54934, 55085, 55199, 55235, 55236, 57330 + 54376, 54377, 54515, 54516, 54672, 54736, 54737, 54741, 54742, 54773, 54774, 54933, 54934, 55085, 55199, 55235, 55236, 57330, + 58627, 58628, 58629, 58630, 58128 // Charred Island, Sunbleak, and Deepfin bank chests }; } From 72218c314047cb35e56863697fd77e73e9fcc856 Mon Sep 17 00:00:00 2001 From: chsami Date: Sun, 8 Feb 2026 19:42:37 +0100 Subject: [PATCH 02/17] docs: add architecture decision records for project structure and caching --- AGENTS.md | 140 ++++++------------ cache/README.md | 18 +++ docs/ARCHITECTURE.md | 36 +++++ docs/INDEX.md | 7 + .../adr-0001-record-architecture-decisions.md | 14 ++ .../adr-0002-composite-build-structure.md | 14 ++ .../adr-0003-queryable-cache-pattern.md | 14 ++ .../adr-0004-shaded-distribution-packaging.md | 14 ++ runelite-api/README.md | 20 +++ runelite-client/README.md | 25 ++++ .../microbot/BlockingEventManager.java | 8 + .../client/plugins/microbot/IScript.java | 8 + .../client/plugins/microbot/Microbot.java | 4 + .../client/plugins/microbot/Script.java | 36 +++-- .../client/plugins/microbot/util/Global.java | 13 +- runelite-gradle-plugin/README.md | 19 +++ runelite-jshell/README.md | 18 +++ 17 files changed, 300 insertions(+), 108 deletions(-) create mode 100644 cache/README.md create mode 100644 docs/ARCHITECTURE.md create mode 100644 docs/INDEX.md create mode 100644 docs/decisions/adr-0001-record-architecture-decisions.md create mode 100644 docs/decisions/adr-0002-composite-build-structure.md create mode 100644 docs/decisions/adr-0003-queryable-cache-pattern.md create mode 100644 docs/decisions/adr-0004-shaded-distribution-packaging.md create mode 100644 runelite-api/README.md create mode 100644 runelite-client/README.md create mode 100644 runelite-gradle-plugin/README.md create mode 100644 runelite-jshell/README.md diff --git a/AGENTS.md b/AGENTS.md index d6955dccfc4..ea6744059a2 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,98 +1,44 @@ -# Microbot API Guide (for Claude) +# Microbot Project Notes (for Codex) + +## Microbot at a Glance +Microbot is a RuneLite-based Old School RuneScape client fork with an always-on hidden plugin that hosts automation scripts. It packages a shaded client for end users and keeps developer ergonomics via Queryable caches and script helpers under `microbot/util`. The build mirrors upstream RuneLite as a composite Gradle setup. + +## Tech Stack +- Java target 11 (develop/run with JDK 17+), Gradle wrapper, composite builds (`cache`, `runelite-api`, `runelite-client`, `runelite-gradle-plugin`, `runelite-jshell`). +- RuneLite client + plugin APIs, LWJGL, Guice, Lombok, OkHttp, Gson, Logback/SLF4J. +- CI helper `ci/build.sh` bootstraps `glslang` then runs `./gradlew :buildAll`. + +## Repo Map +- `runelite-client/` – Main client (`:client`) containing the Microbot plugin and shaded jar assembly. +- `runelite-api/` – RuneLite API included build consumed by the client. +- `runelite-gradle-plugin/` – Gradle plugins for assemble/index/jarsign tasks. +- `runelite-jshell/` – JShell support artifacts. +- `cache/` – Cache tools/build used by RuneLite. +- `docs/` – User/dev docs and static site assets. +- `config/` – Shared Checkstyle configuration. +- `ci/` – CI build helper script. + +## How to Validate Changes +- Fast sanity: `./gradlew :client:compileJava` +- Full build (all included builds): `./gradlew buildAll` +- Assemble shaded client: `./gradlew :client:assemble` (creates `runelite-client/build/libs/*-shaded.jar` and `microbot-.jar`) +- Tests are disabled by default via Gradle config; enable/selectively run if you add tests (`./gradlew :client:runTests` or `runDebugTests`). + +## Non-Negotiable Rules +- Never instantiate caches or queryables directly; always use `Microbot.getRs2XxxCache().query()` or `.getStream()` (see `runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/QUERYABLE_API.md`). +- Do not block or sleep on the RuneLite client thread; long work belongs on script/executor threads. +- Keep logging minimal; avoid PII/session identifiers and respect existing log levels/patterns. +- Preserve the hidden/always-on nature of `MicrobotPlugin` and its config panel wiring. +- Follow Checkstyle/Lombok patterns already in the codebase; do not downgrade security (e.g., telemetry token handling, HTTP clients) without discussion. + +## Review Guidelines +- P0: Anything that can crash the client, block the client thread, break world hopping/login, corrupt cache/queryable invariants, or expose credentials/telemetry tokens. +- P1: Regressions to script loop timing, overlay correctness, plugin discovery/config panels, packaging (shaded jar/version props), or build reproducibility. +- Check threading (client vs script), cache access patterns, Gradle task wiring, and error handling around network calls. + +## When Unsure +- Start with `docs/ARCHITECTURE.md` and `docs/decisions/` for background. +- API and script usage: `runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/README.md` and `QUERYABLE_API.md`. +- Development/setup: `docs/development.md`; installation: `docs/installation.md`. +- Still unclear? Ask in Discord (link in `README.md`) or leave TODO with assumption noted. -## Scope & Paths -- Primary plugin code: `runelite-client/src/main/java/net/runelite/client/plugins/microbot`. -- Queryable API docs: `.../microbot/api/QUERYABLE_API.md`; quick read: `api/README.md`. -- Keep new scripts inside the microbot plugin; share helpers under `microbot/util`. -- Config UI for microbot plugins is rendered via `plugins/microbot/ui/MicrobotConfigPanel` (not the default RuneLite config panel); put config UI changes there. - -## Paths & Builds -- Plugin sources live in `runelite-client/src/main/java/net/runelite/client/plugins/microbot`. -- The queryable API lives in `.../microbot/api`; full guide: `.../microbot/api/QUERYABLE_API.md`. -- Quick builds: `./gradlew :runelite-client:compileJava`; full build: `./gradlew build`. - -## Cache & Queryable API - -### Singleton Pattern -All caches are `@Singleton` classes injected via Guice and exposed through `Microbot` static getters: - -```java -@Singleton -public final class Rs2NpcCache { - @Inject - public Rs2NpcCache(Client client, ClientThread clientThread) { ... } - - public Stream getStream() { ... } - public Rs2NpcQueryable query() { return new Rs2NpcQueryable(); } -} -``` - -### Usage Rules - -**CRITICAL:** Never instantiate caches or queryables directly. Always access via `Microbot.getRs2XxxCache()`: - -```java -// ❌ WRONG - Don't instantiate caches -Rs2NpcCache cache = new Rs2NpcCache(); - -// ❌ WRONG - Don't instantiate queryables directly -Rs2NpcModel npc = new Rs2NpcQueryable().withName("Banker").nearest(); - -// ✅ CORRECT - Use Microbot.getRs2XxxCache().query() -Rs2NpcModel npc = Microbot.getRs2NpcCache().query() - .withName("Banker") - .nearest(); - -// ✅ CORRECT - Other caches -Rs2TileObjectModel tree = Microbot.getRs2TileObjectCache().query().withName("Tree").nearest(); -Rs2TileItemModel item = Microbot.getRs2TileItemCache().query().withName("Bones").nearest(); -Rs2PlayerModel player = Microbot.getRs2PlayerCache().query().withName("PlayerName").first(); - -// ✅ CORRECT - Direct stream access -Rs2NpcModel firstNpc = Microbot.getRs2NpcCache().getStream() - .filter(npc -> npc.getName() != null) - .findFirst() - .orElse(null); - -// ✅ CORRECT - Boat cache (no queryable, direct methods) -Rs2BoatModel boat = Microbot.getRs2BoatCache().getLocalBoat(); -``` - -### Available Caches - -| Cache | Accessor | Methods | -|-------|----------|---------| -| `Rs2NpcCache` | `Microbot.getRs2NpcCache()` | `.query()`, `.getStream()` | -| `Rs2PlayerCache` | `Microbot.getRs2PlayerCache()` | `.query()`, `.getStream()` | -| `Rs2TileItemCache` | `Microbot.getRs2TileItemCache()` | `.query()`, `.getStream()` | -| `Rs2TileObjectCache` | `Microbot.getRs2TileObjectCache()` | `.query()`, `.getStream()` | -| `Rs2BoatCache` | `Microbot.getRs2BoatCache()` | `.getLocalBoat()`, `.getBoat(player)` | - -### Boat World View Support -When querying objects on a boat, use `.fromWorldView()` to search the player's current world view: - -```java -// Query objects in the boat's world view -var sails = Microbot.getRs2TileObjectCache().query() - .fromWorldView() - .withName("Sails") - .nearest(); -``` - -## Interaction & Timing Tips -- Never sleep on the RuneLite client thread; use the script thread with `sleep(...)` / `sleepUntil(...)`. -- After interactions, wait for state changes (e.g., `Rs2Bank.isOpen()`, `Rs2Player.isAnimating()`). -- Limit search radius with `.within(...)` to reduce overhead, and cache query results when reusing in a loop. - -## Helpful References -- Example templates: `runelite-client/src/main/java/net/runelite/client/plugins/microbot/example/`. -- API examples: `api/*/` directories contain `*ApiExample.java` files for NPCs, tile items, players, and objects. -- Core utilities (legacy but still useful): `microbot/util` (e.g., `Rs2Inventory`, `Rs2Bank`, `Rs2Walker`). - -## QuestScript Loop (Quest Helper) -- `QuestScript.run(config, plugin)` sets a 400–1000ms fixed-delay loop; exits early if quest helper is toggled off, not logged in, paused (`super.run()`), or no quest is selected, and waits out player animations. -- Captures the active `QuestStep`, marks when dialogue starts, auto-chooses matching dialogue options, and clicks highlighted widgets (special shop buy for Pirate's Treasure). -- Runs quest-specific logic via `QuestRegistry.getQuest(...).executeCustomLogic()` (Pirate's Treasure gets the plugin injected). -- While incomplete: handles dialogue quirks (Cook's Assistant/Pirate's Treasure), exits cutscenes, clears walk targets when talking, and manages reachability flags. -- Requirement phase: equips required items, warns on missing items (rate-limited), and attempts to acquire them by looting nearby or walking toward the defined point; prioritizes item-on-item detailed steps before other step types. -- Dispatch order: `ConditionalStep` → `NpcStep` → `ObjectStep` → `DigStep` → `PuzzleStep`; per-type handlers choose the correct menu action, manage line-of-sight and walkable tiles, and call `sleepUntil` to wait for movement/animation/interactions before looping. diff --git a/cache/README.md b/cache/README.md new file mode 100644 index 00000000000..f89bb3628de --- /dev/null +++ b/cache/README.md @@ -0,0 +1,18 @@ +# cache + +What it does: Included build that packages cache tooling/resources required by the RuneLite client (mirrors upstream RuneLite `cache` module). + +Public entry points +- Library/tooling jar only; no runtime main. + +How to build/test +- From root: `./gradlew -p cache build` +- Included in `./gradlew buildAll`. + +Key invariants/constraints +- Must stay version-aligned with `runelite-client` to avoid cache format mismatches. +- Build outputs are consumed during shaded client assembly; avoid breaking task names or published coordinates. + +Links +- Architecture: `../docs/ARCHITECTURE.md` +- ADR 0002 (composite build): `../docs/decisions/adr-0002-composite-build-structure.md` diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md new file mode 100644 index 00000000000..ce48f2487d4 --- /dev/null +++ b/docs/ARCHITECTURE.md @@ -0,0 +1,36 @@ +# Architecture + +## Components & Interaction +- **RuneLite client (`runelite-client`)**: Main application with Microbot hidden plugin (`MicrobotPlugin`) always enabled; entrypoint `net.runelite.client.RuneLite`. Builds shaded distribution via `shadowJar` + `microbotReleaseJar`. +- **Microbot runtime**: `Microbot` singleton exposes caches, utilities, and script lifecycle helpers; `Script` base class drives scheduled script loops; `BlockingEventManager` preempts scripts when required UI/game states are detected. +- **Queryable caches**: Guice-injected caches (`Rs2NpcCache`, `Rs2PlayerCache`, `Rs2TileItemCache`, `Rs2TileObjectCache`, `Rs2BoatCache`, `Rs2PlayerStateCache`) updated per tick and accessed via `Microbot.getRs2XxxCache().query()` or `.getStream()`. World-view aware for boats. +- **Utilities (`microbot/util`)**: Facades over RuneLite APIs for player, inventory, banking, walking, etc.; expected to run on script threads, not the client thread. +- **Included builds**: `runelite-api` (shared API artifacts), `runelite-gradle-plugin` (assemble/index/jarsign tasks), `cache` (cache tooling), `runelite-jshell` (JShell support). Root Gradle orchestrates via composite build. +- **Telemetry/API**: `MicrobotApi` sends session/open/install pings to `https://microbot.cloud/api` using OkHttp; token bundled in code. + +## Key Data Flows +- User starts client → `MicrobotClientLoader` fetches jav_config/world info → RuneLite client loads → `MicrobotPlugin` starts, registers overlays/config panels and initializes caches. +- Script loop (`Script.run()` implementations) executes on scheduled executors → queries caches via Queryable API → performs interactions through utilities (`Rs2Inventory`, `Rs2Walker`, etc.) → waits with `sleepUntil` helpers. +- Blocking events (`BlockingEventManager`) continuously validate (e.g., welcome screen, bank popups) → if triggered, they run on a dedicated executor and block script progression until resolved. +- Telemetry flow: `MicrobotApi.microbotOpen/microbotPing/microbotDelete` invoke remote API with session UUID and client version; failures are logged at debug level. + +## Runtime Boundaries +- **Threads**: Client thread (never block/sleep); script/executor threads (automation logic, sleeps allowed); blocking-event executor (resolves UI blockers). Use `ClientThread.runOnClientThreadOptional` for safe client access. +- **Services vs libraries**: Microbot plugin runs inside client process; no external services beyond Microbot cloud API; caches are in-memory per client instance. +- **Distribution**: Shaded jar (`*-shaded.jar` and `microbot-.jar`) produced in `runelite-client/build/libs`. + +## Configuration & Environments +- Gradle properties: `gradle.properties` holds `microbot.version`, `microbot.commit.sha`, optional repo credentials (`microbot.repo.*`), and `glslang.path` (populated by CI script). +- Runtime config: `MicrobotClientLoader` consumes `RuneLiteProperties` for jav_config URL; falls back to world-supplied hosts on failure. `MicrobotVersionChecker` logs current version/commit on startup. +- Logging: Game chat logging configurable via `MicrobotConfig` (patterns/levels, microbot-only filter); logback appender wired at plugin startup. + +## Non-Obvious Behaviors +- Caches refresh at most once per game tick; repeated queries within the same tick reuse cached lists. +- `BlockingEventManager` uses exponential backoff when no events validate to reduce overhead; events are re-queued if execution fails. +- Tests are disabled globally in `runelite-client/build.gradle.kts`; enabling requires flipping `enabled` on `Test` tasks or using `runTests`/`runDebugTests` tasks. +- World hopping short-circuits if the player is interacting or already hopping; confirmation widget auto-click handled in `Microbot.hopToWorld`. + +## References +- Queryable API guide: `../runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/QUERYABLE_API.md` +- Development setup: `development.md` +- Decision records: `decisions/` diff --git a/docs/INDEX.md b/docs/INDEX.md new file mode 100644 index 00000000000..510fa90ea20 --- /dev/null +++ b/docs/INDEX.md @@ -0,0 +1,7 @@ +- [Architecture](ARCHITECTURE.md) +- [Decision Records](decisions/adr-0001-record-architecture-decisions.md) +- [Development Setup](development.md) +- [Installation](installation.md) +- [API Overview](api/README.md) +- [Queryable API Guide](../runelite-client/src/main/java/net/runelite/client/plugins/microbot/api/QUERYABLE_API.md) +- [Gallery](gallery.md) diff --git a/docs/decisions/adr-0001-record-architecture-decisions.md b/docs/decisions/adr-0001-record-architecture-decisions.md new file mode 100644 index 00000000000..9df6aabba4b --- /dev/null +++ b/docs/decisions/adr-0001-record-architecture-decisions.md @@ -0,0 +1,14 @@ +# ADR 0001: Record Architecture Decisions + +- Status: Accepted (2026-02-08) + +## Context +Contributors need a lightweight, traceable way to capture architectural choices across the RuneLite+Microbot composite build without scattering rationale in PRs. + +## Decision +Adopt Architecture Decision Records (ADRs) stored under `docs/decisions/` with sequential numbering, concise rationale, and links from `docs/INDEX.md`. + +## Consequences +- New significant architectural choices are documented via ADRs. +- Reviewers expect ADR updates when behavior or structure changes at module/runtime boundaries. +- Past rationale is easy to reference for future Codex sessions and human maintainers. diff --git a/docs/decisions/adr-0002-composite-build-structure.md b/docs/decisions/adr-0002-composite-build-structure.md new file mode 100644 index 00000000000..7338b06f4c5 --- /dev/null +++ b/docs/decisions/adr-0002-composite-build-structure.md @@ -0,0 +1,14 @@ +# ADR 0002: Composite Build Structure + +- Status: Accepted (2026-02-08) + +## Context +The project mirrors upstream RuneLite by using included builds (`cache`, `runelite-api`, `runelite-gradle-plugin`, `runelite-jshell`) plus the `:client` project. Flattening or vendoring these modules would simplify the tree but risk divergence from upstream tooling and artifacts. + +## Decision +Keep the composite Gradle setup defined in `settings.gradle.kts`, treating included builds as first-class modules wired via `common.settings.gradle.kts` for shared configuration. + +## Consequences +- Contributors work inside the existing multi-project layout; IDEs must import included builds. +- Shared tasks like `buildAll`/`cleanAll` orchestrate across modules; single-module builds remain available for quick iterations (e.g., `:client:compileJava`). +- Dependency version alignment stays consistent with upstream RuneLite release practices. diff --git a/docs/decisions/adr-0003-queryable-cache-pattern.md b/docs/decisions/adr-0003-queryable-cache-pattern.md new file mode 100644 index 00000000000..e7974e41e43 --- /dev/null +++ b/docs/decisions/adr-0003-queryable-cache-pattern.md @@ -0,0 +1,14 @@ +# ADR 0003: Queryable Cache Pattern for Game Entities + +- Status: Accepted (2026-02-08) + +## Context +Scripts frequently need fast, thread-safe access to NPCs, players, tile objects/items, and boat state. Direct RuneLite API traversal on script threads is error-prone and can violate client-thread rules. + +## Decision +Expose entity data through Guice-managed caches (`Rs2NpcCache`, `Rs2PlayerCache`, `Rs2TileObjectCache`, `Rs2TileItemCache`, `Rs2BoatCache`, `Rs2PlayerStateCache`) accessed only via `Microbot.getRs2XxxCache().query()` or `.getStream()`. Caches refresh per game tick and support world-view queries for boat contexts. + +## Consequences +- Scripts must not instantiate caches/queryables directly; tests and new utilities should follow the same pattern. +- Cache access stays tick-consistent and client-thread safe via `ClientThread.runOnClientThreadOptional` wrappers where needed. +- Performance remains predictable by limiting repeated client traversal and encouraging query filters (e.g., `within`, `fromWorldView`). diff --git a/docs/decisions/adr-0004-shaded-distribution-packaging.md b/docs/decisions/adr-0004-shaded-distribution-packaging.md new file mode 100644 index 00000000000..c505848ed2e --- /dev/null +++ b/docs/decisions/adr-0004-shaded-distribution-packaging.md @@ -0,0 +1,14 @@ +# ADR 0004: Shaded Distribution Packaging + +- Status: Accepted (2026-02-08) + +## Context +End users install Microbot as a single jar. The client depends on multiple modules and native LWJGL artifacts, so an assembled, reproducible output is required. Upstream RuneLite uses shaded packaging; Microbot extends this with versioned release naming. + +## Decision +Produce distribution jars via the `shadowJar` task in `runelite-client`, generating both `*-shaded.jar` and `microbot-.jar` (`microbotReleaseJar`). Keep this as the primary delivery artifact for releases and local testing. + +## Consequences +- Build pipelines and docs reference `runelite-client/build/libs/microbot-.jar` as the canonical output. +- Any changes to packaging (signing, classifiers, contents) must update Gradle tasks and release instructions. +- Developers can rely on `./gradlew :client:assemble` to reproduce end-user artifacts without additional tooling. diff --git a/runelite-api/README.md b/runelite-api/README.md new file mode 100644 index 00000000000..3eacd5b4e36 --- /dev/null +++ b/runelite-api/README.md @@ -0,0 +1,20 @@ +# runelite-api + +What it does: Provides the RuneLite public API artifacts consumed by `runelite-client` and plugins (interfaces, events, data models). + +Public entry points +- Library jar only; no runtime main. +- Published via included-build coordinates `net.runelite:runelite-api`. + +How to build/test +- From repo root: `./gradlew -p runelite-api build` +- Part of aggregate tasks: `./gradlew buildAll` +- Tests mirror upstream RuneLite defaults. + +Key invariants/constraints +- API surface must stay compatible with the client; changes here ripple to `runelite-client` and plugin code. +- Avoid Microbot-specific types creeping into the shared API unless intentionally upstreamed. + +Links +- Architecture: `../docs/ARCHITECTURE.md` +- ADR 0002 (composite build): `../docs/decisions/adr-0002-composite-build-structure.md` diff --git a/runelite-client/README.md b/runelite-client/README.md new file mode 100644 index 00000000000..a711a7c0809 --- /dev/null +++ b/runelite-client/README.md @@ -0,0 +1,25 @@ +# runelite-client + +What it does: Main RuneLite client fork that embeds the hidden, always-on Microbot plugin, overlays, and config panels. Builds shaded artifacts for end users. + +Public entry points +- `net.runelite.client.RuneLite` (application main class) +- `net.runelite.client.plugins.microbot.MicrobotPlugin` (plugin descriptor/boot) +- Gradle tasks: `:client:runDebug`, `:client:assemble` (`shadowJar` + `microbotReleaseJar`) + +How to run/test +- Fast compile: `./gradlew :client:compileJava` +- Run with JDWP: `./gradlew :client:runDebug` +- Assemble shaded jars: `./gradlew :client:assemble` +- Tests are disabled by default; if enabled, use `./gradlew :client:runTests` (or `runDebugTests` for debugger). + +Key invariants/constraints +- Never block/sleep on the client thread; use script/executor threads and `ClientThread.runOnClientThreadOptional` for client access. +- Use Queryable caches only via `Microbot.getRs2XxxCache().query()`/`.getStream()`; do not instantiate caches/queryables manually. +- Preserve hidden/always-on plugin descriptor and Microbot config panel wiring. +- Version and commit values are injected during `processResources`; keep `gradle.properties` values in sync when packaging. + +Links +- Architecture: `../docs/ARCHITECTURE.md` +- ADRs: `../docs/decisions/` +- API guide: `src/main/java/net/runelite/client/plugins/microbot/api/QUERYABLE_API.md` diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/BlockingEventManager.java b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/BlockingEventManager.java index 8bb35b9b5bf..67bcd9ab97e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/BlockingEventManager.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/BlockingEventManager.java @@ -14,6 +14,10 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +/** + * Orchestrates detection and execution of blocking events that must run before scripts continue. + * Maintains a prioritized list, periodically validates them with backoff, and runs at most one at a time on a dedicated executor. + */ @Slf4j public class BlockingEventManager { @@ -151,6 +155,10 @@ private void validateAndEnqueueWithBackoff() { * If an event is already running, returns true immediately. * Otherwise poll the queue; if we get an event, mark running and execute. */ + /** + * Returns {@code true} if a blocking event is currently running or one was dequeued and scheduled. + * Called from {@link net.runelite.client.plugins.microbot.Script#run()} to pause script loops until blockers finish. + */ public boolean shouldBlockAndProcess() { if (isRunning.get()) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/IScript.java b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/IScript.java index 87874208c13..cde2425cce5 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/IScript.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/IScript.java @@ -1,5 +1,13 @@ package net.runelite.client.plugins.microbot; +/** + * Contract for Microbot scripts executed by the scheduler. + * Implementations should return {@code true} from {@link #run()} when the loop should continue. + */ +/** + * Contract for Microbot scripts executed by scheduler loops. + * Return {@code true} to continue the loop iteration; {@code false} pauses/aborts the caller's cycle. + */ public interface IScript { boolean run(); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/Microbot.java b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/Microbot.java index dcd49c1f96e..5ba2294614d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/Microbot.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/Microbot.java @@ -293,6 +293,10 @@ public static boolean isHopping() { return idx == GameState.HOPPING; } + /** + * Attempts to hop to the specified world, handling confirmation dialogs and guarding against unsafe states + * (interacting player, existing hop, invalid world). Returns {@code true} if a hop is initiated. + */ public static boolean hopToWorld(int worldNumber) { if (!Microbot.isLoggedIn()) { return false; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/Script.java b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/Script.java index 443dccdbf63..d44945f8aed 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/Script.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/Script.java @@ -16,21 +16,28 @@ import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; +/** + * Base class for Microbot automation scripts. + * Provides scheduling helpers, guards against client-thread misuse, and common shutdown/reset logic. + */ @Slf4j public abstract class Script extends Global implements IScript { - protected ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10, - new ThreadFactory() { - private final AtomicInteger threadNumber = new AtomicInteger(1); - @Override - public Thread newThread(@NotNull Runnable r) { - Thread t = new Thread(r); - t.setName(Script.this.getClass().getSimpleName() + "-" + threadNumber.getAndIncrement()); - return t; - } - }); + protected ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10, + new ThreadFactory() { + private final AtomicInteger threadNumber = new AtomicInteger(1); + @Override + public Thread newThread(@NotNull Runnable r) { + Thread t = new Thread(r); + t.setName(Script.this.getClass().getSimpleName() + "-" + threadNumber.getAndIncrement()); + return t; + } + }); protected ScheduledFuture scheduledFuture; protected ScheduledFuture mainScheduledFuture; + /** + * Indicates whether the main scheduled script loop is still active. + */ public boolean isRunning() { return mainScheduledFuture != null && !mainScheduledFuture.isDone(); } @@ -38,6 +45,10 @@ public boolean isRunning() { @Getter protected static WorldPoint initialPlayerLocation; + /** + * Cancel scheduled tasks, clear shared state, and reset helpers. + * Safe to call multiple times; no-ops if already shut down. + */ public void shutdown() { if (mainScheduledFuture != null && !mainScheduledFuture.isDone()) { mainScheduledFuture.cancel(true); @@ -55,6 +66,11 @@ public void shutdown() { } } + /** + * Default pre-loop guard invoked by script schedulers. + * Returns {@code false} to pause a loop when a blocking event is executing, scripts are paused, + * tutorial island is incomplete, or the current thread is interrupted. + */ public boolean run() { //Avoid executing any blocking events if the player hasn't finished Tutorial Island if (Microbot.isLoggedIn() && !Rs2Player.hasCompletedTutorialIsland()) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/Global.java b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/Global.java index 5be74bcd43e..e6d51fbf458 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/Global.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/Global.java @@ -59,10 +59,18 @@ public static T sleepUntilNotNull(Callable method, int timeoutMillis) { return sleepUntilNotNull(method, timeoutMillis, 100); } + /** + * Polls until the supplied condition becomes true or timeout elapses. + * Must not be invoked on the client thread; callers should run on script/executor threads. + */ public static boolean sleepUntil(BooleanSupplier awaitedCondition) { return sleepUntil(awaitedCondition, 5000); } + /** + * Polls until the supplied condition becomes true or the given duration elapses. + * No-op on the client thread to avoid blocking RuneLite. + */ public static boolean sleepUntil(BooleanSupplier awaitedCondition, int time) { if (Microbot.getClient().isClientThread()) return false; boolean done = false; @@ -147,6 +155,9 @@ public static boolean sleepUntilTrue(BooleanSupplier awaitedCondition, BooleanSu return false; } + /** + * Polls a condition on the client thread until true or timeout, without blocking the client thread itself. + */ public static void sleepUntilOnClientThread(BooleanSupplier awaitedCondition) { sleepUntilOnClientThread(awaitedCondition, Rs2Random.between(2500, 5000)); } @@ -168,4 +179,4 @@ public boolean sleepUntilTick(int ticksToWait) { int startTick = Microbot.getClient().getTickCount(); return Global.sleepUntil(() -> Microbot.getClient().getTickCount() >= startTick + ticksToWait, ticksToWait * 600 + 2000); } -} \ No newline at end of file +} diff --git a/runelite-gradle-plugin/README.md b/runelite-gradle-plugin/README.md new file mode 100644 index 00000000000..fdcba618677 --- /dev/null +++ b/runelite-gradle-plugin/README.md @@ -0,0 +1,19 @@ +# runelite-gradle-plugin + +What it does: Houses custom Gradle plugins used by the client build for assembling resources, indexing, and jar signing. + +Public entry points +- Plugin IDs: `net.runelite.runelite-gradle-plugin.assemble`, `net.runelite.runelite-gradle-plugin.index`, `net.runelite.runelite-gradle-plugin.jarsign`. +- Consumed by `runelite-client/build.gradle.kts`. + +How to build/test +- From root: `./gradlew -p runelite-gradle-plugin build` +- Included in `./gradlew buildAll`. + +Key invariants/constraints +- Keep plugin IDs and task contracts stable; `runelite-client` relies on them for resource overlay, index generation, and shaded packaging. +- Changes should remain compatible with composite build import in IDEs. + +Links +- Architecture: `../docs/ARCHITECTURE.md` +- ADR 0002 (composite build): `../docs/decisions/adr-0002-composite-build-structure.md` diff --git a/runelite-jshell/README.md b/runelite-jshell/README.md new file mode 100644 index 00000000000..7ee045a6f65 --- /dev/null +++ b/runelite-jshell/README.md @@ -0,0 +1,18 @@ +# runelite-jshell + +What it does: Provides JShell support artifacts used alongside the RuneLite client for interactive evaluation and debugging. + +Public entry points +- Library jar only; consumed by `runelite-client` as project dependency `:jshell`. + +How to build/test +- From root: `./gradlew -p runelite-jshell build` +- Included in `./gradlew buildAll`. + +Key invariants/constraints +- Keep alignment with RuneLite client versions to avoid classpath mismatches. +- No Microbot-specific logic should leak here; it must stay a generic JShell helper module. + +Links +- Architecture: `../docs/ARCHITECTURE.md` +- ADR 0002 (composite build): `../docs/decisions/adr-0002-composite-build-structure.md` From 56cf5701ce89fd1e1b4fd139bd56e33b984e080d Mon Sep 17 00:00:00 2001 From: Max Weber Date: Fri, 6 Feb 2026 19:17:01 -0700 Subject: [PATCH 03/17] client: support tcp rtt on linux & macos --- .../worldhopper/WorldHopperPlugin.java | 6 +- .../worldhopper/ping/LinuxTCPInfo.java | 179 ++++++++++++++++++ .../ping/MacOSTCPConnectionInfo.java | 105 ++++++++++ .../client/plugins/worldhopper/ping/Ping.java | 49 ++++- .../plugins/worldhopper/ping/RLLibC.java | 4 + .../ping/RetransmitCalculator.java | 18 +- .../plugins/worldhopper/ping/TCPInfo.java | 36 ++++ .../plugins/worldhopper/ping/TCP_INFO_v0.java | 20 +- 8 files changed, 396 insertions(+), 21 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/LinuxTCPInfo.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/MacOSTCPConnectionInfo.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/TCPInfo.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java index 7805e0cc9be..28889aa88bd 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java @@ -83,7 +83,7 @@ import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.worldhopper.ping.Ping; import net.runelite.client.plugins.worldhopper.ping.RetransmitCalculator; -import net.runelite.client.plugins.worldhopper.ping.TCP_INFO_v0; +import net.runelite.client.plugins.worldhopper.ping.TCPInfo; import net.runelite.client.ui.ClientToolbar; import net.runelite.client.ui.NavigationButton; import net.runelite.client.ui.overlay.OverlayManager; @@ -912,10 +912,10 @@ private void pingCurrentWorld() int rtt = -1; if (fd != null) { - TCP_INFO_v0 tcpInfo = Ping.getTcpInfo(fd); + TCPInfo tcpInfo = Ping.getTCPInfo(fd); if (tcpInfo != null) { - rtt = (int) (tcpInfo.RttUs.longValue() / 1000L); + rtt = (int) (tcpInfo.getRTT() / 1000L); retransmitCalculator.record(tcpInfo); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/LinuxTCPInfo.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/LinuxTCPInfo.java new file mode 100644 index 00000000000..bfbe38368f1 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/LinuxTCPInfo.java @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2026 Abex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.plugins.worldhopper.ping; + +import com.sun.jna.Structure; +import java.util.List; + +public class LinuxTCPInfo extends Structure implements TCPInfo +{ + public byte state; + public byte ca_state; + public byte retransmits; + public byte probes; + public byte backoff; + public byte options; + public byte wscale; + public byte flags; + + public int rto; + public int ato; + public int snd_mss; + public int rcv_mss; + + public int unacked; + public int sacked; + public int lost; + public int retrans; + public int fackets; + + public int last_data_sent; + public int last_ack_sent; + public int last_data_recv; + public int last_ack_recv; + + public int pmtu; + public int rcv_ssthresh; + public int rtt; + public int rttvar; + public int snd_ssthresh; + public int snd_cwnd; + public int advmss; + public int reordering; + + public int rcv_rtt; + public int rcv_space; + + public int total_retrans; + + public long pacing_rate; + public long max_pacing_rate; + public long bytes_acked; + public long bytes_received; + public int segs_out; + public int segs_in; + + public int notsent_bytes; + public int min_rtt; + public int data_segs_in; + public int data_segs_out; + + public long delivery_rate; + + public long busy_time; + public long rwnd_limited; + public long sndbuf_limited; + + public int delivered; + public int delivered_ce; + + public long bytes_sent; + public long bytes_retrans; + public int dsack_dups; + public int reord_seen; + + public int rcv_ooopack; + + public int snd_wnd; + + @Override + protected List getFieldOrder() + { + return List.of( + "state", + "ca_state", + "retransmits", + "probes", + "backoff", + "options", + "wscale", + "flags", + "rto", + "ato", + "snd_mss", + "rcv_mss", + "unacked", + "sacked", + "lost", + "retrans", + "fackets", + "last_data_sent", + "last_ack_sent", + "last_data_recv", + "last_ack_recv", + "pmtu", + "rcv_ssthresh", + "rtt", + "rttvar", + "snd_ssthresh", + "snd_cwnd", + "advmss", + "reordering", + "rcv_rtt", + "rcv_space", + "total_retrans", + "pacing_rate", + "max_pacing_rate", + "bytes_acked", + "bytes_received", + "segs_out", + "segs_in", + "notsent_bytes", + "min_rtt", + "data_segs_in", + "data_segs_out", + "delivery_rate", + "busy_time", + "rwnd_limited", + "sndbuf_limited", + "delivered", + "delivered_ce", + "bytes_sent", + "bytes_retrans", + "dsack_dups", + "reord_seen", + "rcv_ooopack", + "snd_wnd" + ); + } + + @Override + public long getRTT() + { + return this.rtt & 0xFFFFFFFFL; + } + + @Override + public long getRetransmitted() + { + return total_retrans & 0xFFFFFFFFL; + } + + @Override + public long getTransmitted() + { + return segs_out & 0xFFFFFFFFL; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/MacOSTCPConnectionInfo.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/MacOSTCPConnectionInfo.java new file mode 100644 index 00000000000..a23b9ebb28d --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/MacOSTCPConnectionInfo.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2026 Abex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.plugins.worldhopper.ping; + +import com.sun.jna.Structure; +import java.util.List; + +public class MacOSTCPConnectionInfo extends Structure implements TCPInfo +{ + public byte state; + public byte snd_wscale; + public byte rcv_wscale; + public byte pad1; + public int options; + public int flags; + public int rto; + public int maxseg; + public int snd_ssthresh; + public int snd_cwnd; + public int snd_wnd; + public int snd_sbbytes; + public int rcv_wnd; + public int rttcur; + public int srtt; + public int rttvar; + public int tfo; + public long txpackets; + public long txbytes; + public long txretransmitbytes; + public long rxpackets; + public long rxbytes; + public long rxoutoforderbytes; + public long txretransmitpackets; + + @Override + protected List getFieldOrder() + { + return List.of( + "state", + "snd_wscale", + "rcv_wscale", + "pad1", + "options", + "flags", + "rto", + "maxseg", + "snd_ssthresh", + "snd_cwnd", + "snd_wnd", + "snd_sbbytes", + "rcv_wnd", + "rttcur", + "srtt", + "rttvar", + "tfo", + "txpackets", + "txbytes", + "txretransmitbytes", + "rxpackets", + "rxbytes", + "rxoutoforderbytes", + "txretransmitpackets" + ); + } + + @Override + public long getRTT() + { + return srtt * 1000L; + } + + @Override + public long getRetransmitted() + { + return txretransmitpackets; + } + + @Override + public long getTransmitted() + { + return txpackets; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/Ping.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/Ping.java index 8c11174ab33..179ea717011 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/Ping.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/Ping.java @@ -29,6 +29,7 @@ import com.sun.jna.Memory; import com.sun.jna.Native; import com.sun.jna.Pointer; +import com.sun.jna.Structure; import com.sun.jna.platform.win32.WinNT; import com.sun.jna.ptr.IntByReference; import java.io.FileDescriptor; @@ -39,6 +40,7 @@ import java.net.InetSocketAddress; import java.net.Socket; import java.net.UnknownHostException; +import javax.annotation.Nullable; import lombok.extern.slf4j.Slf4j; import net.runelite.client.util.OSType; import net.runelite.http.api.worlds.World; @@ -285,13 +287,23 @@ private static int tcpPing(InetAddress inetAddress) throws IOException } } - public static TCP_INFO_v0 getTcpInfo(FileDescriptor fd) + @Nullable + public static TCPInfo getTCPInfo(FileDescriptor fd) { - if (OSType.getOSType() != OSType.Windows) + switch (OSType.getOSType()) { - return null; + case Windows: + return getTCPInfoWindows(fd); + case MacOS: + case Linux: + return getTCPInfoNix(fd); + default: + return null; } + } + private static TCP_INFO_v0 getTCPInfoWindows(FileDescriptor fd) + { int handle; try { @@ -338,4 +350,35 @@ public static TCP_INFO_v0 getTcpInfo(FileDescriptor fd) info.read(); return info; } + + private static TCPInfo getTCPInfoNix(FileDescriptor fdObj) + { + int fd; + try + { + Field f = FileDescriptor.class.getDeclaredField("fd"); + f.setAccessible(true); + fd = f.getInt(fdObj); + } + catch (NoSuchFieldException | IllegalAccessException ex) + { + log.debug(null, ex); + return null; + } + + Structure out = OSType.getOSType() == OSType.MacOS + ? new MacOSTCPConnectionInfo() + : new LinuxTCPInfo(); + var size = new IntByReference(out.size()); + int err = RLLibC.INSTANCE.getsockopt(fd, RLLibC.IPPROTO_TCP, RLLibC.TCP_INFO, out.getPointer(), size.getPointer()); + out.read(); + + if (err != 0) + { + log.debug("getsockopt(TCP_INFO): {}", Native.getLastError()); + return null; + } + + return (TCPInfo) out; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/RLLibC.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/RLLibC.java index 3e49c501559..4e7c0e3e671 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/RLLibC.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/RLLibC.java @@ -37,8 +37,10 @@ interface RLLibC extends LibC int SOCK_DGRAM = 2; int SOL_SOCKET = OSType.getOSType() == OSType.MacOS ? 0xffff : 1; int IPPROTO_ICMP = 1; + int IPPROTO_TCP = 6; int SO_SNDTIMEO = OSType.getOSType() == OSType.MacOS ? 0x1005 : 21; int SO_RCVTIMEO = OSType.getOSType() == OSType.MacOS ? 0x1006 : 20; + int TCP_INFO = OSType.getOSType() == OSType.MacOS ? 0x106 : 11; int socket(int domain, int type, int protocol); @@ -47,4 +49,6 @@ interface RLLibC extends LibC int recvfrom(int sockfd, Pointer buf, int len, int flags, Pointer src_addr, Pointer addrlen); int setsockopt(int sockfd, int level, int optname, Pointer optval, int optlen); + + int getsockopt(int socket, int level, int option_name, Pointer option_value, Pointer option_len); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/RetransmitCalculator.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/RetransmitCalculator.java index 3ced1859c3e..a047f27cabc 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/RetransmitCalculator.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/RetransmitCalculator.java @@ -24,7 +24,6 @@ */ package net.runelite.client.plugins.worldhopper.ping; -import java.util.Arrays; import lombok.extern.slf4j.Slf4j; @Slf4j @@ -33,28 +32,19 @@ public class RetransmitCalculator private static final int SAMPLES = 16; private int index; - private long connectionTime; private final long[] bytesOut = new long[SAMPLES]; private final long[] bytesRetrans = new long[SAMPLES]; private int loss; - public void record(TCP_INFO_v0 info) + public void record(TCPInfo info) { int nextIndex = index++ & (SAMPLES - 1); - long connectionTime = info.ConnectionTimeMs.longValue(); - long out = info.BytesOut.longValue(); - long rt = info.BytesRetrans.longValue(); + long out = info.getTransmitted(); + long rt = info.getRetransmitted(); - log.trace("rtt: {}us bytes out: {} retrans: {}", info.RttUs.longValue(), out, rt); + log.trace("rtt: {}us out: {} retrans: {}", info.getRTT(), out, rt); - if (connectionTime < this.connectionTime) - { - Arrays.fill(bytesOut, 0L); - Arrays.fill(bytesRetrans, 0L); - } - - this.connectionTime = connectionTime; bytesOut[nextIndex] = out; bytesRetrans[nextIndex] = rt; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/TCPInfo.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/TCPInfo.java new file mode 100644 index 00000000000..1fc67c58381 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/TCPInfo.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2026 Abex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.plugins.worldhopper.ping; + +public interface TCPInfo +{ + /** + * Round trip time in µs + */ + long getRTT(); + + long getTransmitted(); + long getRetransmitted(); +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/TCP_INFO_v0.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/TCP_INFO_v0.java index a4596729087..e59b54f23b8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/TCP_INFO_v0.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/TCP_INFO_v0.java @@ -28,7 +28,7 @@ import com.sun.jna.platform.win32.WinDef; import java.util.List; -public class TCP_INFO_v0 extends Structure +public class TCP_INFO_v0 extends Structure implements TCPInfo { public WinDef.ULONG State; public WinDef.ULONG Mss; @@ -75,4 +75,22 @@ protected List getFieldOrder() "SynRetrans" ); } + + @Override + public long getRTT() + { + return RttUs.longValue(); + } + + @Override + public long getRetransmitted() + { + return BytesOut.longValue(); + } + + @Override + public long getTransmitted() + { + return BytesRetrans.longValue(); + } } From 57e58afe47c3e652314688660b6c7d5630fc3039 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 8 Feb 2026 11:34:59 -0500 Subject: [PATCH 04/17] world hopper: use rtt on macos/linux --- .../net/runelite/client/plugins/worldhopper/ping/Ping.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/Ping.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/Ping.java index 179ea717011..a90374c823e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/Ping.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/Ping.java @@ -93,15 +93,20 @@ public static int ping(World world, boolean useTcpPing) return p; case MacOS: case Linux: + p = -1; try { - return icmpPing(inetAddress, OSType.getOSType() == OSType.MacOS); + p = icmpPing(inetAddress, OSType.getOSType() == OSType.MacOS); } catch (IOException ex) { log.debug("error during icmp ping", ex); + } + if (p == -1 && useTcpPing) + { return tcpPing(inetAddress); } + return p; default: return tcpPing(inetAddress); } From 6c23985bb800dba65644acaf825fa16e8fb491ef Mon Sep 17 00:00:00 2001 From: Max Weber Date: Sat, 7 Feb 2026 12:59:08 -0700 Subject: [PATCH 05/17] hiscore: always default to NORMAL highscores this races both client startup and the default world plugin, so it doesn't reliably select a relevant world, and it can cause the plugin to crash on startup if the client starts with a FSW world --- .../runelite/client/plugins/hiscore/HiscorePanel.java | 11 +---------- .../client/plugins/hiscore/HiscorePanelTest.java | 3 --- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/HiscorePanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/HiscorePanel.java index 9b5844b2a6d..f428ca6c5f0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/HiscorePanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/HiscorePanel.java @@ -244,8 +244,7 @@ public void mousePressed(MouseEvent mouseEvent) tabGroup.addTab(tab); } - // Default selected tab is normal hiscores - resetEndpoints(); + tabGroup.select(tabGroup.getTab(0)); add(tabGroup, c); c.gridy++; @@ -696,14 +695,6 @@ private static String sanitize(String lookup) return lookup.replace('\u00A0', ' '); } - private void resetEndpoints() - { - // Select the correct tab based on the world type. - HiscoreEndpoint endpoint = plugin.getWorldEndpoint(); - int idx = ArrayUtils.indexOf(ENDPOINTS, endpoint); - tabGroup.select(tabGroup.getTab(idx)); - } - @VisibleForTesting static String formatLevel(int level) { diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/hiscore/HiscorePanelTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/hiscore/HiscorePanelTest.java index 6cccb7ff8f9..39835407475 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/hiscore/HiscorePanelTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/hiscore/HiscorePanelTest.java @@ -28,11 +28,9 @@ import net.runelite.client.game.SpriteManager; import net.runelite.client.hiscore.HiscoreClient; import static net.runelite.client.plugins.hiscore.HiscorePanel.formatLevel; -import net.runelite.client.hiscore.HiscoreEndpoint; import static org.junit.Assert.assertEquals; import org.junit.Test; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; public class HiscorePanelTest { @@ -40,7 +38,6 @@ public class HiscorePanelTest public void testConstructor() { HiscorePlugin plugin = mock(HiscorePlugin.class); - when(plugin.getWorldEndpoint()).thenReturn(HiscoreEndpoint.NORMAL); new HiscorePanel(mock(Client.class), plugin, mock(HiscoreConfig.class), mock(NameAutocompleter.class), mock(HiscoreClient.class), mock(SpriteManager.class)); } From 10bf3b88501d72c5084181106e5c2b795d80abdd Mon Sep 17 00:00:00 2001 From: chsami Date: Mon, 9 Feb 2026 05:59:38 +0100 Subject: [PATCH 06/17] fix(ships): correct menu option formatting for ship routes --- .../runelite/client/plugins/microbot/shortestpath/ships.tsv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/microbot/shortestpath/ships.tsv b/runelite-client/src/main/resources/net/runelite/client/plugins/microbot/shortestpath/ships.tsv index 6e5e350476e..97ade59f3a0 100644 --- a/runelite-client/src/main/resources/net/runelite/client/plugins/microbot/shortestpath/ships.tsv +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/microbot/shortestpath/ships.tsv @@ -1,7 +1,7 @@ # Origin Destination menuOption menuTarget objectID Skills Currency Quests isMembers Duration Display info # Port Sarim, Musa Point -3029 3217 0 2956 3143 1 Pay-fare;Captain Tobias;3644 30 Coins 10 Musa Point -2956 3146 0 3032 3217 1 Pay-Fare;Customs officer;3648 30 Coins 10 Port Sarim +3029 3217 0 2956 3143 1 Musa Point;Captain Tobias;3644 30 Coins 10 Musa Point +2956 3146 0 3032 3217 1 Port Sarim;Customs officer;3648 30 Coins 10 Port Sarim # Ardougne, Brimhaven, Rimmington 2673 3275 0 2775 3233 1 Brimhaven;Captain Barnaby;9250 30 Coins Y 6 Brimhaven 2673 3275 0 2915 3221 1 Rimmington;Captain Barnaby;9250 30 Coins Y 6 Rimmington From baf336d591723012d24c931e38659c4e5f8b7522 Mon Sep 17 00:00:00 2001 From: RuneLite Cache-Code Autoupdater Date: Tue, 10 Feb 2026 12:19:20 -0700 Subject: [PATCH 07/17] Update Quests to 2026-2-11 --- runelite-api/src/main/java/net/runelite/api/Quest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-api/src/main/java/net/runelite/api/Quest.java b/runelite-api/src/main/java/net/runelite/api/Quest.java index 8d4b9e2988e..be681e548b8 100644 --- a/runelite-api/src/main/java/net/runelite/api/Quest.java +++ b/runelite-api/src/main/java/net/runelite/api/Quest.java @@ -232,12 +232,12 @@ public enum Quest SHADOWS_OF_CUSTODIA(5190, "Shadows of Custodia"), SCRAMBLED(5191, "Scrambled!"), VALE_TOTEMS(5194, "Vale Totems"), - TUTORIAL_ISLAND(7033, "Tutorial Island"), PANDEMONIUM(7103, "Pandemonium"), PRYING_TIMES(7104, "Prying Times"), CURRENT_AFFAIRS(7105, "Current Affairs"), TROUBLED_TORTUGANS(7106, "Troubled Tortugans"), THE_RED_REEF(7107, "The Red Reef"), + LEARNING_THE_ROPES(9643, "Learning the Ropes"), ; @Getter From 314ef96a701f59b43bb527b8567473a20d75a0b5 Mon Sep 17 00:00:00 2001 From: RuneLite Cache-Code Autoupdater Date: Tue, 10 Feb 2026 12:19:20 -0700 Subject: [PATCH 08/17] Update Scripts to 2026-2-11 --- .../src/main/scripts/OptionsPanelZoomUpdater.hash | 2 +- .../src/main/scripts/OptionsPanelZoomUpdater.rs2asm | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/runelite-client/src/main/scripts/OptionsPanelZoomUpdater.hash b/runelite-client/src/main/scripts/OptionsPanelZoomUpdater.hash index 498f1efccaa..a4898ff6e02 100644 --- a/runelite-client/src/main/scripts/OptionsPanelZoomUpdater.hash +++ b/runelite-client/src/main/scripts/OptionsPanelZoomUpdater.hash @@ -1 +1 @@ -82E52039B52B9B52475BDF93508FFC3AC6BCE4183F725DA50FBA0E78D76985EE \ No newline at end of file +EE83501CDE10EEF0EF0CC75B7F41E075215C41B7C2D073449C9810A6FE85CC4B \ No newline at end of file diff --git a/runelite-client/src/main/scripts/OptionsPanelZoomUpdater.rs2asm b/runelite-client/src/main/scripts/OptionsPanelZoomUpdater.rs2asm index 2c2088898c8..3c714cf9e09 100644 --- a/runelite-client/src/main/scripts/OptionsPanelZoomUpdater.rs2asm +++ b/runelite-client/src/main/scripts/OptionsPanelZoomUpdater.rs2asm @@ -25,13 +25,13 @@ LABEL15: iconst 0 iconst 0 iconst 0 - iconst 7602234 + iconst 7602233 if_setposition return LABEL22: - iconst 7602233 + iconst 7602232 if_getwidth - iconst 7602234 + iconst 7602233 if_getwidth sub istore 2 @@ -80,6 +80,6 @@ LABEL58: iconst 0 iconst 0 iconst 0 - iconst 7602234 + iconst 7602233 if_setposition return From ff6bd1b1455ac656b814fde0c4baec508df266ea Mon Sep 17 00:00:00 2001 From: RuneLite Cache-Code Autoupdater Date: Tue, 10 Feb 2026 12:19:20 -0700 Subject: [PATCH 09/17] Update Widget IDs to 2026-2-11 --- runelite-api/src/main/interfaces/interfaces.toml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/runelite-api/src/main/interfaces/interfaces.toml b/runelite-api/src/main/interfaces/interfaces.toml index 0742286b166..334a8da0e3c 100644 --- a/runelite-api/src/main/interfaces/interfaces.toml +++ b/runelite-api/src/main/interfaces/interfaces.toml @@ -601,9 +601,9 @@ solved=8 [music] id=239 container=0 -scroll_container=4 -list=6 -scrollbar=7 +scroll_container=8 +list=10 +scrollbar=11 [nightmare_pillar_health] id=413 @@ -785,11 +785,11 @@ init=1 [settings_side] id=116 -camera_zoom_slider_track=57 -music_slider=98 -music_slider_step_holder=110 -sound_effect_slider=112 -area_sound_slider=126 +camera_zoom_slider_track=56 +music_slider=96 +music_slider_step_holder=108 +sound_effect_slider=110 +area_sound_slider=124 [shop] id=300 From b4d9ce697af9c1d92f3977f08f8ffd0137d9b303 Mon Sep 17 00:00:00 2001 From: RuneLite Cache-Code Autoupdater Date: Tue, 10 Feb 2026 12:19:20 -0700 Subject: [PATCH 10/17] Update Script arguments to 2026-2-11 --- runelite-api/src/main/java/net/runelite/api/ScriptID.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-api/src/main/java/net/runelite/api/ScriptID.java b/runelite-api/src/main/java/net/runelite/api/ScriptID.java index 82758bcea62..b4a567bef23 100644 --- a/runelite-api/src/main/java/net/runelite/api/ScriptID.java +++ b/runelite-api/src/main/java/net/runelite/api/ScriptID.java @@ -357,7 +357,7 @@ public final class ScriptID *
  • int (WidgetID) drag parent
  • * */ - @ScriptArguments(integer = 11, string = 1) + @ScriptArguments(integer = 12, string = 1) public static final int SETTINGS_SLIDER_CHOOSE_ONOP = 3885; /** From ff70a860d1850708c21d2d1ce033cee900bdc456 Mon Sep 17 00:00:00 2001 From: RuneLite Cache-Code Autoupdater Date: Tue, 10 Feb 2026 12:19:20 -0700 Subject: [PATCH 11/17] Update Legacy ID classes to 2026-2-11 --- .../src/main/java/net/runelite/api/NpcID.java | 1 + .../java/net/runelite/api/NullObjectID.java | 11 +++++++--- .../main/java/net/runelite/api/ObjectID.java | 21 ++++++++++++++----- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/runelite-api/src/main/java/net/runelite/api/NpcID.java b/runelite-api/src/main/java/net/runelite/api/NpcID.java index a9d7037b598..b78c303d890 100644 --- a/runelite-api/src/main/java/net/runelite/api/NpcID.java +++ b/runelite-api/src/main/java/net/runelite/api/NpcID.java @@ -13015,5 +13015,6 @@ public final class NpcID public static final int KETZEK_15572 = 15572; public static final int KETZEK_15573 = 15573; public static final int TZTOKJAD_15574 = 15574; + public static final int TIGER_SHARK_15575 = 15575; /* This file is automatically generated. Do not edit. */ } diff --git a/runelite-api/src/main/java/net/runelite/api/NullObjectID.java b/runelite-api/src/main/java/net/runelite/api/NullObjectID.java index 327141d4bfd..45c88541273 100644 --- a/runelite-api/src/main/java/net/runelite/api/NullObjectID.java +++ b/runelite-api/src/main/java/net/runelite/api/NullObjectID.java @@ -20915,7 +20915,6 @@ public final class NullObjectID public static final int NULL_42640 = 42640; public static final int NULL_42647 = 42647; public static final int NULL_42648 = 42648; - public static final int NULL_42650 = 42650; public static final int NULL_42651 = 42651; public static final int NULL_42652 = 42652; public static final int NULL_42653 = 42653; @@ -30246,8 +30245,6 @@ public final class NullObjectID public static final int NULL_58496 = 58496; public static final int NULL_58497 = 58497; public static final int NULL_58498 = 58498; - public static final int NULL_58504 = 58504; - public static final int NULL_58505 = 58505; public static final int NULL_58506 = 58506; public static final int NULL_58507 = 58507; public static final int NULL_58508 = 58508; @@ -31329,8 +31326,16 @@ public final class NullObjectID public static final int NULL_60617 = 60617; public static final int NULL_60618 = 60618; public static final int NULL_60643 = 60643; + public static final int NULL_60644 = 60644; public static final int NULL_60646 = 60646; public static final int NULL_60661 = 60661; public static final int NULL_60662 = 60662; + public static final int NULL_60674 = 60674; + public static final int NULL_60675 = 60675; + public static final int NULL_60676 = 60676; + public static final int NULL_60677 = 60677; + public static final int NULL_60678 = 60678; + public static final int NULL_60679 = 60679; + public static final int NULL_60680 = 60680; /* This file is automatically generated. Do not edit. */ } diff --git a/runelite-api/src/main/java/net/runelite/api/ObjectID.java b/runelite-api/src/main/java/net/runelite/api/ObjectID.java index f26d96b5662..59c3c76876e 100644 --- a/runelite-api/src/main/java/net/runelite/api/ObjectID.java +++ b/runelite-api/src/main/java/net/runelite/api/ObjectID.java @@ -27414,10 +27414,10 @@ public final class ObjectID public static final int STRANGE_TILE_56670 = 56670; public static final int TELEPORT_SPELL = 56671; public static final int TELEPORT_SPELL_56672 = 56672; - public static final int SHRINE_56674 = 56674; + public static final int STATUE_56674 = 56674; public static final int STATUE_56675 = 56675; - public static final int SHRINE_56677 = 56677; - public static final int SHRINE_56678 = 56678; + public static final int STATUE_56677 = 56677; + public static final int STATUE_56678 = 56678; public static final int SUN_STATUE = 56680; public static final int SUN_STATUE_56681 = 56681; public static final int URN_56683 = 56683; @@ -28249,8 +28249,6 @@ public final class ObjectID public static final int CORAL_DREDGER = 58499; public static final int CORAL_DREDGER_58500 = 58500; public static final int CORAL_DREDGER_58501 = 58501; - public static final int CORAL_REFINER = 58502; - public static final int ANCHOR_58503 = 58503; public static final int CHAIR_58519 = 58519; public static final int CACTUS_58520 = 58520; public static final int BUBBLES_58525 = 58525; @@ -29308,6 +29306,7 @@ public final class ObjectID public static final int IRONWOOD_CARGO_HOLD_60640 = 60640; public static final int ROSEWOOD_CARGO_HOLD_60641 = 60641; public static final int ROSEWOOD_CARGO_HOLD_60642 = 60642; + public static final int DIVING_BELL = 60645; public static final int STAINEDGLASS_WINDOW_60647 = 60647; public static final int STAINEDGLASS_WINDOW_60648 = 60648; public static final int SHUTTERED_WINDOW_60649 = 60649; @@ -29322,5 +29321,17 @@ public final class ObjectID public static final int DECORATIVE_WINDOW_60658 = 60658; public static final int STAINEDGLASS_WINDOW_60659 = 60659; public static final int WINDOW_SPACE_60660 = 60660; + public static final int CRANE_60663 = 60663; + public static final int CORAL_60664 = 60664; + public static final int CORAL_60665 = 60665; + public static final int CORAL_60666 = 60666; + public static final int CORAL_60667 = 60667; + public static final int CORAL_60668 = 60668; + public static final int CORAL_60669 = 60669; + public static final int CORAL_60670 = 60670; + public static final int CORAL_60671 = 60671; + public static final int CORAL_60672 = 60672; + public static final int CORAL_60673 = 60673; + public static final int FOUNTAIN_60681 = 60681; /* This file is automatically generated. Do not edit. */ } From 655ff632ae6b24fc066d2e5ff1331d03d724c564 Mon Sep 17 00:00:00 2001 From: RuneLite Cache-Code Autoupdater Date: Tue, 10 Feb 2026 12:19:32 -0700 Subject: [PATCH 12/17] Update GameVals to 2026-2-11 --- .../net/runelite/api/gameval/DBTableID.java | 23 +- .../net/runelite/api/gameval/InterfaceID.java | 234 ++++++------- .../java/net/runelite/api/gameval/NpcID.java | 5 + .../net/runelite/api/gameval/ObjectID1.java | 98 ++++-- .../net/runelite/api/gameval/SpriteID.java | 9 + .../net/runelite/api/gameval/VarPlayerID.java | 155 +++++++++ .../net/runelite/api/gameval/VarbitID.java | 307 ++++++++++++++++++ 7 files changed, 686 insertions(+), 145 deletions(-) diff --git a/runelite-api/src/main/java/net/runelite/api/gameval/DBTableID.java b/runelite-api/src/main/java/net/runelite/api/gameval/DBTableID.java index 376141b2449..cda734912bc 100644 --- a/runelite-api/src/main/java/net/runelite/api/gameval/DBTableID.java +++ b/runelite-api/src/main/java/net/runelite/api/gameval/DBTableID.java @@ -415,13 +415,13 @@ public static final class Row public static final int QUEST_EXISTENTIALCRISIS = 5192; public static final int QUEST_IMPENDINGCHAOS = 5193; public static final int MINIQUEST_VALETOTEMS = 5194; - public static final int MINIQUEST_TUTORIALISLAND = 7033; public static final int QUEST_PANDEMONIUM = 7103; public static final int QUEST_PRYINGTIMES = 7104; public static final int QUEST_CURRENTAFFAIRS = 7105; public static final int QUEST_TROUBLEDTORTUGANS = 7106; public static final int QUEST_REDREEF = 7107; public static final int QUEST_BURIALATSEA = 7108; + public static final int QUEST_LEARNINGTHEROPES = 9643; } } @@ -4957,40 +4957,45 @@ public static final class Music */ public static final int COL_VARIABLE = 5; + /** + * boolean + */ + public static final int COL_AUTOMATIC_UNLOCK = 6; + /** * integer */ - public static final int COL_AREA = 6; + public static final int COL_AREA = 7; /** * integer */ - public static final int COL_AREA_DEFAULT = 7; + public static final int COL_AREA_DEFAULT = 8; /** * boolean */ - public static final int COL_HIDDEN = 8; + public static final int COL_HIDDEN = 9; /** * integer */ - public static final int COL_HOLIDAY = 9; + public static final int COL_HOLIDAY = 10; /** * dbrow */ - public static final int COL_SECONDARY_TRACK = 10; + public static final int COL_SECONDARY_TRACK = 11; /** * integer */ - public static final int COL_RELEASE_TYPE = 11; + public static final int COL_RELEASE_TYPE = 12; /** * integer */ - public static final int COL_RELATED_CONTENT = 12; + public static final int COL_RELATED_CONTENT = 13; public static final class Row { @@ -14872,8 +14877,6 @@ public static final class Row public static final int SAILING_NPC_BOAT_BT_TRIAL_MASTER_3_BOAT = 8658; public static final int SAILING_NPC_BOAT_TROUBLED_TORTUGANS_RED_REEF = 8659; public static final int SAILING_NPC_BOAT_RED_REEF_ZENITH = 8660; - public static final int SAILING_NPC_BOAT_DYNAMIC_1 = 8661; - public static final int SAILING_NPC_BOAT_DYNAMIC_2 = 8662; } } diff --git a/runelite-api/src/main/java/net/runelite/api/gameval/InterfaceID.java b/runelite-api/src/main/java/net/runelite/api/gameval/InterfaceID.java index d7dd56f4ed4..a651c98ca6d 100644 --- a/runelite-api/src/main/java/net/runelite/api/gameval/InterfaceID.java +++ b/runelite-api/src/main/java/net/runelite/api/gameval/InterfaceID.java @@ -4826,104 +4826,103 @@ public static final class SettingsSide public static final int DISPLAY_DYNAMIC_SETTING_1_BUTTONS = 0x0074_0028; public static final int DISPLAY_DYNAMIC_SETTING_2_BUTTONS = 0x0074_0029; public static final int DROPDOWN_SCROLLBAR = 0x0074_002a; - public static final int TOOLTIP = 0x0074_002b; - public static final int ZOOM_TOGGLE = 0x0074_002c; - public static final int MOUSE_ZOOM = 0x0074_002d; - public static final int MOUSE_ZOOM_DISABLE = 0x0074_002e; - public static final int ZOOM_CONTAINER = 0x0074_002f; - public static final int ZOOM1 = 0x0074_0030; - public static final int ZOOM2 = 0x0074_0031; - public static final int ZOOM3 = 0x0074_0032; - public static final int ZOOM4 = 0x0074_0033; - public static final int ZOOM5 = 0x0074_0034; - public static final int ZOOM6 = 0x0074_0035; - public static final int ZOOM7 = 0x0074_0036; - public static final int ZOOM8 = 0x0074_0037; - public static final int ZOOM9 = 0x0074_0038; - public static final int ZOOM_SLIDER = 0x0074_0039; - public static final int ZOOM_SLIDER_BOBBLE = 0x0074_003a; - public static final int SETTINGS_TAB = 0x0074_003b; - public static final int TAB_1_1_BACKING = 0x0074_003c; - public static final int TAB_1_1 = 0x0074_003d; - public static final int TAB_1_2_BACKING = 0x0074_003e; - public static final int TAB_1_2 = 0x0074_003f; - public static final int TAB_1_3_BACKING = 0x0074_0040; - public static final int TAB_1_3 = 0x0074_0041; - public static final int TAB_ICON_1 = 0x0074_0042; - public static final int AUDIO_TAB = 0x0074_0043; - public static final int DISPLAY_TAB = 0x0074_0044; - public static final int TAB_LINE = 0x0074_0045; - public static final int TAB_2_1_BACKING = 0x0074_0046; - public static final int TAB_2_1 = 0x0074_0047; - public static final int TAB_2_2_BACKING = 0x0074_0048; - public static final int TAB_2_2 = 0x0074_0049; - public static final int TAB_2_3_BACKING = 0x0074_004a; - public static final int TAB_2_3 = 0x0074_004b; - public static final int TAB_ICON_2 = 0x0074_004c; - public static final int TAB_3_1_BACKING = 0x0074_004d; - public static final int TAB_3_1 = 0x0074_004e; - public static final int TAB_3_2_BACKING = 0x0074_004f; - public static final int TAB_3_2 = 0x0074_0050; - public static final int TAB_3_3_BACKING = 0x0074_0051; - public static final int TAB_3_3 = 0x0074_0052; - public static final int TAB_ICON_3 = 0x0074_0053; - public static final int MASTER_HOLDER = 0x0074_0054; - public static final int MASTER_ICON = 0x0074_0055; - public static final int MASTER_ZOOM_CONTAINER = 0x0074_0056; - public static final int ZOOM37 = 0x0074_0057; - public static final int ZOOM47 = 0x0074_0058; - public static final int ZOOM48 = 0x0074_0059; - public static final int ZOOM49 = 0x0074_005a; - public static final int ZOOM50 = 0x0074_005b; - public static final int ZOOM51 = 0x0074_005c; - public static final int ZOOM52 = 0x0074_005d; - public static final int ZOOM53 = 0x0074_005e; - public static final int ZOOM54 = 0x0074_005f; - public static final int MASTER_BOBBLE_CONTAINER = 0x0074_0060; - public static final int MASTER_SLIDER_BOBBLE = 0x0074_0061; - public static final int MUSIC_HOLDER = 0x0074_0062; - public static final int MUSIC_ICON = 0x0074_0063; - public static final int MUSIC_ZOOM_CONTAINER = 0x0074_0064; - public static final int ZOOM10 = 0x0074_0065; - public static final int ZOOM11 = 0x0074_0066; - public static final int ZOOM12 = 0x0074_0067; - public static final int ZOOM13 = 0x0074_0068; - public static final int ZOOM14 = 0x0074_0069; - public static final int ZOOM15 = 0x0074_006a; - public static final int ZOOM16 = 0x0074_006b; - public static final int ZOOM17 = 0x0074_006c; - public static final int ZOOM18 = 0x0074_006d; - public static final int MUSIC_BOBBLE_CONTAINER = 0x0074_006e; - public static final int MUSIC_SLIDER_BOBBLE = 0x0074_006f; - public static final int SOUND_HOLDER = 0x0074_0070; - public static final int SOUND_ICON = 0x0074_0071; - public static final int SOUND_ZOOM_CONTAINER = 0x0074_0072; - public static final int ZOOM19 = 0x0074_0073; - public static final int ZOOM20 = 0x0074_0074; - public static final int ZOOM21 = 0x0074_0075; - public static final int ZOOM22 = 0x0074_0076; - public static final int ZOOM23 = 0x0074_0077; - public static final int ZOOM24 = 0x0074_0078; - public static final int ZOOM25 = 0x0074_0079; - public static final int ZOOM26 = 0x0074_007a; - public static final int ZOOM27 = 0x0074_007b; - public static final int SOUND_BOBBLE_CONTAINER = 0x0074_007c; - public static final int SOUND_SLIDER_BOBBLE = 0x0074_007d; - public static final int AREASOUNDS_HOLDER = 0x0074_007e; - public static final int MUSIC_TOGGLE = 0x0074_007f; - public static final int AREASOUND_ICON = 0x0074_0080; - public static final int AREASOUNDS_ZOOM_CONTAINER = 0x0074_0081; - public static final int ZOOM28 = 0x0074_0082; - public static final int ZOOM29 = 0x0074_0083; - public static final int ZOOM30 = 0x0074_0084; - public static final int ZOOM31 = 0x0074_0085; - public static final int ZOOM32 = 0x0074_0086; - public static final int ZOOM33 = 0x0074_0087; - public static final int ZOOM34 = 0x0074_0088; - public static final int ZOOM35 = 0x0074_0089; - public static final int ZOOM36 = 0x0074_008a; - public static final int AREASOUNDS_BOBBLE_CONTAINER = 0x0074_008b; - public static final int AREASOUNDS_SLIDER_BOBBLE = 0x0074_008c; + public static final int ZOOM_TOGGLE = 0x0074_002b; + public static final int MOUSE_ZOOM = 0x0074_002c; + public static final int MOUSE_ZOOM_DISABLE = 0x0074_002d; + public static final int ZOOM_CONTAINER = 0x0074_002e; + public static final int ZOOM1 = 0x0074_002f; + public static final int ZOOM2 = 0x0074_0030; + public static final int ZOOM3 = 0x0074_0031; + public static final int ZOOM4 = 0x0074_0032; + public static final int ZOOM5 = 0x0074_0033; + public static final int ZOOM6 = 0x0074_0034; + public static final int ZOOM7 = 0x0074_0035; + public static final int ZOOM8 = 0x0074_0036; + public static final int ZOOM9 = 0x0074_0037; + public static final int ZOOM_SLIDER = 0x0074_0038; + public static final int ZOOM_SLIDER_BOBBLE = 0x0074_0039; + public static final int SETTINGS_TAB = 0x0074_003a; + public static final int TAB_1_1_BACKING = 0x0074_003b; + public static final int TAB_1_1 = 0x0074_003c; + public static final int TAB_1_2_BACKING = 0x0074_003d; + public static final int TAB_1_2 = 0x0074_003e; + public static final int TAB_1_3_BACKING = 0x0074_003f; + public static final int TAB_1_3 = 0x0074_0040; + public static final int TAB_ICON_1 = 0x0074_0041; + public static final int AUDIO_TAB = 0x0074_0042; + public static final int DISPLAY_TAB = 0x0074_0043; + public static final int TAB_LINE = 0x0074_0044; + public static final int TAB_2_1_BACKING = 0x0074_0045; + public static final int TAB_2_1 = 0x0074_0046; + public static final int TAB_2_2_BACKING = 0x0074_0047; + public static final int TAB_2_2 = 0x0074_0048; + public static final int TAB_2_3_BACKING = 0x0074_0049; + public static final int TAB_2_3 = 0x0074_004a; + public static final int TAB_ICON_2 = 0x0074_004b; + public static final int TAB_3_1_BACKING = 0x0074_004c; + public static final int TAB_3_1 = 0x0074_004d; + public static final int TAB_3_2_BACKING = 0x0074_004e; + public static final int TAB_3_2 = 0x0074_004f; + public static final int TAB_3_3_BACKING = 0x0074_0050; + public static final int TAB_3_3 = 0x0074_0051; + public static final int TAB_ICON_3 = 0x0074_0052; + public static final int MASTER_HOLDER = 0x0074_0053; + public static final int MASTER_ZOOM_CONTAINER = 0x0074_0054; + public static final int ZOOM37 = 0x0074_0055; + public static final int ZOOM47 = 0x0074_0056; + public static final int ZOOM48 = 0x0074_0057; + public static final int ZOOM49 = 0x0074_0058; + public static final int ZOOM50 = 0x0074_0059; + public static final int ZOOM51 = 0x0074_005a; + public static final int ZOOM52 = 0x0074_005b; + public static final int ZOOM53 = 0x0074_005c; + public static final int ZOOM54 = 0x0074_005d; + public static final int MASTER_BOBBLE_CONTAINER = 0x0074_005e; + public static final int MASTER_SLIDER_BOBBLE = 0x0074_005f; + public static final int MASTER_ICON = 0x0074_0060; + public static final int MUSIC_HOLDER = 0x0074_0061; + public static final int MUSIC_ZOOM_CONTAINER = 0x0074_0062; + public static final int ZOOM10 = 0x0074_0063; + public static final int ZOOM11 = 0x0074_0064; + public static final int ZOOM12 = 0x0074_0065; + public static final int ZOOM13 = 0x0074_0066; + public static final int ZOOM14 = 0x0074_0067; + public static final int ZOOM15 = 0x0074_0068; + public static final int ZOOM16 = 0x0074_0069; + public static final int ZOOM17 = 0x0074_006a; + public static final int ZOOM18 = 0x0074_006b; + public static final int MUSIC_BOBBLE_CONTAINER = 0x0074_006c; + public static final int MUSIC_SLIDER_BOBBLE = 0x0074_006d; + public static final int MUSIC_ICON = 0x0074_006e; + public static final int SOUND_HOLDER = 0x0074_006f; + public static final int SOUND_ZOOM_CONTAINER = 0x0074_0070; + public static final int ZOOM19 = 0x0074_0071; + public static final int ZOOM20 = 0x0074_0072; + public static final int ZOOM21 = 0x0074_0073; + public static final int ZOOM22 = 0x0074_0074; + public static final int ZOOM23 = 0x0074_0075; + public static final int ZOOM24 = 0x0074_0076; + public static final int ZOOM25 = 0x0074_0077; + public static final int ZOOM26 = 0x0074_0078; + public static final int ZOOM27 = 0x0074_0079; + public static final int SOUND_BOBBLE_CONTAINER = 0x0074_007a; + public static final int SOUND_SLIDER_BOBBLE = 0x0074_007b; + public static final int SOUND_ICON = 0x0074_007c; + public static final int AREASOUNDS_HOLDER = 0x0074_007d; + public static final int AREASOUNDS_ZOOM_CONTAINER = 0x0074_007e; + public static final int ZOOM28 = 0x0074_007f; + public static final int ZOOM29 = 0x0074_0080; + public static final int ZOOM30 = 0x0074_0081; + public static final int ZOOM31 = 0x0074_0082; + public static final int ZOOM32 = 0x0074_0083; + public static final int ZOOM33 = 0x0074_0084; + public static final int ZOOM34 = 0x0074_0085; + public static final int ZOOM35 = 0x0074_0086; + public static final int ZOOM36 = 0x0074_0087; + public static final int AREASOUNDS_BOBBLE_CONTAINER = 0x0074_0088; + public static final int AREASOUNDS_SLIDER_BOBBLE = 0x0074_0089; + public static final int AREASOUND_ICON = 0x0074_008a; + public static final int TOOLTIP = 0x0074_008b; } public static final class EnakhFilm @@ -9258,24 +9257,27 @@ public static final class Music { public static final int UNIVERSE = 0x00ef_0000; public static final int CONTENTS = 0x00ef_0001; - public static final int FRAME = 0x00ef_0002; - public static final int BACKGROUND = 0x00ef_0003; - public static final int SCROLLABLE = 0x00ef_0004; - public static final int OVERLAY = 0x00ef_0005; - public static final int JUKEBOX = 0x00ef_0006; - public static final int SCROLLBAR = 0x00ef_0007; - public static final int NOW_PLAYING_TITLE = 0x00ef_0008; - public static final int NOW_PLAYING_TEXT = 0x00ef_0009; - public static final int AREA = 0x00ef_000a; - public static final int AREA_BACKGROUND = 0x00ef_000b; - public static final int AREA_TITLE = 0x00ef_000c; - public static final int MANUAL = 0x00ef_000d; - public static final int MANUAL_BACKGROUND = 0x00ef_000e; - public static final int MANUAL_TITLE = 0x00ef_000f; - public static final int RANDOM = 0x00ef_0010; - public static final int COUNT = 0x00ef_0011; - public static final int RANDOM_BACKGROUND = 0x00ef_0012; - public static final int RANDOM_TITLE = 0x00ef_0013; + public static final int NOW_PLAYING = 0x00ef_0002; + public static final int NOW_PLAYING_TITLE = 0x00ef_0003; + public static final int NOW_PLAYING_TEXT = 0x00ef_0004; + public static final int COUNT = 0x00ef_0005; + public static final int FRAME = 0x00ef_0006; + public static final int BACKGROUND = 0x00ef_0007; + public static final int INNER = 0x00ef_0008; + public static final int SCROLLABLE = 0x00ef_0009; + public static final int OVERLAY = 0x00ef_000a; + public static final int JUKEBOX = 0x00ef_000b; + public static final int SCROLLBAR = 0x00ef_000c; + public static final int CONTROLS = 0x00ef_000d; + public static final int AREA = 0x00ef_000e; + public static final int SHUFFLE = 0x00ef_000f; + public static final int SINGLE = 0x00ef_0010; + public static final int SKIP = 0x00ef_0011; + public static final int PLAYLIST = 0x00ef_0012; + public static final int DROPDOWN_CONTAINER = 0x00ef_0013; + public static final int DROPDOWN = 0x00ef_0014; + public static final int DROPDOWN_CONTENT = 0x00ef_0015; + public static final int DROPDOWN_SCROLLBAR = 0x00ef_0016; } public static final class Xpreward diff --git a/runelite-api/src/main/java/net/runelite/api/gameval/NpcID.java b/runelite-api/src/main/java/net/runelite/api/gameval/NpcID.java index 9e1b1f5d4e2..e01a8af855b 100644 --- a/runelite-api/src/main/java/net/runelite/api/gameval/NpcID.java +++ b/runelite-api/src/main/java/net/runelite/api/gameval/NpcID.java @@ -67711,5 +67711,10 @@ public final class NpcID * TzTok-Jad */ public static final int TZHAAR_FIGHTPIT_SWARM_BOSS = 15574; + + /** + * Tiger shark + */ + public static final int SAILING_TIGER_SHARK_NOOP = 15575; /* This file is automatically generated. Do not edit. */ } diff --git a/runelite-api/src/main/java/net/runelite/api/gameval/ObjectID1.java b/runelite-api/src/main/java/net/runelite/api/gameval/ObjectID1.java index 9129a400bf7..46b3afcbf97 100644 --- a/runelite-api/src/main/java/net/runelite/api/gameval/ObjectID1.java +++ b/runelite-api/src/main/java/net/runelite/api/gameval/ObjectID1.java @@ -29742,7 +29742,6 @@ class ObjectID1 * Tree */ public static final int REGICIDE_TREE_DEAD1SWAMP_WEB = 42649; - public static final int QUEST_START_ICON_TUTORIAL = 42650; public static final int QUEST_START_ICON_ANIMALMAGNETISM = 42651; public static final int QUEST_START_ICON_ANOTHERSLICEOFHAM = 42652; public static final int QUEST_START_ICON_ASCENTOFARCEUUS = 42653; @@ -66512,7 +66511,7 @@ class ObjectID1 public static final int VMQ4_MOKI_ENTRANCE_STATUE_SUN = 56673; /** - * Shrine + * Statue */ public static final int VMQ4_MOKI_ENTRANCE_STATUE_SUN_INACTIVE = 56674; @@ -66523,12 +66522,12 @@ class ObjectID1 public static final int VMQ4_MOKI_ENTRANCE_STATUE_MOON = 56676; /** - * Shrine + * Statue */ public static final int VMQ4_MOKI_ENTRANCE_STATUE_MOON_INACTIVE = 56677; /** - * Shrine + * Statue */ public static final int VMQ4_MOKI_ENTRANCE_STATUE_MOON_ACTIVATED = 56678; public static final int VMQ4_SUN_PUZZLE_STATUE = 56679; @@ -71678,18 +71677,6 @@ class ObjectID1 * Coral dredger */ public static final int TRR_CORAL_DREDGER_FIXED = 58501; - - /** - * Coral refiner - */ - public static final int TRR_CORAL_REFINER = 58502; - - /** - * Anchor - */ - public static final int TRR_ANCHOR_BOTTOM = 58503; - public static final int TRR_ANCHOR_MIDDLE = 58504; - public static final int TRR_ANCHOR_TOP = 58505; public static final int TRR_PIER_SUPPORT_PILLAR01A = 58506; public static final int TRR_PIER_SUPPORT_STRAIGHT01A = 58507; public static final int TRR_PIER_SUPPORT_CORNER_OUTSIDE01A = 58508; @@ -77574,17 +77561,17 @@ class ObjectID1 public static final int CIVITAS_TABLE_RICH_1_SMALL1 = 60527; /** - * Red Coral + * Red coral */ public static final int RED_CORAL01_1X1 = 60528; /** - * Red Coral + * Red coral */ public static final int RED_CORAL01_2X2 = 60529; /** - * Red Coral + * Red coral */ public static final int RED_CORAL01_3X2 = 60530; public static final int BGSOUND_SAILING_STOMRY_SEAS_WATER_WIND_LOOP_01 = 60531; @@ -78056,6 +78043,12 @@ class ObjectID1 */ public static final int SAILING_BOAT_CARGO_HOLD_ROSEWOOD_LARGE_CARGO = 60642; public static final int DEADMAN_DUNGEON_CORRIDORFILLER = 60643; + public static final int QUEST_START_ICON_LEARNINGTHEROPES = 60644; + + /** + * Diving bell + */ + public static final int TRR_DIVING_BELL = 60645; public static final int BLACK_WALL02 = 60646; /** @@ -78129,5 +78122,72 @@ class ObjectID1 public static final int POH_CHAPELWINDOW_HOTSPOT_DEADMAN = 60660; public static final int DEADMAN_DUNGEON_INSIDEWALL_SIDER = 60661; public static final int DEADMAN_DUNGEON_INSIDEWALL_SIDEL = 60662; + + /** + * Crane + */ + public static final int TRR_DIVING_BELL_CRANE = 60663; + + /** + * Coral + */ + public static final int _100_CORAL_LACE_CORNER1_PURPLE = 60664; + + /** + * Coral + */ + public static final int _100_CORAL_LACE_CORNER2_PURPLE = 60665; + + /** + * Coral + */ + public static final int _100_CORAL_LACE_INVERSE_PURPLE = 60666; + + /** + * Coral + */ + public static final int _100_CORAL_LACE_ROCK1_PURPLE = 60667; + + /** + * Coral + */ + public static final int _100_CORAL_LACE_ROCK2_PURPLE = 60668; + + /** + * Coral + */ + public static final int _100_CORAL_LACE_SIDE1_PURPLE = 60669; + + /** + * Coral + */ + public static final int _100_CORAL_LACE_SIDE2_PURPLE = 60670; + + /** + * Coral + */ + public static final int _100_CORAL_LACE_TOP1_PURPLE = 60671; + + /** + * Coral + */ + public static final int _100_CORAL_LACE_TOP2_PURPLE = 60672; + + /** + * Coral + */ + public static final int _100_CORAL_LACE_TOP3_PURPLE = 60673; + public static final int TRR_ROCKS_BIG01 = 60674; + public static final int TRR_ROCKS_BIG02 = 60675; + public static final int OCEAN_OUTCROP_UNDERWATER01 = 60676; + public static final int OCEAN_OUTCROP_UNDERWATER02 = 60677; + public static final int OCEAN_OUTCROP_UNDERWATER03 = 60678; + public static final int OCEAN_OUTCROP_UNDERWATER04 = 60679; + public static final int CORAL_SEABED_LOW_WALL = 60680; + + /** + * Fountain + */ + public static final int FOUNTAIN_2X3 = 60681; /* This file is automatically generated. Do not edit. */ } diff --git a/runelite-api/src/main/java/net/runelite/api/gameval/SpriteID.java b/runelite-api/src/main/java/net/runelite/api/gameval/SpriteID.java index d6085b9ae04..2fc87d97c55 100644 --- a/runelite-api/src/main/java/net/runelite/api/gameval/SpriteID.java +++ b/runelite-api/src/main/java/net/runelite/api/gameval/SpriteID.java @@ -784,6 +784,7 @@ public final class SpriteID public static final int MINIMAP_BOAT_SLOOP = 7290; public static final int MINIMAP_BOAT_COLOSSAL = 7291; public static final int MINIMAP_BOAT_CLASSIC_LARGE = 7292; + public static final int STOP_OUTLINED = 7426; public static final class _2XStandardSpellsOn { @@ -11027,4 +11028,12 @@ public static final class BankStorage public static final int _6 = 7424; public static final int _7 = 7425; } + + public static final class MusicIcons + { + public static final int _0 = 7427; + public static final int _1 = 7428; + public static final int _2 = 7429; + public static final int _3 = 7430; + } } diff --git a/runelite-api/src/main/java/net/runelite/api/gameval/VarPlayerID.java b/runelite-api/src/main/java/net/runelite/api/gameval/VarPlayerID.java index 3c8a0cbde6e..f3f0c237194 100644 --- a/runelite-api/src/main/java/net/runelite/api/gameval/VarPlayerID.java +++ b/runelite-api/src/main/java/net/runelite/api/gameval/VarPlayerID.java @@ -1678,6 +1678,7 @@ public final class VarPlayerID public static final int OMNISHOP_FILTER = 3872; public static final int OMNISHOP_LASTSHOP = 3874; public static final int PRIDE23_GENERAL = 3882; + public static final int MUSIC_CURRENT_TRACK = 3883; public static final int HFS_PRIMARY = 3894; public static final int FORESTRY_TEMP_1 = 3897; public static final int GRAVESTONE_CREATION_DEATH_COORD = 3916; @@ -2595,5 +2596,159 @@ public final class VarPlayerID public static final int DEADMAN_SKULL_GENERAL = 5227; public static final int SIGIL_STATE_1 = 5228; public static final int SIGIL_TOGGLE_1 = 5229; + public static final int MUSIC_PLAYER_COLOUR_LOCKED = 5235; + public static final int MUSIC_PLAYER_COLOUR_UNLOCKED = 5236; + public static final int MUSIC_PLAYER_COLOUR_UNAVAILABLE = 5237; + public static final int MUSICMULTI_27 = 5238; + public static final int MUSIC_PLAYLIST_1_1 = 5239; + public static final int MUSIC_PLAYLIST_1_2 = 5240; + public static final int MUSIC_PLAYLIST_1_3 = 5241; + public static final int MUSIC_PLAYLIST_1_4 = 5242; + public static final int MUSIC_PLAYLIST_1_5 = 5243; + public static final int MUSIC_PLAYLIST_1_6 = 5244; + public static final int MUSIC_PLAYLIST_1_7 = 5245; + public static final int MUSIC_PLAYLIST_1_8 = 5246; + public static final int MUSIC_PLAYLIST_1_9 = 5247; + public static final int MUSIC_PLAYLIST_1_10 = 5248; + public static final int MUSIC_PLAYLIST_1_11 = 5249; + public static final int MUSIC_PLAYLIST_1_12 = 5250; + public static final int MUSIC_PLAYLIST_1_13 = 5251; + public static final int MUSIC_PLAYLIST_1_14 = 5252; + public static final int MUSIC_PLAYLIST_1_15 = 5253; + public static final int MUSIC_PLAYLIST_1_16 = 5254; + public static final int MUSIC_PLAYLIST_1_17 = 5255; + public static final int MUSIC_PLAYLIST_1_18 = 5256; + public static final int MUSIC_PLAYLIST_1_19 = 5257; + public static final int MUSIC_PLAYLIST_1_20 = 5258; + public static final int MUSIC_PLAYLIST_1_21 = 5259; + public static final int MUSIC_PLAYLIST_1_22 = 5260; + public static final int MUSIC_PLAYLIST_1_23 = 5261; + public static final int MUSIC_PLAYLIST_1_24 = 5262; + public static final int MUSIC_PLAYLIST_1_25 = 5263; + public static final int MUSIC_PLAYLIST_1_26 = 5264; + public static final int MUSIC_PLAYLIST_1_27 = 5265; + public static final int MUSIC_PLAYLIST_1_28 = 5266; + public static final int MUSIC_PLAYLIST_1_29 = 5267; + public static final int MUSIC_PLAYLIST_1_30 = 5268; + public static final int MUSIC_PLAYLIST_1_31 = 5269; + public static final int MUSIC_PLAYLIST_1_32 = 5270; + public static final int MUSIC_PLAYLIST_1_33 = 5271; + public static final int MUSIC_PLAYLIST_1_34 = 5272; + public static final int MUSIC_PLAYLIST_1_35 = 5273; + public static final int MUSIC_PLAYLIST_1_36 = 5274; + public static final int MUSIC_PLAYLIST_1_37 = 5275; + public static final int MUSIC_PLAYLIST_1_38 = 5276; + public static final int MUSIC_PLAYLIST_1_39 = 5277; + public static final int MUSIC_PLAYLIST_1_40 = 5278; + public static final int MUSIC_PLAYLIST_1_41 = 5279; + public static final int MUSIC_PLAYLIST_1_42 = 5280; + public static final int MUSIC_PLAYLIST_1_43 = 5281; + public static final int MUSIC_PLAYLIST_1_44 = 5282; + public static final int MUSIC_PLAYLIST_1_45 = 5283; + public static final int MUSIC_PLAYLIST_1_46 = 5284; + public static final int MUSIC_PLAYLIST_1_47 = 5285; + public static final int MUSIC_PLAYLIST_1_48 = 5286; + public static final int MUSIC_PLAYLIST_1_49 = 5287; + public static final int MUSIC_PLAYLIST_1_50 = 5288; + public static final int MUSIC_PLAYLIST_2_1 = 5289; + public static final int MUSIC_PLAYLIST_2_2 = 5290; + public static final int MUSIC_PLAYLIST_2_3 = 5291; + public static final int MUSIC_PLAYLIST_2_4 = 5292; + public static final int MUSIC_PLAYLIST_2_5 = 5293; + public static final int MUSIC_PLAYLIST_2_6 = 5294; + public static final int MUSIC_PLAYLIST_2_7 = 5295; + public static final int MUSIC_PLAYLIST_2_8 = 5296; + public static final int MUSIC_PLAYLIST_2_9 = 5297; + public static final int MUSIC_PLAYLIST_2_10 = 5298; + public static final int MUSIC_PLAYLIST_2_11 = 5299; + public static final int MUSIC_PLAYLIST_2_12 = 5300; + public static final int MUSIC_PLAYLIST_2_13 = 5301; + public static final int MUSIC_PLAYLIST_2_14 = 5302; + public static final int MUSIC_PLAYLIST_2_15 = 5303; + public static final int MUSIC_PLAYLIST_2_16 = 5304; + public static final int MUSIC_PLAYLIST_2_17 = 5305; + public static final int MUSIC_PLAYLIST_2_18 = 5306; + public static final int MUSIC_PLAYLIST_2_19 = 5307; + public static final int MUSIC_PLAYLIST_2_20 = 5308; + public static final int MUSIC_PLAYLIST_2_21 = 5309; + public static final int MUSIC_PLAYLIST_2_22 = 5310; + public static final int MUSIC_PLAYLIST_2_23 = 5311; + public static final int MUSIC_PLAYLIST_2_24 = 5312; + public static final int MUSIC_PLAYLIST_2_25 = 5313; + public static final int MUSIC_PLAYLIST_2_26 = 5314; + public static final int MUSIC_PLAYLIST_2_27 = 5315; + public static final int MUSIC_PLAYLIST_2_28 = 5316; + public static final int MUSIC_PLAYLIST_2_29 = 5317; + public static final int MUSIC_PLAYLIST_2_30 = 5318; + public static final int MUSIC_PLAYLIST_2_31 = 5319; + public static final int MUSIC_PLAYLIST_2_32 = 5320; + public static final int MUSIC_PLAYLIST_2_33 = 5321; + public static final int MUSIC_PLAYLIST_2_34 = 5322; + public static final int MUSIC_PLAYLIST_2_35 = 5323; + public static final int MUSIC_PLAYLIST_2_36 = 5324; + public static final int MUSIC_PLAYLIST_2_37 = 5325; + public static final int MUSIC_PLAYLIST_2_38 = 5326; + public static final int MUSIC_PLAYLIST_2_39 = 5327; + public static final int MUSIC_PLAYLIST_2_40 = 5328; + public static final int MUSIC_PLAYLIST_2_41 = 5329; + public static final int MUSIC_PLAYLIST_2_42 = 5330; + public static final int MUSIC_PLAYLIST_2_43 = 5331; + public static final int MUSIC_PLAYLIST_2_44 = 5332; + public static final int MUSIC_PLAYLIST_2_45 = 5333; + public static final int MUSIC_PLAYLIST_2_46 = 5334; + public static final int MUSIC_PLAYLIST_2_47 = 5335; + public static final int MUSIC_PLAYLIST_2_48 = 5336; + public static final int MUSIC_PLAYLIST_2_49 = 5337; + public static final int MUSIC_PLAYLIST_2_50 = 5338; + public static final int MUSIC_PLAYLIST_3_1 = 5339; + public static final int MUSIC_PLAYLIST_3_2 = 5340; + public static final int MUSIC_PLAYLIST_3_3 = 5341; + public static final int MUSIC_PLAYLIST_3_4 = 5342; + public static final int MUSIC_PLAYLIST_3_5 = 5343; + public static final int MUSIC_PLAYLIST_3_6 = 5344; + public static final int MUSIC_PLAYLIST_3_7 = 5345; + public static final int MUSIC_PLAYLIST_3_8 = 5346; + public static final int MUSIC_PLAYLIST_3_9 = 5347; + public static final int MUSIC_PLAYLIST_3_10 = 5348; + public static final int MUSIC_PLAYLIST_3_11 = 5349; + public static final int MUSIC_PLAYLIST_3_12 = 5350; + public static final int MUSIC_PLAYLIST_3_13 = 5351; + public static final int MUSIC_PLAYLIST_3_14 = 5352; + public static final int MUSIC_PLAYLIST_3_15 = 5353; + public static final int MUSIC_PLAYLIST_3_16 = 5354; + public static final int MUSIC_PLAYLIST_3_17 = 5355; + public static final int MUSIC_PLAYLIST_3_18 = 5356; + public static final int MUSIC_PLAYLIST_3_19 = 5357; + public static final int MUSIC_PLAYLIST_3_20 = 5358; + public static final int MUSIC_PLAYLIST_3_21 = 5359; + public static final int MUSIC_PLAYLIST_3_22 = 5360; + public static final int MUSIC_PLAYLIST_3_23 = 5361; + public static final int MUSIC_PLAYLIST_3_24 = 5362; + public static final int MUSIC_PLAYLIST_3_25 = 5363; + public static final int MUSIC_PLAYLIST_3_26 = 5364; + public static final int MUSIC_PLAYLIST_3_27 = 5365; + public static final int MUSIC_PLAYLIST_3_28 = 5366; + public static final int MUSIC_PLAYLIST_3_29 = 5367; + public static final int MUSIC_PLAYLIST_3_30 = 5368; + public static final int MUSIC_PLAYLIST_3_31 = 5369; + public static final int MUSIC_PLAYLIST_3_32 = 5370; + public static final int MUSIC_PLAYLIST_3_33 = 5371; + public static final int MUSIC_PLAYLIST_3_34 = 5372; + public static final int MUSIC_PLAYLIST_3_35 = 5373; + public static final int MUSIC_PLAYLIST_3_36 = 5374; + public static final int MUSIC_PLAYLIST_3_37 = 5375; + public static final int MUSIC_PLAYLIST_3_38 = 5376; + public static final int MUSIC_PLAYLIST_3_39 = 5377; + public static final int MUSIC_PLAYLIST_3_40 = 5378; + public static final int MUSIC_PLAYLIST_3_41 = 5379; + public static final int MUSIC_PLAYLIST_3_42 = 5380; + public static final int MUSIC_PLAYLIST_3_43 = 5381; + public static final int MUSIC_PLAYLIST_3_44 = 5382; + public static final int MUSIC_PLAYLIST_3_45 = 5383; + public static final int MUSIC_PLAYLIST_3_46 = 5384; + public static final int MUSIC_PLAYLIST_3_47 = 5385; + public static final int MUSIC_PLAYLIST_3_48 = 5386; + public static final int MUSIC_PLAYLIST_3_49 = 5387; + public static final int MUSIC_PLAYLIST_3_50 = 5388; /* This file is automatically generated. Do not edit. */ } diff --git a/runelite-api/src/main/java/net/runelite/api/gameval/VarbitID.java b/runelite-api/src/main/java/net/runelite/api/gameval/VarbitID.java index 1d71ae1cada..d2633b6b3a4 100644 --- a/runelite-api/src/main/java/net/runelite/api/gameval/VarbitID.java +++ b/runelite-api/src/main/java/net/runelite/api/gameval/VarbitID.java @@ -13941,5 +13941,312 @@ public final class VarbitID public static final int BANK_POPUPTAB_OPEN = 19722; public static final int BANK_SETTING_FORGET_POPUP = 19723; public static final int DEADMAN_2026_GE_WIPE = 19724; + public static final int MUSIC_CURRENT_PLAYLIST = 19731; + public static final int SETTINGS_MUSIC_PLAYER_DISABLE_TEXT_SHADOW = 19732; + public static final int SETTINGS_MUSIC_PLAYER_HIDE_TRACKS = 19733; + public static final int USE_PREVIOUS_MUSIC_MODE_ON_LOGIN = 19734; + public static final int SETTINGS_MUSIC_DEFAULT_TRACK_ON_AREA_ENTRY = 19735; + public static final int DONT_UPDATE_MUSIC_ON_PLAYLIST_CHANGE = 19736; + public static final int USE_SHUFFLE_MODE_ON_MANUAL_MUSIC_SELECTION = 19737; + public static final int MUSIC_PLAYLIST_1_TRACK_1 = 19738; + public static final int MUSIC_PLAYLIST_1_TRACK_2 = 19739; + public static final int MUSIC_PLAYLIST_1_TRACK_3 = 19740; + public static final int MUSIC_PLAYLIST_1_TRACK_4 = 19741; + public static final int MUSIC_PLAYLIST_1_TRACK_5 = 19742; + public static final int MUSIC_PLAYLIST_1_TRACK_6 = 19743; + public static final int MUSIC_PLAYLIST_1_TRACK_7 = 19744; + public static final int MUSIC_PLAYLIST_1_TRACK_8 = 19745; + public static final int MUSIC_PLAYLIST_1_TRACK_9 = 19746; + public static final int MUSIC_PLAYLIST_1_TRACK_10 = 19747; + public static final int MUSIC_PLAYLIST_1_TRACK_11 = 19748; + public static final int MUSIC_PLAYLIST_1_TRACK_12 = 19749; + public static final int MUSIC_PLAYLIST_1_TRACK_13 = 19750; + public static final int MUSIC_PLAYLIST_1_TRACK_14 = 19751; + public static final int MUSIC_PLAYLIST_1_TRACK_15 = 19752; + public static final int MUSIC_PLAYLIST_1_TRACK_16 = 19753; + public static final int MUSIC_PLAYLIST_1_TRACK_17 = 19754; + public static final int MUSIC_PLAYLIST_1_TRACK_18 = 19755; + public static final int MUSIC_PLAYLIST_1_TRACK_19 = 19756; + public static final int MUSIC_PLAYLIST_1_TRACK_20 = 19757; + public static final int MUSIC_PLAYLIST_1_TRACK_21 = 19758; + public static final int MUSIC_PLAYLIST_1_TRACK_22 = 19759; + public static final int MUSIC_PLAYLIST_1_TRACK_23 = 19760; + public static final int MUSIC_PLAYLIST_1_TRACK_24 = 19761; + public static final int MUSIC_PLAYLIST_1_TRACK_25 = 19762; + public static final int MUSIC_PLAYLIST_1_TRACK_26 = 19763; + public static final int MUSIC_PLAYLIST_1_TRACK_27 = 19764; + public static final int MUSIC_PLAYLIST_1_TRACK_28 = 19765; + public static final int MUSIC_PLAYLIST_1_TRACK_29 = 19766; + public static final int MUSIC_PLAYLIST_1_TRACK_30 = 19767; + public static final int MUSIC_PLAYLIST_1_TRACK_31 = 19768; + public static final int MUSIC_PLAYLIST_1_TRACK_32 = 19769; + public static final int MUSIC_PLAYLIST_1_TRACK_33 = 19770; + public static final int MUSIC_PLAYLIST_1_TRACK_34 = 19771; + public static final int MUSIC_PLAYLIST_1_TRACK_35 = 19772; + public static final int MUSIC_PLAYLIST_1_TRACK_36 = 19773; + public static final int MUSIC_PLAYLIST_1_TRACK_37 = 19774; + public static final int MUSIC_PLAYLIST_1_TRACK_38 = 19775; + public static final int MUSIC_PLAYLIST_1_TRACK_39 = 19776; + public static final int MUSIC_PLAYLIST_1_TRACK_40 = 19777; + public static final int MUSIC_PLAYLIST_1_TRACK_41 = 19778; + public static final int MUSIC_PLAYLIST_1_TRACK_42 = 19779; + public static final int MUSIC_PLAYLIST_1_TRACK_43 = 19780; + public static final int MUSIC_PLAYLIST_1_TRACK_44 = 19781; + public static final int MUSIC_PLAYLIST_1_TRACK_45 = 19782; + public static final int MUSIC_PLAYLIST_1_TRACK_46 = 19783; + public static final int MUSIC_PLAYLIST_1_TRACK_47 = 19784; + public static final int MUSIC_PLAYLIST_1_TRACK_48 = 19785; + public static final int MUSIC_PLAYLIST_1_TRACK_49 = 19786; + public static final int MUSIC_PLAYLIST_1_TRACK_50 = 19787; + public static final int MUSIC_PLAYLIST_1_TRACK_51 = 19788; + public static final int MUSIC_PLAYLIST_1_TRACK_52 = 19789; + public static final int MUSIC_PLAYLIST_1_TRACK_53 = 19790; + public static final int MUSIC_PLAYLIST_1_TRACK_54 = 19791; + public static final int MUSIC_PLAYLIST_1_TRACK_55 = 19792; + public static final int MUSIC_PLAYLIST_1_TRACK_56 = 19793; + public static final int MUSIC_PLAYLIST_1_TRACK_57 = 19794; + public static final int MUSIC_PLAYLIST_1_TRACK_58 = 19795; + public static final int MUSIC_PLAYLIST_1_TRACK_59 = 19796; + public static final int MUSIC_PLAYLIST_1_TRACK_60 = 19797; + public static final int MUSIC_PLAYLIST_1_TRACK_61 = 19798; + public static final int MUSIC_PLAYLIST_1_TRACK_62 = 19799; + public static final int MUSIC_PLAYLIST_1_TRACK_63 = 19800; + public static final int MUSIC_PLAYLIST_1_TRACK_64 = 19801; + public static final int MUSIC_PLAYLIST_1_TRACK_65 = 19802; + public static final int MUSIC_PLAYLIST_1_TRACK_66 = 19803; + public static final int MUSIC_PLAYLIST_1_TRACK_67 = 19804; + public static final int MUSIC_PLAYLIST_1_TRACK_68 = 19805; + public static final int MUSIC_PLAYLIST_1_TRACK_69 = 19806; + public static final int MUSIC_PLAYLIST_1_TRACK_70 = 19807; + public static final int MUSIC_PLAYLIST_1_TRACK_71 = 19808; + public static final int MUSIC_PLAYLIST_1_TRACK_72 = 19809; + public static final int MUSIC_PLAYLIST_1_TRACK_73 = 19810; + public static final int MUSIC_PLAYLIST_1_TRACK_74 = 19811; + public static final int MUSIC_PLAYLIST_1_TRACK_75 = 19812; + public static final int MUSIC_PLAYLIST_1_TRACK_76 = 19813; + public static final int MUSIC_PLAYLIST_1_TRACK_77 = 19814; + public static final int MUSIC_PLAYLIST_1_TRACK_78 = 19815; + public static final int MUSIC_PLAYLIST_1_TRACK_79 = 19816; + public static final int MUSIC_PLAYLIST_1_TRACK_80 = 19817; + public static final int MUSIC_PLAYLIST_1_TRACK_81 = 19818; + public static final int MUSIC_PLAYLIST_1_TRACK_82 = 19819; + public static final int MUSIC_PLAYLIST_1_TRACK_83 = 19820; + public static final int MUSIC_PLAYLIST_1_TRACK_84 = 19821; + public static final int MUSIC_PLAYLIST_1_TRACK_85 = 19822; + public static final int MUSIC_PLAYLIST_1_TRACK_86 = 19823; + public static final int MUSIC_PLAYLIST_1_TRACK_87 = 19824; + public static final int MUSIC_PLAYLIST_1_TRACK_88 = 19825; + public static final int MUSIC_PLAYLIST_1_TRACK_89 = 19826; + public static final int MUSIC_PLAYLIST_1_TRACK_90 = 19827; + public static final int MUSIC_PLAYLIST_1_TRACK_91 = 19828; + public static final int MUSIC_PLAYLIST_1_TRACK_92 = 19829; + public static final int MUSIC_PLAYLIST_1_TRACK_93 = 19830; + public static final int MUSIC_PLAYLIST_1_TRACK_94 = 19831; + public static final int MUSIC_PLAYLIST_1_TRACK_95 = 19832; + public static final int MUSIC_PLAYLIST_1_TRACK_96 = 19833; + public static final int MUSIC_PLAYLIST_1_TRACK_97 = 19834; + public static final int MUSIC_PLAYLIST_1_TRACK_98 = 19835; + public static final int MUSIC_PLAYLIST_1_TRACK_99 = 19836; + public static final int MUSIC_PLAYLIST_1_TRACK_100 = 19837; + public static final int MUSIC_PLAYLIST_2_TRACK_1 = 19838; + public static final int MUSIC_PLAYLIST_2_TRACK_2 = 19839; + public static final int MUSIC_PLAYLIST_2_TRACK_3 = 19840; + public static final int MUSIC_PLAYLIST_2_TRACK_4 = 19841; + public static final int MUSIC_PLAYLIST_2_TRACK_5 = 19842; + public static final int MUSIC_PLAYLIST_2_TRACK_6 = 19843; + public static final int MUSIC_PLAYLIST_2_TRACK_7 = 19844; + public static final int MUSIC_PLAYLIST_2_TRACK_8 = 19845; + public static final int MUSIC_PLAYLIST_2_TRACK_9 = 19846; + public static final int MUSIC_PLAYLIST_2_TRACK_10 = 19847; + public static final int MUSIC_PLAYLIST_2_TRACK_11 = 19848; + public static final int MUSIC_PLAYLIST_2_TRACK_12 = 19849; + public static final int MUSIC_PLAYLIST_2_TRACK_13 = 19850; + public static final int MUSIC_PLAYLIST_2_TRACK_14 = 19851; + public static final int MUSIC_PLAYLIST_2_TRACK_15 = 19852; + public static final int MUSIC_PLAYLIST_2_TRACK_16 = 19853; + public static final int MUSIC_PLAYLIST_2_TRACK_17 = 19854; + public static final int MUSIC_PLAYLIST_2_TRACK_18 = 19855; + public static final int MUSIC_PLAYLIST_2_TRACK_19 = 19856; + public static final int MUSIC_PLAYLIST_2_TRACK_20 = 19857; + public static final int MUSIC_PLAYLIST_2_TRACK_21 = 19858; + public static final int MUSIC_PLAYLIST_2_TRACK_22 = 19859; + public static final int MUSIC_PLAYLIST_2_TRACK_23 = 19860; + public static final int MUSIC_PLAYLIST_2_TRACK_24 = 19861; + public static final int MUSIC_PLAYLIST_2_TRACK_25 = 19862; + public static final int MUSIC_PLAYLIST_2_TRACK_26 = 19863; + public static final int MUSIC_PLAYLIST_2_TRACK_27 = 19864; + public static final int MUSIC_PLAYLIST_2_TRACK_28 = 19865; + public static final int MUSIC_PLAYLIST_2_TRACK_29 = 19866; + public static final int MUSIC_PLAYLIST_2_TRACK_30 = 19867; + public static final int MUSIC_PLAYLIST_2_TRACK_31 = 19868; + public static final int MUSIC_PLAYLIST_2_TRACK_32 = 19869; + public static final int MUSIC_PLAYLIST_2_TRACK_33 = 19870; + public static final int MUSIC_PLAYLIST_2_TRACK_34 = 19871; + public static final int MUSIC_PLAYLIST_2_TRACK_35 = 19872; + public static final int MUSIC_PLAYLIST_2_TRACK_36 = 19873; + public static final int MUSIC_PLAYLIST_2_TRACK_37 = 19874; + public static final int MUSIC_PLAYLIST_2_TRACK_38 = 19875; + public static final int MUSIC_PLAYLIST_2_TRACK_39 = 19876; + public static final int MUSIC_PLAYLIST_2_TRACK_40 = 19877; + public static final int MUSIC_PLAYLIST_2_TRACK_41 = 19878; + public static final int MUSIC_PLAYLIST_2_TRACK_42 = 19879; + public static final int MUSIC_PLAYLIST_2_TRACK_43 = 19880; + public static final int MUSIC_PLAYLIST_2_TRACK_44 = 19881; + public static final int MUSIC_PLAYLIST_2_TRACK_45 = 19882; + public static final int MUSIC_PLAYLIST_2_TRACK_46 = 19883; + public static final int MUSIC_PLAYLIST_2_TRACK_47 = 19884; + public static final int MUSIC_PLAYLIST_2_TRACK_48 = 19885; + public static final int MUSIC_PLAYLIST_2_TRACK_49 = 19886; + public static final int MUSIC_PLAYLIST_2_TRACK_50 = 19887; + public static final int MUSIC_PLAYLIST_2_TRACK_51 = 19888; + public static final int MUSIC_PLAYLIST_2_TRACK_52 = 19889; + public static final int MUSIC_PLAYLIST_2_TRACK_53 = 19890; + public static final int MUSIC_PLAYLIST_2_TRACK_54 = 19891; + public static final int MUSIC_PLAYLIST_2_TRACK_55 = 19892; + public static final int MUSIC_PLAYLIST_2_TRACK_56 = 19893; + public static final int MUSIC_PLAYLIST_2_TRACK_57 = 19894; + public static final int MUSIC_PLAYLIST_2_TRACK_58 = 19895; + public static final int MUSIC_PLAYLIST_2_TRACK_59 = 19896; + public static final int MUSIC_PLAYLIST_2_TRACK_60 = 19897; + public static final int MUSIC_PLAYLIST_2_TRACK_61 = 19898; + public static final int MUSIC_PLAYLIST_2_TRACK_62 = 19899; + public static final int MUSIC_PLAYLIST_2_TRACK_63 = 19900; + public static final int MUSIC_PLAYLIST_2_TRACK_64 = 19901; + public static final int MUSIC_PLAYLIST_2_TRACK_65 = 19902; + public static final int MUSIC_PLAYLIST_2_TRACK_66 = 19903; + public static final int MUSIC_PLAYLIST_2_TRACK_67 = 19904; + public static final int MUSIC_PLAYLIST_2_TRACK_68 = 19905; + public static final int MUSIC_PLAYLIST_2_TRACK_69 = 19906; + public static final int MUSIC_PLAYLIST_2_TRACK_70 = 19907; + public static final int MUSIC_PLAYLIST_2_TRACK_71 = 19908; + public static final int MUSIC_PLAYLIST_2_TRACK_72 = 19909; + public static final int MUSIC_PLAYLIST_2_TRACK_73 = 19910; + public static final int MUSIC_PLAYLIST_2_TRACK_74 = 19911; + public static final int MUSIC_PLAYLIST_2_TRACK_75 = 19912; + public static final int MUSIC_PLAYLIST_2_TRACK_76 = 19913; + public static final int MUSIC_PLAYLIST_2_TRACK_77 = 19914; + public static final int MUSIC_PLAYLIST_2_TRACK_78 = 19915; + public static final int MUSIC_PLAYLIST_2_TRACK_79 = 19916; + public static final int MUSIC_PLAYLIST_2_TRACK_80 = 19917; + public static final int MUSIC_PLAYLIST_2_TRACK_81 = 19918; + public static final int MUSIC_PLAYLIST_2_TRACK_82 = 19919; + public static final int MUSIC_PLAYLIST_2_TRACK_83 = 19920; + public static final int MUSIC_PLAYLIST_2_TRACK_84 = 19921; + public static final int MUSIC_PLAYLIST_2_TRACK_85 = 19922; + public static final int MUSIC_PLAYLIST_2_TRACK_86 = 19923; + public static final int MUSIC_PLAYLIST_2_TRACK_87 = 19924; + public static final int MUSIC_PLAYLIST_2_TRACK_88 = 19925; + public static final int MUSIC_PLAYLIST_2_TRACK_89 = 19926; + public static final int MUSIC_PLAYLIST_2_TRACK_90 = 19927; + public static final int MUSIC_PLAYLIST_2_TRACK_91 = 19928; + public static final int MUSIC_PLAYLIST_2_TRACK_92 = 19929; + public static final int MUSIC_PLAYLIST_2_TRACK_93 = 19930; + public static final int MUSIC_PLAYLIST_2_TRACK_94 = 19931; + public static final int MUSIC_PLAYLIST_2_TRACK_95 = 19932; + public static final int MUSIC_PLAYLIST_2_TRACK_96 = 19933; + public static final int MUSIC_PLAYLIST_2_TRACK_97 = 19934; + public static final int MUSIC_PLAYLIST_2_TRACK_98 = 19935; + public static final int MUSIC_PLAYLIST_2_TRACK_99 = 19936; + public static final int MUSIC_PLAYLIST_2_TRACK_100 = 19937; + public static final int MUSIC_PLAYLIST_3_TRACK_1 = 19938; + public static final int MUSIC_PLAYLIST_3_TRACK_2 = 19939; + public static final int MUSIC_PLAYLIST_3_TRACK_3 = 19940; + public static final int MUSIC_PLAYLIST_3_TRACK_4 = 19941; + public static final int MUSIC_PLAYLIST_3_TRACK_5 = 19942; + public static final int MUSIC_PLAYLIST_3_TRACK_6 = 19943; + public static final int MUSIC_PLAYLIST_3_TRACK_7 = 19944; + public static final int MUSIC_PLAYLIST_3_TRACK_8 = 19945; + public static final int MUSIC_PLAYLIST_3_TRACK_9 = 19946; + public static final int MUSIC_PLAYLIST_3_TRACK_10 = 19947; + public static final int MUSIC_PLAYLIST_3_TRACK_11 = 19948; + public static final int MUSIC_PLAYLIST_3_TRACK_12 = 19949; + public static final int MUSIC_PLAYLIST_3_TRACK_13 = 19950; + public static final int MUSIC_PLAYLIST_3_TRACK_14 = 19951; + public static final int MUSIC_PLAYLIST_3_TRACK_15 = 19952; + public static final int MUSIC_PLAYLIST_3_TRACK_16 = 19953; + public static final int MUSIC_PLAYLIST_3_TRACK_17 = 19954; + public static final int MUSIC_PLAYLIST_3_TRACK_18 = 19955; + public static final int MUSIC_PLAYLIST_3_TRACK_19 = 19956; + public static final int MUSIC_PLAYLIST_3_TRACK_20 = 19957; + public static final int MUSIC_PLAYLIST_3_TRACK_21 = 19958; + public static final int MUSIC_PLAYLIST_3_TRACK_22 = 19959; + public static final int MUSIC_PLAYLIST_3_TRACK_23 = 19960; + public static final int MUSIC_PLAYLIST_3_TRACK_24 = 19961; + public static final int MUSIC_PLAYLIST_3_TRACK_25 = 19962; + public static final int MUSIC_PLAYLIST_3_TRACK_26 = 19963; + public static final int MUSIC_PLAYLIST_3_TRACK_27 = 19964; + public static final int MUSIC_PLAYLIST_3_TRACK_28 = 19965; + public static final int MUSIC_PLAYLIST_3_TRACK_29 = 19966; + public static final int MUSIC_PLAYLIST_3_TRACK_30 = 19967; + public static final int MUSIC_PLAYLIST_3_TRACK_31 = 19968; + public static final int MUSIC_PLAYLIST_3_TRACK_32 = 19969; + public static final int MUSIC_PLAYLIST_3_TRACK_33 = 19970; + public static final int MUSIC_PLAYLIST_3_TRACK_34 = 19971; + public static final int MUSIC_PLAYLIST_3_TRACK_35 = 19972; + public static final int MUSIC_PLAYLIST_3_TRACK_36 = 19973; + public static final int MUSIC_PLAYLIST_3_TRACK_37 = 19974; + public static final int MUSIC_PLAYLIST_3_TRACK_38 = 19975; + public static final int MUSIC_PLAYLIST_3_TRACK_39 = 19976; + public static final int MUSIC_PLAYLIST_3_TRACK_40 = 19977; + public static final int MUSIC_PLAYLIST_3_TRACK_41 = 19978; + public static final int MUSIC_PLAYLIST_3_TRACK_42 = 19979; + public static final int MUSIC_PLAYLIST_3_TRACK_43 = 19980; + public static final int MUSIC_PLAYLIST_3_TRACK_44 = 19981; + public static final int MUSIC_PLAYLIST_3_TRACK_45 = 19982; + public static final int MUSIC_PLAYLIST_3_TRACK_46 = 19983; + public static final int MUSIC_PLAYLIST_3_TRACK_47 = 19984; + public static final int MUSIC_PLAYLIST_3_TRACK_48 = 19985; + public static final int MUSIC_PLAYLIST_3_TRACK_49 = 19986; + public static final int MUSIC_PLAYLIST_3_TRACK_50 = 19987; + public static final int MUSIC_PLAYLIST_3_TRACK_51 = 19988; + public static final int MUSIC_PLAYLIST_3_TRACK_52 = 19989; + public static final int MUSIC_PLAYLIST_3_TRACK_53 = 19990; + public static final int MUSIC_PLAYLIST_3_TRACK_54 = 19991; + public static final int MUSIC_PLAYLIST_3_TRACK_55 = 19992; + public static final int MUSIC_PLAYLIST_3_TRACK_56 = 19993; + public static final int MUSIC_PLAYLIST_3_TRACK_57 = 19994; + public static final int MUSIC_PLAYLIST_3_TRACK_58 = 19995; + public static final int MUSIC_PLAYLIST_3_TRACK_59 = 19996; + public static final int MUSIC_PLAYLIST_3_TRACK_60 = 19997; + public static final int MUSIC_PLAYLIST_3_TRACK_61 = 19998; + public static final int MUSIC_PLAYLIST_3_TRACK_62 = 19999; + public static final int MUSIC_PLAYLIST_3_TRACK_63 = 20000; + public static final int MUSIC_PLAYLIST_3_TRACK_64 = 20001; + public static final int MUSIC_PLAYLIST_3_TRACK_65 = 20002; + public static final int MUSIC_PLAYLIST_3_TRACK_66 = 20003; + public static final int MUSIC_PLAYLIST_3_TRACK_67 = 20004; + public static final int MUSIC_PLAYLIST_3_TRACK_68 = 20005; + public static final int MUSIC_PLAYLIST_3_TRACK_69 = 20006; + public static final int MUSIC_PLAYLIST_3_TRACK_70 = 20007; + public static final int MUSIC_PLAYLIST_3_TRACK_71 = 20008; + public static final int MUSIC_PLAYLIST_3_TRACK_72 = 20009; + public static final int MUSIC_PLAYLIST_3_TRACK_73 = 20010; + public static final int MUSIC_PLAYLIST_3_TRACK_74 = 20011; + public static final int MUSIC_PLAYLIST_3_TRACK_75 = 20012; + public static final int MUSIC_PLAYLIST_3_TRACK_76 = 20013; + public static final int MUSIC_PLAYLIST_3_TRACK_77 = 20014; + public static final int MUSIC_PLAYLIST_3_TRACK_78 = 20015; + public static final int MUSIC_PLAYLIST_3_TRACK_79 = 20016; + public static final int MUSIC_PLAYLIST_3_TRACK_80 = 20017; + public static final int MUSIC_PLAYLIST_3_TRACK_81 = 20018; + public static final int MUSIC_PLAYLIST_3_TRACK_82 = 20019; + public static final int MUSIC_PLAYLIST_3_TRACK_83 = 20020; + public static final int MUSIC_PLAYLIST_3_TRACK_84 = 20021; + public static final int MUSIC_PLAYLIST_3_TRACK_85 = 20022; + public static final int MUSIC_PLAYLIST_3_TRACK_86 = 20023; + public static final int MUSIC_PLAYLIST_3_TRACK_87 = 20024; + public static final int MUSIC_PLAYLIST_3_TRACK_88 = 20025; + public static final int MUSIC_PLAYLIST_3_TRACK_89 = 20026; + public static final int MUSIC_PLAYLIST_3_TRACK_90 = 20027; + public static final int MUSIC_PLAYLIST_3_TRACK_91 = 20028; + public static final int MUSIC_PLAYLIST_3_TRACK_92 = 20029; + public static final int MUSIC_PLAYLIST_3_TRACK_93 = 20030; + public static final int MUSIC_PLAYLIST_3_TRACK_94 = 20031; + public static final int MUSIC_PLAYLIST_3_TRACK_95 = 20032; + public static final int MUSIC_PLAYLIST_3_TRACK_96 = 20033; + public static final int MUSIC_PLAYLIST_3_TRACK_97 = 20034; + public static final int MUSIC_PLAYLIST_3_TRACK_98 = 20035; + public static final int MUSIC_PLAYLIST_3_TRACK_99 = 20036; + public static final int MUSIC_PLAYLIST_3_TRACK_100 = 20037; /* This file is automatically generated. Do not edit. */ } From 478ac5f5bbf90f78170ab285181ac04d73237d0f Mon Sep 17 00:00:00 2001 From: Max Weber Date: Tue, 10 Feb 2026 14:07:25 -0700 Subject: [PATCH 13/17] music: update 2026-2-11 --- .../client/plugins/music/MusicConfig.java | 68 -- .../client/plugins/music/MusicPlugin.java | 791 +++--------------- .../src/main/scripts/MusicFilterTrack.hash | 1 + .../src/main/scripts/MusicFilterTrack.rs2asm | 81 ++ 4 files changed, 197 insertions(+), 744 deletions(-) create mode 100644 runelite-client/src/main/scripts/MusicFilterTrack.hash create mode 100644 runelite-client/src/main/scripts/MusicFilterTrack.rs2asm diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicConfig.java index 17c43b2fbd0..a803d3b29db 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicConfig.java @@ -100,72 +100,4 @@ default boolean mutePrayerSounds() { return false; } - - @ConfigItem( - keyName = GRANULAR_SLIDERS, - name = "Granular volume sliders", - description = "Make the volume sliders allow better control of volume.", - position = 6 - ) - default boolean granularSliders() - { - return true; - } - - @ConfigItem( - keyName = "musicVolume", - name = "", - description = "", - hidden = true - ) - default int getMusicVolume() - { - return 0; - } - - @ConfigItem( - keyName = "musicVolume", - name = "", - description = "", - hidden = true - ) - void setMusicVolume(int vol); - - @ConfigItem( - keyName = "soundEffectVolume", - name = "", - description = "", - hidden = true - ) - default int getSoundEffectVolume() - { - return 0; - } - - @ConfigItem( - keyName = "soundEffectVolume", - name = "", - description = "", - hidden = true - ) - void setSoundEffectVolume(int val); - - @ConfigItem( - keyName = "areaSoundEffectVolume", - name = "", - description = "", - hidden = true - ) - default int getAreaSoundEffectVolume() - { - return 0; - } - - @ConfigItem( - keyName = "areaSoundEffectVolume", - name = "", - description = "", - hidden = true - ) - void setAreaSoundEffectVolume(int vol); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicPlugin.java index d202d674cb0..5a26b63e369 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicPlugin.java @@ -27,56 +27,34 @@ package net.runelite.client.plugins.music; import com.google.common.collect.ImmutableSet; -import com.google.common.primitives.Ints; import com.google.inject.Provides; -import java.util.Arrays; -import java.util.Collection; -import java.util.Comparator; import java.util.Set; -import java.util.function.Consumer; -import java.util.function.IntConsumer; -import java.util.function.IntSupplier; -import java.util.stream.Collectors; +import javax.annotation.Nullable; import javax.inject.Inject; +import joptsimple.internal.Strings; import lombok.AllArgsConstructor; import lombok.Getter; -import lombok.RequiredArgsConstructor; -import lombok.Setter; import net.runelite.api.Actor; import net.runelite.api.Client; import net.runelite.api.GameState; import net.runelite.api.NPC; -import net.runelite.api.ParamID; import net.runelite.api.Player; -import net.runelite.api.Preferences; -import net.runelite.api.ScriptEvent; -import net.runelite.api.ScriptID; -import net.runelite.api.SettingID; import net.runelite.api.SoundEffectID; -import net.runelite.api.StructComposition; -import net.runelite.api.StructID; -import net.runelite.api.annotations.Component; -import net.runelite.api.annotations.Varbit; -import net.runelite.api.annotations.Varp; import net.runelite.api.events.AmbientSoundEffectCreated; import net.runelite.api.events.AreaSoundEffectPlayed; -import net.runelite.api.events.BeforeRender; -import net.runelite.api.events.ClientTick; import net.runelite.api.events.GameStateChanged; -import net.runelite.api.events.PostStructComposition; -import net.runelite.api.events.ScriptPreFired; +import net.runelite.api.events.ScriptCallbackEvent; import net.runelite.api.events.SoundEffectPlayed; import net.runelite.api.events.VarClientIntChanged; -import net.runelite.api.events.VolumeChanged; +import net.runelite.api.events.VarbitChanged; import net.runelite.api.events.WidgetLoaded; +import net.runelite.api.gameval.DBTableID; import net.runelite.api.gameval.InterfaceID; import net.runelite.api.gameval.SpriteID; import net.runelite.api.gameval.VarClientID; -import net.runelite.api.gameval.VarPlayerID; import net.runelite.api.gameval.VarbitID; import net.runelite.api.widgets.JavaScriptCallback; import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetConfig; import net.runelite.api.widgets.WidgetPositionMode; import net.runelite.api.widgets.WidgetType; import net.runelite.client.callback.ClientThread; @@ -87,8 +65,6 @@ import net.runelite.client.game.chatbox.ChatboxTextInput; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.ui.overlay.tooltip.Tooltip; -import net.runelite.client.ui.overlay.tooltip.TooltipManager; @PluginDescriptor( name = "Music", @@ -97,8 +73,6 @@ ) public class MusicPlugin extends Plugin { - private static final int SLIDER_HANDLE_SIZE = 16; - private static final Set SOURCELESS_PLAYER_SOUNDS = ImmutableSet.of( SoundEffectID.TELEPORT_VWOOP ); @@ -147,60 +121,24 @@ public class MusicPlugin extends Plugin @Inject private ChatboxPanelManager chatboxPanelManager; - @Inject - private TooltipManager tooltipManager; - - private Channel musicChannel; - private Channel effectChannel; - private Channel areaChannel; - private Channel[] channels; - private ChatboxTextInput searchInput; private Widget musicSearchButton; private Widget musicFilterButton; - private Collection tracks; - - private MusicState currentMusicFilter = MusicState.ALL; + private String search = ""; - private Tooltip sliderTooltip; - private boolean shuttingDown = false; + @Nullable + private MusicState currentMusicFilter = null; @Override protected void startUp() { clientThread.invoke(() -> { - this.shuttingDown = false; - - Preferences preferences = client.getPreferences(); - musicChannel = new Channel("Music", - VarPlayerID.OPTION_MUSIC, VarbitID.OPTION_MUSIC_SAVED, - musicConfig::getMusicVolume, musicConfig::setMusicVolume, - client::setMusicVolume, 255, - InterfaceID.SettingsSide.MUSIC_HOLDER); - effectChannel = new Channel("Sound Effects", - VarPlayerID.OPTION_SOUNDS, VarbitID.OPTION_SOUNDS_SAVED, - musicConfig::getSoundEffectVolume, musicConfig::setSoundEffectVolume, - preferences::setSoundEffectVolume, 127, - InterfaceID.SettingsSide.SOUND_HOLDER); - areaChannel = new Channel("Area Sounds", - VarPlayerID.OPTION_AREASOUNDS, VarbitID.OPTION_AREASOUNDS_SAVED, - musicConfig::getAreaSoundEffectVolume, musicConfig::setAreaSoundEffectVolume, - preferences::setAreaSoundEffectVolume, 127, - InterfaceID.SettingsSide.AREASOUNDS_HOLDER); - channels = new Channel[]{musicChannel, effectChannel, areaChannel}; - addMusicButtons(); if (client.getGameState() == GameState.LOGGED_IN) { - if (musicConfig.granularSliders()) - { - updateMusicOptions(); - resetSettingsWindow(); - } - if (musicConfig.muteAmbientSounds()) { // Reload the scene to remove ambient sounds @@ -213,18 +151,17 @@ protected void startUp() @Override protected void shutDown() { - Widget header = client.getWidget(InterfaceID.Music.UNIVERSE); + Widget header = client.getWidget(InterfaceID.Music.NOW_PLAYING); if (header != null) { header.deleteAllChildren(); } - tracks = null; + currentMusicFilter = null; + search = ""; + clientThread.invoke(() -> { - shuttingDown = true; - teardownMusicOptions(); - if (musicConfig.muteAmbientSounds()) { // Reload the scene to reapply ambient sounds @@ -249,8 +186,7 @@ public void onGameStateChanged(GameStateChanged gameStateChanged) if (gameState == GameState.LOGIN_SCREEN) { // Reset music filter on logout - currentMusicFilter = MusicState.ALL; - tracks = null; + currentMusicFilter = null; } else if (gameState == GameState.LOGGED_IN) { @@ -267,23 +203,16 @@ public void onWidgetLoaded(WidgetLoaded widgetLoaded) { if (widgetLoaded.getGroupId() == InterfaceID.MUSIC) { - tracks = null; // Reset filter state as the widget has been reloaded. // It is too early here to call updateFilter() - currentMusicFilter = MusicState.ALL; + currentMusicFilter = null; addMusicButtons(); } - - if ((widgetLoaded.getGroupId() == InterfaceID.SETTINGS || widgetLoaded.getGroupId() == InterfaceID.SETTINGS_SIDE) - && musicConfig.granularSliders()) - { - updateMusicOptions(); - } } private void addMusicButtons() { - Widget header = client.getWidget(InterfaceID.Music.UNIVERSE); + Widget header = client.getWidget(InterfaceID.Music.NOW_PLAYING); if (header == null) { @@ -293,31 +222,27 @@ private void addMusicButtons() header.deleteAllChildren(); //Creation of the search and toggle status buttons - musicSearchButton = header.createChild(-1, WidgetType.GRAPHIC); - musicSearchButton.setSpriteId(SpriteID.GeSmallicons.SEARCH); - musicSearchButton.setOriginalWidth(18); - musicSearchButton.setOriginalHeight(17); - musicSearchButton.setXPositionMode(WidgetPositionMode.ABSOLUTE_RIGHT); - musicSearchButton.setOriginalX(5); - musicSearchButton.setOriginalY(32); - musicSearchButton.setHasListener(true); + musicSearchButton = header.createChild(-1, WidgetType.GRAPHIC) + .setSpriteId(SpriteID.GeSmallicons.SEARCH) + .setSize(18, 17) + .setPos(5, 6, WidgetPositionMode.ABSOLUTE_RIGHT, WidgetPositionMode.ABSOLUTE_BOTTOM) + .setName("Search") + .setHasListener(true); musicSearchButton.setAction(1, "Open"); musicSearchButton.setOnOpListener((JavaScriptCallback) e -> openSearch()); - musicSearchButton.setName("Search"); musicSearchButton.revalidate(); - musicFilterButton = header.createChild(-1, WidgetType.GRAPHIC); - musicFilterButton.setSpriteId(SpriteID.OrbFiller.PRAYER); - musicFilterButton.setOriginalWidth(15); - musicFilterButton.setOriginalHeight(15); - musicFilterButton.setXPositionMode(WidgetPositionMode.ABSOLUTE_RIGHT); - musicFilterButton.setOriginalX(25); - musicFilterButton.setOriginalY(34); - musicFilterButton.setHasListener(true); + musicFilterButton = header.createChild(-1, WidgetType.GRAPHIC) + .setSpriteId(SpriteID.OrbFiller.PRAYER) + .setSize(15, 15) + .setPos(25, 6, WidgetPositionMode.ABSOLUTE_RIGHT, WidgetPositionMode.ABSOLUTE_BOTTOM) + .setName("All") + .setHasListener(true); musicFilterButton.setAction(1, "Toggle"); musicFilterButton.setOnOpListener((JavaScriptCallback) e -> toggleStatus()); - musicFilterButton.setName("All"); musicFilterButton.revalidate(); + + updateFilterButton(); } @Subscribe @@ -329,15 +254,6 @@ public void onVarClientIntChanged(VarClientIntChanged varClientIntChanged) } } - @Subscribe - public void onVolumeChanged(VolumeChanged volumeChanged) - { - if (musicConfig.granularSliders()) - { - updateMusicOptions(); - } - } - @Subscribe public void onConfigChanged(ConfigChanged configChanged) { @@ -345,19 +261,7 @@ public void onConfigChanged(ConfigChanged configChanged) { clientThread.invoke(() -> { - if (MusicConfig.GRANULAR_SLIDERS.equals(configChanged.getKey())) - { - if (musicConfig.granularSliders()) - { - updateMusicOptions(); - resetSettingsWindow(); - } - else - { - teardownMusicOptions(); - } - } - else if (MusicConfig.MUTE_AMBIENT_SOUNDS.equals(configChanged.getKey())) + if (MusicConfig.MUTE_AMBIENT_SOUNDS.equals(configChanged.getKey())) { // Reload the scene to reapply ambient sounds if (client.getGameState() == GameState.LOGGED_IN) @@ -365,11 +269,55 @@ else if (MusicConfig.MUTE_AMBIENT_SOUNDS.equals(configChanged.getKey())) client.setGameState(GameState.LOADING); } } - else if (musicConfig.granularSliders()) + }); + } + } + + @Subscribe + private void onVarbitChanged(VarbitChanged ev) + { + if (ev.getVarbitId() == VarbitID.SETTINGS_MUSIC_PLAYER_HIDE_TRACKS) + { + currentMusicFilter = null; + updateFilterButton(); + } + } + + @Subscribe + private void onScriptCallbackEvent(ScriptCallbackEvent ev) + { + if ("musicTrackFilter".equals(ev.getEventName())) + { + int override = -1; + + if (currentMusicFilter != null) + { + boolean unlocked = client.getIntStack()[client.getIntStackSize() - 1] != 0; + switch (currentMusicFilter) { - updateMusicOptions(); + case ALL: + override = 1; + break; + case LOCKED: + override = unlocked ? 0 : 1; + break; + case UNLOCKED: + override = unlocked ? 1 : 0; + break; } - }); + } + + if (!Strings.isNullOrEmpty(search)) + { + int dbrow = client.getIntStack()[client.getIntStackSize() - 2]; + var displayName = client.getDBTableField(dbrow, DBTableID.Music.COL_DISPLAYNAME, 0); + if (displayName.length > 0 && !((String) displayName[0]).toLowerCase().contains(search)) + { + override = 0; + } + } + + client.getIntStack()[client.getIntStackSize() - 3] = override; } } @@ -383,19 +331,43 @@ private boolean isChatboxOpen() return searchInput != null && chatboxPanelManager.getCurrentInput() == searchInput; } - private String getChatboxInput() - { - return isChatboxOpen() ? searchInput.getValue() : ""; - } - private void toggleStatus() { MusicState[] states = MusicState.values(); + + if (currentMusicFilter == null) + { + int state = client.getVarbitValue(VarbitID.SETTINGS_MUSIC_PLAYER_HIDE_TRACKS); + currentMusicFilter = states[state]; + } + currentMusicFilter = states[(currentMusicFilter.ordinal() + 1) % states.length]; - musicFilterButton.setSpriteId(currentMusicFilter.getSpriteID()); - musicFilterButton.setName(currentMusicFilter.getName()); - updateFilter(getChatboxInput()); + updateFilterButton(); client.playSoundEffect(SoundEffectID.UI_BOOP); + + redrawList(); + } + + private void updateFilterButton() + { + var filter = currentMusicFilter; + if (filter == null) + { + int state = client.getVarbitValue(VarbitID.SETTINGS_MUSIC_PLAYER_HIDE_TRACKS); + filter = MusicState.values()[state]; + } + + musicFilterButton.setSpriteId(filter.getSpriteID()); + musicFilterButton.setName(filter.getName()); + } + + private void redrawList() + { + var transmitListenerWidget = client.getWidget(InterfaceID.Music.INNER); + if (transmitListenerWidget != null && transmitListenerWidget.getOnVarTransmitListener() != null) + { + client.runScript(transmitListenerWidget.getOnVarTransmitListener()); + } } private void openSearch() @@ -425,556 +397,23 @@ private void closeSearch() private void updateFilter(String input) { - final Widget container = client.getWidget(InterfaceID.Music.UNIVERSE); - final Widget musicList = client.getWidget(InterfaceID.Music.JUKEBOX); - final Widget scrollContainer = client.getWidget(InterfaceID.Music.SCROLLABLE); - - if (container == null || musicList == null) - { - return; - } - - String filter = input.toLowerCase(); - updateList(scrollContainer, musicList, filter); - } - - private void updateList(Widget scrollContainer, Widget musicList, String filter) - { - if (tracks == null) - { - tracks = Arrays.stream(musicList.getDynamicChildren()) - .sorted(Comparator.comparingInt(Widget::getRelativeY)) - .collect(Collectors.toList()); - } - - tracks.forEach(w -> w.setHidden(true)); - - Collection relevantTracks = tracks.stream() - .filter(w -> w.getText().toLowerCase().contains(filter)) - .filter(w -> currentMusicFilter == MusicState.ALL || w.getTextColor() == currentMusicFilter.getColor()) - .collect(Collectors.toList()); - - // Original music track list has a little offset - int y = 3; - - for (Widget track : relevantTracks) - { - track.setHidden(false); - track.setOriginalY(y); - track.revalidate(); - - y += track.getHeight(); - } - - y += 3; - - int newHeight = 0; - - if (scrollContainer.getScrollHeight() > 0) - { - newHeight = (scrollContainer.getScrollY() * y) / scrollContainer.getScrollHeight(); - } - - scrollContainer.setScrollHeight(y); - scrollContainer.revalidateScroll(); - - client.runScript( - ScriptID.UPDATE_SCROLLBAR, - InterfaceID.Music.SCROLLBAR, - InterfaceID.Music.SCROLLABLE, - newHeight - ); + search = input.toLowerCase(); + redrawList(); } @AllArgsConstructor @Getter private enum MusicState { - NOT_FOUND(0xff0000, "Locked", SpriteID.OrbFiller.HITPOINTS), - FOUND(0xdc10d, "Unlocked", SpriteID.OrbFiller.HITPOINTS_POISON), - ALL(0, "All", SpriteID.OrbFiller.PRAYER); + ALL("All", SpriteID.OrbFiller.PRAYER), + UNLOCKED("Unlocked", SpriteID.OrbFiller.HITPOINTS_POISON), + LOCKED("Locked", SpriteID.OrbFiller.HITPOINTS), + ; - private final int color; private final String name; private final int spriteID; } - @RequiredArgsConstructor - private class Slider - { - @Getter - protected final Channel channel; - - protected Widget track; - protected Widget handle; - - public void update() - { - handle.setNoClickThrough(false); - handle.setOnDragListener((JavaScriptCallback) this::drag); - handle.setOnDragCompleteListener((JavaScriptCallback) this::drag); - handle.setHasListener(true); - - track.setOnMouseRepeatListener((JavaScriptCallback) ev -> - { - int value = channel.getValue(); - int percent = (int) Math.round((value * 100.0 / channel.getMax())); - - sliderTooltip = new Tooltip(channel.getName() + ": " + percent + "%"); - }); - track.setOnClickListener((JavaScriptCallback) this::click); - track.setHasListener(true); - } - - public void shutDown() - { - if (handle != null) - { - handle.setDragParent(null); - handle.setOnDragListener((Object[]) null); - handle.setOnDragCompleteListener((Object[]) null); - } - if (track != null) - { - track.setOnMouseRepeatListener((Object[]) null); - track.setOnClickListener((Object[]) null); - } - } - - protected void drag(ScriptEvent ev) - { - moveHandle(ev.getMouseX()); - } - - protected void click(ScriptEvent ev) - { - moveHandle(ev.getMouseX() - (SLIDER_HANDLE_SIZE / 2)); - } - - protected void moveHandle(int x) - { - int level = (x * channel.max) / getWidth(); - level = Ints.constrainToRange(level, 0, channel.max); - channel.setLevel(level); - - int percent = (int) Math.round((level * 100.0 / channel.getMax())); - sliderTooltip = new Tooltip(channel.getName() + ": " + percent + "%"); - } - - protected int getWidth() - { - return track.getWidth() - SLIDER_HANDLE_SIZE; - } - } - - private class SettingsSideSlider extends Slider - { - @Component - private final int root; - private Widget icon; - - SettingsSideSlider(Channel channel, @Component int root) - { - super(channel); - this.root = root; - } - - @Override - public void update() - { - Widget root = client.getWidget(this.root); - if (root == null) - { - return; - } - - Object[] onLoad = root.getOnLoadListener(); - if (onLoad == null || onLoad.length != 6) - { - return; - } - - this.icon = client.getWidget((Integer) onLoad[1]); - this.track = client.getWidget((Integer) onLoad[2]); - this.handle = client.getWidget((Integer) onLoad[3]); - if (this.track == null || this.handle == null) - { - return; - } - - Widget[] trackChildren = track.getChildren(); - - if (trackChildren != null) - { - for (Widget w : trackChildren) - { - if (w != null) - { - w.setAction(0, null); - } - } - } - - handle.setOnVarTransmitListener((Object[]) null); - handle.setDragParent(track); - handle.setSpriteId(SpriteID.SettingsSlider.HANDLE_GREEN); - super.update(); - - int val = channel.getValue(); - handle.setOriginalX((val * getWidth()) / channel.getMax()); - handle.revalidate(); - - // emulate [proc,settings_update_icon] - boolean unmuted = val != 0; - Widget strikethrough = icon.getChild(1); - if (strikethrough != null) - { - strikethrough.setHidden(unmuted); - } - icon.setAction(0, unmuted ? "Mute" : "Unmute"); - // Set name + no tooltip; we have our own for ops - icon.setName(channel.getName()); - icon.setOnMouseRepeatListener((Object[]) null); - icon.setOnOpListener((JavaScriptCallback) ev -> channel.toggleMute()); - icon.setClickMask(0); // do not transmit op, it can get desynced from our state - } - - @Override - public void shutDown() - { - super.shutDown(); - - if (this.handle != null) - { - handle.setSpriteId(SpriteID.SettingsSlider.HANDLE_BLUE); - } - - if (this.icon != null) - { - this.icon.setOnOpListener((Object[]) null); - this.icon.setClickMask(WidgetConfig.transmitAction(0)); - } - - Widget root = client.getWidget(this.root); - if (root != null) - { - client.createScriptEvent(root.getOnLoadListener()) - .setSource(root) - .run(); - } - - this.handle = this.track = this.icon = null; - } - } - - private class SettingsSlider extends Slider - { - private final int offsetX; - private final int offsetY; - private final int width; - private final Widget realTrack; - - SettingsSlider(Channel channel, Widget handle, Widget track, int width, int offsetY, int offsetX, Widget realTrack) - { - super(channel); - this.handle = handle; - this.track = track; - this.width = width; - this.offsetX = offsetX; - this.offsetY = offsetY; - this.realTrack = realTrack; - } - - @Override - public void update() - { - super.update(); - - int val = channel.getValue(); - handle.setOriginalX(offsetX + (val * getWidth()) / channel.getMax()); - handle.setOriginalY(offsetY); - handle.revalidate(); - } - - @Override - protected int getWidth() - { - return width - SLIDER_HANDLE_SIZE; - } - - @Override - protected void click(ScriptEvent ev) - { - super.click(ev); - realTrack.setOriginalX(offsetX); - realTrack.setOriginalY(offsetY); - realTrack.setOriginalWidth(this.width); - realTrack.setOriginalHeight(SLIDER_HANDLE_SIZE); - realTrack.revalidate(); - } - - @Override - @SuppressWarnings("PMD.UselessOverridingMethod") - public void shutDown() - { - // calling settings_init will do teardown for us - super.shutDown(); - } - } - - @Subscribe - private void onPostStructComposition(PostStructComposition ev) - { - if (shuttingDown) - { - return; - } - - StructComposition sc = ev.getStructComposition(); - switch (sc.getId()) - { - case StructID.SETTINGS_MUSIC_VOLUME: - case StructID.SETTINGS_EFFECT_VOLUME: - case StructID.SETTINGS_AREA_VOLUME: - if (!musicConfig.granularSliders()) - { - return; - } - - sc.setValue(ParamID.SETTING_SLIDER_STEPS, 1); - sc.setValue(ParamID.SETTING_CUSTOM_TRANSMIT, 0); - sc.setValue(ParamID.SETTING_FOREGROUND_CLICKZONE, 0); - sc.setValue(ParamID.SETTING_SLIDER_CUSTOM_ONOP, 1); - sc.setValue(ParamID.SETTING_SLIDER_CUSTOM_SETPOS, 1); - sc.setValue(ParamID.SETTING_SLIDER_IS_DRAGGABLE, 1); - sc.setValue(ParamID.SETTING_SLIDER_DEADZONE, 0); - sc.setValue(ParamID.SETTING_SLIDER_DEADTIME, 0); - break; - } - } - - @Subscribe - private void onScriptPreFired(ScriptPreFired ev) - { - if (shuttingDown) - { - return; - } - - if (ev.getScriptId() == ScriptID.SETTINGS_SLIDER_CHOOSE_ONOP) - { - if (!musicConfig.granularSliders()) - { - return; - } - - int arg = client.getIntStackSize() - 11; - int[] is = client.getIntStack(); - Channel channel; - switch (is[arg]) - { - case SettingID.MUSIC_VOLUME: - channel = musicChannel; - break; - case SettingID.EFFECT_VOLUME: - channel = effectChannel; - break; - case SettingID.AREA_VOLUME: - channel = areaChannel; - break; - default: - return; - } - - Widget track = client.getScriptActiveWidget(); - Widget handle = client.getWidget(is[arg + 1]) - .getChild(is[arg + 2]); - Widget realTrack = client.getWidget(is[arg + 7]); - SettingsSlider s = new SettingsSlider(channel, handle, track, is[arg + 3], is[arg + 4], is[arg + 5], realTrack); - s.update(); - s.getChannel().setWindowSlider(s); - } - - if (ev.getScriptId() == ScriptID.TOPLEVEL_REDRAW && musicConfig.granularSliders()) - { - // we have to set the var to our value so toplevel_redraw doesn't try to set - // the volume to what vanilla has stored - for (Channel c : channels) - { - c.updateVar(); - } - } - } - - private class Channel - { - @Getter - private final String name; - @Varp - private final int var; - @Varbit - private final int mutedVarbitId; - private final IntSupplier getter; - private final Consumer setter; - private final IntConsumer volumeChanger; - - @Getter - private final int max; - - private final Slider sideSlider; - - @Setter - private Slider windowSlider; - - Channel(String name, - @Varp int var, @Varbit int mutedVarbitId, - IntSupplier getter, Consumer setter, - IntConsumer volumeChanger, int max, - @Component int sideRoot) - { - this.name = name; - this.var = var; - this.mutedVarbitId = mutedVarbitId; - this.getter = getter; - this.setter = setter; - this.volumeChanger = volumeChanger; - this.max = max; - this.sideSlider = new SettingsSideSlider(this, sideRoot); - } - - private int getValueRaw() - { - int value = getter.getAsInt(); - if (value == 0) - { - // Use the vanilla value - - // the varps are known by the engine and it requires they are stored so - // 0 = max and 4 = muted - int raw = client.getVarpValue(var); - if (raw == 0) - { - raw = -client.getVarbitValue(mutedVarbitId); - } - value = raw * this.max / 100; - - // readd our 1 offset for unknown's place - value += value < 0 ? -1 : 1; - } - - return value; - } - - private int getValue() - { - int value = getValueRaw(); - - // muted with saved restore point - if (value < 0) - { - return 0; - } - - // 0 is used for unknown, so config values are 1 away from zero - return value - 1; - } - - public void toggleMute() - { - int val = -getValueRaw(); - if (val == -1) - { - // muted without a reset value - val = max / 2; - } - setter.accept(val); - } - - public void setLevel(int level) - { - setter.accept(level + 1); - update(); - } - - public void update() - { - volumeChanger.accept(getValue()); - sideSlider.update(); - if (windowSlider != null) - { - windowSlider.update(); - } - } - - public void updateVar() - { - int val = getValue(); - int varVal = Math.round(val / (max / 100.f)); - client.getVarps()[this.var] = varVal; - } - - public void shutDown() - { - sideSlider.shutDown(); - if (windowSlider != null) - { - windowSlider.shutDown(); - } - - volumeChanger.accept(client.getVarpValue(var) * this.max / 100); - } - } - - private void updateMusicOptions() - { - for (Channel channel : channels) - { - channel.update(); - } - } - - private void teardownMusicOptions() - { - // the side panel uses this too, so it has to run before they get shut down - client.getStructCompositionCache().reset(); - - for (Channel channel : channels) - { - channel.shutDown(); - } - - resetSettingsWindow(); - } - - private void resetSettingsWindow() - { - client.getStructCompositionCache().reset(); - - Widget init = client.getWidget(InterfaceID.Settings.UNIVERSE); - if (init != null) - { - // [clientscript, settings_init] - client.createScriptEvent(init.getOnLoadListener()) - .setSource(init) - .run(); - } - } - - @Subscribe - private void onBeforeRender(BeforeRender ev) - { - if (sliderTooltip != null) - { - tooltipManager.add(sliderTooltip); - } - } - - @Subscribe - public void onClientTick(ClientTick event) - { - sliderTooltip = null; - } - @Subscribe public void onAreaSoundEffectPlayed(AreaSoundEffectPlayed areaSoundEffectPlayed) { diff --git a/runelite-client/src/main/scripts/MusicFilterTrack.hash b/runelite-client/src/main/scripts/MusicFilterTrack.hash new file mode 100644 index 00000000000..67b8afdae7a --- /dev/null +++ b/runelite-client/src/main/scripts/MusicFilterTrack.hash @@ -0,0 +1 @@ +4FD89760CC4EB32E465465940F8E0092A758171B82FC32F4BBCEF60A5FD154F8 \ No newline at end of file diff --git a/runelite-client/src/main/scripts/MusicFilterTrack.rs2asm b/runelite-client/src/main/scripts/MusicFilterTrack.rs2asm new file mode 100644 index 00000000000..def5f7a185c --- /dev/null +++ b/runelite-client/src/main/scripts/MusicFilterTrack.rs2asm @@ -0,0 +1,81 @@ +.id 9291 +.int_arg_count 5 +.obj_arg_count 0 + iconst -1 ; push return value + iload 0 ; push id + iload 4 ; push unlocked state + sconst "musicTrackFilter" + runelite_callback + pop_int ; pop unlocked state + pop_int ; pop id + switch ; default value falls through + 0: HIDE + 1: SKIP_HIDE + + iload 4 + iconst 0 + if_icmpeq LABEL4 + jump LABEL10 +LABEL4: + get_varbit 19733 + iconst 1 + if_icmpeq LABEL8 + jump LABEL10 +LABEL8: +HIDE: + iconst 0 + return +LABEL10: + iload 4 + iconst 1 + if_icmpeq LABEL14 + jump LABEL20 +LABEL14: + get_varbit 19733 + iconst 2 + if_icmpeq LABEL18 + jump LABEL20 +LABEL18: + iconst 0 + return +LABEL20: +SKIP_HIDE: + get_varbit 19731 + switch + 1: LABEL23 + 2: LABEL30 + 3: LABEL37 + jump LABEL43 +LABEL23: + iload 1 + iconst 0 + if_icmpeq LABEL27 + jump LABEL29 +LABEL27: + iconst 0 + return +LABEL29: + jump LABEL43 +LABEL30: + iload 2 + iconst 0 + if_icmpeq LABEL34 + jump LABEL36 +LABEL34: + iconst 0 + return +LABEL36: + jump LABEL43 +LABEL37: + iload 3 + iconst 0 + if_icmpeq LABEL41 + jump LABEL43 +LABEL41: + iconst 0 + return +LABEL43: + iconst 1 + return + iconst -1 + return From 738a9932f7761686002a501f474c4c2be9c1c114 Mon Sep 17 00:00:00 2001 From: Max Weber Date: Tue, 10 Feb 2026 14:07:38 -0700 Subject: [PATCH 14/17] camera: update 2026-2-11 --- .../java/net/runelite/client/plugins/camera/CameraPlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/camera/CameraPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/camera/CameraPlugin.java index 030094e56f1..faa7627e213 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/camera/CameraPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/camera/CameraPlugin.java @@ -397,7 +397,7 @@ private void onScriptPreFired(ScriptPreFired ev) { case ScriptID.SETTINGS_SLIDER_CHOOSE_ONOP: { - int arg = client.getIntStackSize() - 11; + int arg = client.getIntStackSize() - 12; int[] is = client.getIntStack(); if (is[arg] == SettingID.CAMERA_ZOOM) From 5e6cdb45951d9c8badb94112e777421fda4b338a Mon Sep 17 00:00:00 2001 From: RuneLite updater Date: Wed, 11 Feb 2026 11:08:10 +0000 Subject: [PATCH 15/17] Release 1.12.17 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index a4776710c31..e5eab99af34 100644 --- a/gradle.properties +++ b/gradle.properties @@ -28,6 +28,6 @@ org.gradle.parallel=true org.gradle.caching=false project.build.group=net.runelite -project.build.version=1.12.17-SNAPSHOT +project.build.version=1.12.17 glslang.path= From a9b49fbdff2824297b93f06debf3e857a4ee355a Mon Sep 17 00:00:00 2001 From: RuneLite updater Date: Wed, 11 Feb 2026 11:08:11 +0000 Subject: [PATCH 16/17] Bump for 1.12.18-SNAPSHOT [ci skip] --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index e5eab99af34..aa7148c5ce3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -28,6 +28,6 @@ org.gradle.parallel=true org.gradle.caching=false project.build.group=net.runelite -project.build.version=1.12.17 +project.build.version=1.12.18-SNAPSHOT glslang.path= From 5413f571459d03ae9e100039acf4ca96fc75dc7a Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 11 Feb 2026 14:35:01 -0500 Subject: [PATCH 17/17] ping: fix flipped BytesOut/BytesRetrans --- .../runelite/client/plugins/worldhopper/ping/TCP_INFO_v0.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/TCP_INFO_v0.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/TCP_INFO_v0.java index e59b54f23b8..539c3302951 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/TCP_INFO_v0.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/ping/TCP_INFO_v0.java @@ -85,12 +85,12 @@ public long getRTT() @Override public long getRetransmitted() { - return BytesOut.longValue(); + return BytesRetrans.longValue(); } @Override public long getTransmitted() { - return BytesRetrans.longValue(); + return BytesOut.longValue(); } }