Plugin Documentation/Copper & Tin Miner

Complete plugin development guide

Build a KLite marketplace plugin.

Use the Copper & Tin Miner as a complete reference implementation for dependency injection, cooperative automation, Shortest Path walking, object interaction, banking, configuration, overlays, diagnostics, packaging, and marketplace publication.

4Java components
12Implementation stages
1Publishable plugin JAR
02

Foundation

Project structure

Keep the plugin entrypoint, configuration, automation state machine, and overlay in separate classes. This makes shutdown behavior, testing, and marketplace review easier to reason about.

Project tree
examples/klite-copper-tin-miner/
├── build.gradle.kts
└── src/main/java/net/runelite/client/plugins/klite/examples/miner/
    ├── CopperTinMinerPlugin.java
    ├── CopperTinMinerConfig.java
    ├── CopperTinMinerTask.java
    └── CopperTinMinerOverlay.java
Plugin

Lifecycle owner

Registers dependencies, the automation task, and the plugin-owned overlay.

Task

State machine

Coordinates mining, walking, banking, cancellation, and bounded API waits.

Config

User settings

Exposes supported options through RuneLite's normal configuration system.

Overlay

Runtime visibility

Shows current mode, destination, route status, runtime, and failures.

03

Lifecycle

Plugin entrypoint and dependency

The entrypoint connects the external plugin to KLite Core and owns every resource that must be released during shutdown.

CopperTinMinerPlugin.java
@PluginDependency(KLitePlugin.class)
@PluginDescriptor(
    name = "Copper and Tin Miner",
    description = "Mines copper and tin near Varrock and banks only when full",
    version = "0.0.2",
    enabledByDefault = false,
    isExternal = true
)
public class CopperTinMinerPlugin extends Plugin
{
    // Inject KLite services and own startup/shutdown here.
}

Startup sequence

  1. 1

    Create the automation task.

  2. 2

    Create and register the plugin overlay.

  3. 3

    Enable the shared automation manager.

  4. 4

    Start the task after checking for conflicts.

Shutdown sequence

  1. 1

    Stop and cancel the automation task.

  2. 2

    Clear the active web-walker route.

  3. 3

    Remove the overlay from the manager.

  4. 4

    Release references so the class loader can unload.

04

Settings

Configuration

Provide configuration through ConfigManager. The example exposes a Show overlay option enabled by default, while operational constants remain in the task implementation.

Configuration provider
@Provides
CopperTinMinerConfig provideConfig(ConfigManager configManager)
{
    return configManager.getConfig(CopperTinMinerConfig.class);
}
05

Execution model

Cooperative automation task

The task implements AutomationTask and advances one bounded unit of work per tick. RuneLite operations return CompletableFuture values; wait through AutomationContext.await with an explicit timeout.

StateResponsibilityExit condition
MININGMove to the mine, select the preferred ore, and track the active rock.Inventory becomes full.
BANKINGMove to the bank and deposit every non-pickaxe stack.Only the pickaxe remains.
WALKINGDelegate route planning and progress to the shared web walker.Arrival radius is reached.
STOPPINGTreat cancellation as normal shutdown rather than a task failure.Resources are released.
06

Interaction control

Mining interaction lifecycle

A successful Mine dispatch does not immediately permit another click. Track the rock ID, world location, dispatch time, and whether the mining animation has been observed.

Completion conditions

  • The tracked rock disappears or changes object ID at the same tile.
  • The mining animation was observed and then remains stopped for a confirmation interval.
  • The animation never starts before the startup timeout, allowing one controlled retry.
Rock tracking state
activeRockId = selected.getObjectId();
activeRockLocation = selected.getLocation();
miningAnimationObserved = false;

// Every task tick:
// 1. Check whether the object ID at the tile changed.
// 2. Check whether the player is still animating.
// 3. Confirm that animation has stopped before selecting another rock.
07

Inventory control

Full-inventory banking

Begin banking only when all 28 inventory slots are occupied and at least one item is not a pickaxe. This prevents empty, partial, and pickaxe-only inventories from opening the bank.

Banking transition
boolean inventoryFull = inventory.size() >= 28;
Optional<InventoryItem> depositable = inventory.stream()
    .filter(item -> !isPickaxe(item))
    .findFirst();

if (!banking && inventoryFull && depositable.isPresent())
{
    banking = true;
}
08

Navigation

Integrated web walking

The plugin owns destinations and arrival radiuses. KLite Core owns route planning, collision data, waypoint selection, scene and minimap rendering, progress tracking, and stall recovery.

Web-walker step
WebWalkResult result = context.await(
    webWalker.step(destination, arrivalDistance),
    API_TIMEOUT
);

if (result.getState() == WebWalkState.NO_PATH)
{
    throw new IllegalStateException(result.getMessage());
}
09

Observability

Plugin-owned overlay

Keep plugin-specific status separate from the global KLite status overlay. The user should be able to identify what the task is doing without opening logs.

Automation

Task status

Activity, current mode, runtime, and failure state.

Mining

Target state

Preferred ore, active rock, and mining destination.

Walking

Route state

Walker state, route length, next waypoint, and route message.

Banking

Transition reason

The explicit full-inventory trigger and deposit progress.

10

Troubleshooting

Diagnostics and logging

Use KLite Logs → Client / Plugin Debug for task and walker behavior. Use the Marketplace tab for artifact download, hash verification, class loading, enable/disable, and unload failures.

Representative log output
[CopperTinMiner] Tracking rock ... until mining stops or object changes.
[WebWalker] Integrated Shortest Path accepted route length=...
[WebWalker] Clicking waypoint ... surface=minimap
[CopperTinMiner] Deposit result: status=...
11

Distribution

Build and publish

Gradle
./gradlew :copper-tin-miner:clean :copper-tin-miner:jar --no-daemon
  1. BuildCreate a reproducible JAR containing only the plugin implementation.
  2. CopyPlace the JAR in marketplace-site/public/artifacts/.
  3. VerifyCalculate the SHA-256 digest and exact file size.
  4. CatalogUpdate plugins.json with version, hash, size, and entrypoint.
  5. DeployPublish the static artifact and catalog together.
  6. TestUnload the previous in-memory version before enabling the replacement.
12

Marketplace quality gate

Review checklist

  • Declares @PluginDependency(KLitePlugin.class) when using KLite services.
  • Does not bundle protected RuneLite or KLite classes.
  • Stops automation and removes overlays during shutdown.
  • Uses bounded asynchronous API calls.
  • Does not retain passwords, secrets, or unbounded logs.
  • Uses the shared WebWalker instead of implementing arbitrary movement.
  • Logs state transitions and actionable failure details.
  • Declares accurate version, minimum client version, authors, and entrypoints.

Next reference

Explore the callable API.

Use the API reference to inspect public KLite types and method signatures available to marketplace plugins.

Open API Reference