Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .run/Microbot.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Microbot" type="Application" factoryName="Application">
<option name="ALTERNATIVE_JRE_PATH" value="11" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
<option name="MAIN_CLASS_NAME" value="net.runelite.client.RuneLite" />
<module name="client.main" />
<option name="PROGRAM_PARAMETERS" value="-developer-mode" />
<option name="VM_PARAMETERS" value="-ea" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>
133 changes: 95 additions & 38 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,38 +1,95 @@
# Repository Guidelines

## Project Structure & Module Organization
- The root `pom.xml` controls the multi-module Maven build for `cache`, `runelite-api`, `runelite-client`, `runelite-jshell`, and `runelite-maven-plugin`.
- Gameplay automation lives in `runelite-client/src/main/java/net/runelite/client/plugins/microbot`; keep new scripts and utilities inside this plugin.
- Shared helpers sit under `.../microbot/util`, while runnable examples live in `.../microbot/example`.
- Tests mirror sources in `runelite-client/src/test/java`, and project documentation and walkthroughs are kept in `docs/`.
- CI helpers and custom Maven settings are in `ci/`, and distributable jars land in `runelite-client/target/`.

## Build, Test, and Development Commands
- `mvn -pl runelite-client -am package` builds the client and produces `target/microbot-<version>.jar`.
- `./ci/build.sh` recreates the CI pipeline, fetching `glslangValidator` and running `mvn verify --settings ci/settings.xml`.
- `mvn -pl runelite-client test` runs the unit suite; add `-DskipTests` only when packaging binaries for distribution.
- `java -jar runelite-client/target/microbot-<version>.jar` launches a locally built client for manual validation.

## Coding Style & Naming Conventions
- Target Java 11 (`maven-compiler-plugin` uses `<release>11</release>`); rely on Lombok for boilerplate where already adopted.
- Keep indentation with tabs, follow the brace placement already in `MicrobotPlugin.java`, and prefer lines under 120 characters.
- Use `UpperCamelCase` for types, `lowerCamelCase` for members, and prefix configuration interfaces with the plugin name (e.g., `ExampleConfig`).
- Centralize shared logic in util classes rather than duplicating inside scripts; inject dependencies through RuneLite’s DI when needed.

## Testing Guidelines
- Write JUnit 4 tests (`junit:4.12`) under matching package paths in `runelite-client/src/test/java`.
- Name test classes with the `*Test` suffix and break scenarios into focused `@Test` methods that assert observable client state.
- Use Mockito (`mockito-core:3.1.0`) for client services; rely on `guice-testlib` when event bus wiring is involved.
- Run `mvn test` (or `mvn verify` before release) locally before opening a pull request and attach logs when failures require review.

## Commit & Pull Request Guidelines
- Follow the existing conventional commit style: `type(scope): summary` (e.g., `refactor(Rs2Walker): expand teleport keywords`).
- Squash noisy work-in-progress commits before pushing and keep summaries under 72 characters.
- PRs should explain the gameplay scenario, note affected plugins, link related issues or scripts, and include screenshots or clips when UI overlays change.
- Confirm tests/builds in the PR description and mention any follow-up tasks or config changes reviewers must perform.

## Agent-Specific Instructions
- Register new automation under `net.runelite.client.plugins.microbot` and reuse the scheduler pattern shown in `ExampleScript`.
- Expose reusable behaviour through `microbot/util` packages so scripts stay thin and composable.
- When adding panel controls or overlays, update the Microbot navigation panel setup in `MicrobotPlugin` and provide default config values.
- Document new APIs in `docs/api/` and cross-link from `docs/development.md` so contributors can discover capabilities quickly.
# Microbot Agent Guide

Guidance for AI agents building Microbot scripts with the new `microbot/api` queryable layer.

## 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`.

## Build & Test
- Fast build: `mvn -pl runelite-client -am package` (jar in `runelite-client/target/`).
- Unit tests: `mvn -pl runelite-client test`.
- CI parity: `./ci/build.sh` (runs `mvn verify --settings ci/settings.xml`).

## Style Rules
- Java 11 target, tabs for indentation, braces match `MicrobotPlugin.java`, prefer <120 chars/line.
- Name types in UpperCamelCase, members in lowerCamelCase; configs prefixed with plugin name (e.g., `ExampleConfig`).

## Script Pattern
Pair a RuneLite `Plugin` with a `Script` that runs on a background thread; never sleep on the client thread.

```java
@PluginDescriptor(name = "Gathering Demo")
public class GatheringPlugin extends Plugin {
@Inject private GatheringScript script;
@Override protected void startUp() { script.run(); }
@Override protected void shutDown() { script.shutdown(); }
}

@Slf4j
public class GatheringScript extends Script {
@Override
public boolean run() {
mainScheduledFuture = scheduledExecutorService.scheduleWithFixedDelay(() -> {
try {
if (!Microbot.isLoggedIn() || !super.run()) return;

Rs2TileObjectModel tree = new Rs2TileObjectQueryable()
.withName("Tree")
.where(obj -> !Rs2Player.isAnimating())
.nearest();

if (tree != null) {
tree.click("Chop down");
sleepUntil(() -> Rs2Player.isAnimating(), 3000);
}
} catch (Exception e) {
log.error("Loop error", e);
}
}, 0, 600, TimeUnit.MILLISECONDS); // ~1 tick
return true;
}
}
```

## Queryable API Cheatsheet
- **NPCs**
```java
Rs2NpcModel banker = new Rs2NpcQueryable()
.withNames("Banker", "Bank clerk")
.where(npc -> !npc.isInteracting())
.nearest(15);
if (banker != null) banker.click("Bank");
```
- **Ground items**
```java
Rs2TileItemModel loot = new Rs2TileItemQueryable()
.where(Rs2TileItemModel::isLootAble)
.where(item -> item.getTotalGeValue() >= 3000)
.nearest(10);
if (loot != null) loot.pickup();
```
- **Tile objects**
```java
Rs2TileObjectModel bankChest = new Rs2TileObjectQueryable()
.withNames("Bank chest", "Bank booth")
.nearest(20);
if (bankChest != null && !Rs2Bank.isOpen()) {
bankChest.click("Bank");
sleepUntil(Rs2Bank::isOpen, 5000);
}
```
- **Players**
```java
Rs2PlayerModel ally = new Rs2PlayerQueryable()
.where(Rs2PlayerModel::isFriend)
.within(20)
.nearest();
```

## Safety & Timing
- Always guard logic with `Microbot.isLoggedIn()` and `super.run()`; bail early when paused.
- Use `sleep`/`sleepUntil` only on script threads; wrap client access with `Microbot.getClientThread().runOnClientThread(...)` when needed.
- Wait for state changes after interactions (`Rs2Bank.isOpen()`, `Rs2Player.isAnimating()`, inventory/bank counts).
- Limit query radius with `.within(...)` to reduce overhead and cache results inside a loop when reused.
96 changes: 96 additions & 0 deletions CLAUDE.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Microbot API Guide (for Claude)

Short notes for writing automation scripts with the Microbot plugin inside RuneLite.

## 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: `mvn -pl runelite-client -am package`; tests: `mvn -pl runelite-client test`.

## Script Skeleton
Use a Plugin + Script pair. Keep sleeps off the client thread and always check login state.

```java
@PluginDescriptor(name = "Goblin Demo", description = "Queryable API example")
public class GoblinDemoPlugin extends Plugin {
@Inject private GoblinDemoScript script;

@Override protected void startUp() { script.run(); }
@Override protected void shutDown() { script.shutdown(); }
}

@Slf4j
public class GoblinDemoScript extends Script {
@Override
public boolean run() {
mainScheduledFuture = scheduledExecutorService.scheduleWithFixedDelay(() -> {
try {
if (!Microbot.isLoggedIn() || !super.run()) return;

Rs2NpcModel target = new Rs2NpcQueryable()
.withName("Goblin")
.where(npc -> !npc.isInteracting())
.nearest(10);

if (target != null && !Rs2Player.isInCombat()) {
target.click("Attack");
sleepUntil(() -> Rs2Player.isInCombat(), 2000);
}
} catch (Exception e) {
log.error("Loop error", e);
}
}, 0, 600, TimeUnit.MILLISECONDS); // ~1 game tick
return true;
}
}
```

## Queryable API Quick Reference
Prefer the queryable API over legacy util calls.

- **NPCs**
```java
Rs2NpcModel banker = new Rs2NpcQueryable()
.withNames("Banker", "Bank clerk")
.where(npc -> !npc.isInteracting())
.nearest(15);
if (banker != null) banker.click("Bank");
```

- **Ground items**
```java
Rs2TileItemModel loot = new Rs2TileItemQueryable()
.where(Rs2TileItemModel::isLootAble)
.where(item -> item.getTotalGeValue() >= 5000)
.nearest(10);
if (loot != null) loot.pickup();
```

- **Tile objects**
```java
Rs2TileObjectModel tree = new Rs2TileObjectQueryable()
.where(obj -> obj.getName() != null && obj.getName().contains("Tree"))
.nearest();
if (tree != null && !Rs2Player.isAnimating()) {
tree.click("Chop down");
sleepUntil(() -> Rs2Player.isAnimating(), 3000);
}
```

- **Players**
```java
Rs2PlayerModel teammate = new Rs2PlayerQueryable()
.where(Rs2PlayerModel::isFriend)
.within(20)
.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`).
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ project.build.group=net.runelite
project.build.version=1.12.10

glslang.path=
microbot.version=2.1.0
microbot.version=2.1.1
microbot.commit.sha=nogit
microbot.repo.url=http://138.201.81.246:8081/repository/microbot-snapshot/
microbot.repo.username=
Expand Down
21 changes: 21 additions & 0 deletions runelite-client/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,29 @@ plugins {
id("net.runelite.runelite-gradle-plugin.assemble")
id("net.runelite.runelite-gradle-plugin.index")
id("net.runelite.runelite-gradle-plugin.jarsign")

// application // <-- add this
}

/*application {
mainClass.set("net.runelite.client.RuneLite")
}

tasks.register<JavaExec>("runDebug") {
group = "application"
description = "Run RuneLite client with JDWP debug"

classpath = sourceSets.main.get().runtimeClasspath
mainClass.set("net.runelite.client.RuneLite")

// same JVM args you need normally
jvmArgs(
"-Dfile.encoding=UTF-8",
// JDWP agent for debugger
"-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005"
)
}*/

lombok.version = libs.versions.lombok.get()

java {
Expand Down
Loading