Kraken API is designed to extend the RuneLite API with additional client interaction utilities for writing automation based plugins that are fully compatible with RuneLite. This API uses network packets to perform "click" interactions within the game client and is based on mappings defined by the EthanVann API.
The following RuneLite "plugin" is purely for an example of the API's capabilities and isn't a full fledged automation script.
@PluginDescriptor(
name = "Example",
description = "Example plugin"
)
public class ExamplePlugin extends Plugin {
@Inject
private Context ctx;
@Inject
private BankService bank;
@Inject
private MovementService movement;
@Inject
private PrayerService prayer;
@Subscribe
private void onGameTick(GameTick e) {
Player local = ctx.players().local().raw();
if(local.isInteracting()) {
return;
}
if(!bank.isOpen()) {
// Open a bank
ctx.gameObjects().withName("Bank booth").nearest().interact("Open");
} else {
// Withdraw a Rune Scimitar
ctx.bank().nameContains("Rune scimitar").first().withdraw();
}
// Wield a Rune Scimitar
ctx.equipment().withId(1333).first().wield();
// Move to a new position
movement.moveTo(new WorldPoint(1234, 5678));
// Activate a protection prayer
prayer.activatePrayer(Prayer.PROTECT_FROM_MELEE);
// "Click" on a Goblin and attack it.
ctx.npcs().withName("Goblin")
.except(n -> n.raw().isInteracting())
.nearest()
.interact("Attack");
// Take the goblin bones
ctx.groundItems().reachable()
.within(5)
.filter(item -> item.name().equalIgnoreCase("bones"))
.first()
.take();
// Bury the bones
ctx.inventory().withName("Bones").first().interact("Bury");
}
}In order to use the API in an actual RuneLite plugin you should check out the Kraken Example Plugin which shows a best practice usage of the API within an actual plugin. To set up your development environment we recommend following this guide on RuneLite's Wiki.
Once you have the example plugin cloned and setup within Intellij you can run the main class in src/test/java/ExamplePluginTest.java to run RuneLite with
the example plugin loaded in the plugin panel within RuneLite's sidebar. See consuming the API section for more information on
integrating the API into your plugins and build process.
If you are just looking to use pre-existing plugins, you can skip this repository and head over to our website: kraken-plugins.com. For more documentation on the API and Kraken plugins please see our official documentation here.
- Java 11+ (JDK required)
- Gradle (wrapper included, no need to install globally)
- Git
- RuneLite (for testing and running plugins)
You can build the project with Gradle:
./gradlew clean buildThe output API .jar will be located in:
./lib/build/libs/kraken-api-<version>.jar
Although we recommend using the Github packages approach to access the API since it is more reliable, Jitpack can get you set up with the Kraken API without a personal access token.
plugins {
id 'java'
id 'application'
}
// Replace with the package version of the API you need
def krakenApiVersion = 'X.Y.Z'
allprojects {
apply plugin: 'java'
repositories {
maven { url 'https://jitpack.io' }
}
}
dependencies {
compileOnly group: 'com.github.cbartram', name:'kraken-api', version: krakenApiVersion
// ... other dependencies
}To use the API jar file in your plugin project you will need to either:
export GITHUB_ACTOR=<YOUR_GITHUB_USERNAME>; export GITHUB_TOKEN=<GITHUB_PAT- or add the following to your
gradle.propertiesfile:gpr.user=your-github-username gpr.key=your-personal-access-token
More information on generating a GitHub Personal Access token can be found below.
Since the API packages are hosted on GitHub Packages you will need to generate a Personal Access Token (PAT) on GitHub to authenticate and pull down the API.
You can generate a GitHub PAT by navigating to your GitHub Settings and clicking "Generate new Token." Give the token a unique name and optional description with read-only access to public repositories. Store the token in a safe place as it won't be viewable again. It can be used to authenticate to GitHub and pull Kraken API packages.
β οΈ Do NOT share this token with anyone.
plugins {
id 'java'
id 'application'
}
// Replace with the package version of the API you need
def krakenApiVersion = 'X.Y.Z'
allprojects {
apply plugin: 'java'
repositories {
// You must declare this maven repository to be able to search and pull Kraken API packages
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/cbartram/kraken-api")
credentials {
username = project.findProperty("gpr.user") ?: System.getenv("GITHUB_ACTOR")
password = project.findProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN")
}
}
// Jitpack is an alternative means of accessing the API Jar file
maven { url 'https://jitpack.io' }
}
}
dependencies {
compileOnly group: 'com.github.cbartram', name:'kraken-api', version: krakenApiVersion
implementation group: 'com.github.cbartram', name:'shortest-path', version: '1.0.3'
// ... other dependencies
}When the API starts it will dynamically parse necessary client methods to determine which methods are used to send packets. These methods are then invoked via reflection to actually send client packets to the OSRS servers. This enables the API to use network packets to communicate directly with OSRS servers and facilitate automatic interactions with the game client.
The core packet logic was originally written and used by the Packet Utils plugin found here. A good portion of the code has been re-written to follow best practices (using logs, factory design pattern, removing redundant code, refactoring to an API instead of plugin, etc...) however, the functionality for client analysis and packet ops are sourced from the Packet Utils repository (credit to EthanVann and contributors on the repo for mapping obfuscated class names and packet logic).
The API is broken up into 2 distinct ways of accessing game information:
- Services (
com.kraken.api.service) - Query System (
com.kraken.api.query)
Each API paradigm has its strengths, and it's likely you will need both when building semi and fully autonomous RuneLite plugins. Read more about each API paradigm below to see which one (or a combination of both) suites your plugin needs.
Services leverage the software design pattern of dependency injection. This is the exact same pattern adopted by RuneLite to ensure that plugins get exactly what they need to run from RuneLite and nothing more. As the developer you will declare to your script what you need from the Kraken API and the dependencies will be directly injected into your script at runtime. Dependency injection ensures that your script classes remain lightweight, testable, and easy to debug.
The Service API paradigm is useful for static widgets or global game entities, for example:
- Bank interface - There is only a single bank interface to open, close, and set withdrawal modes on
- Prayers - A finite amount of static prayer widgets
- Spells - A fixed amount of in-game spells
- UI - Static utilities for calculating UI element bounds
- Camera - A single camera exists and is centered around your local player (
ctx.cameras().first()doesn't really make much sense!) - etc...
If you needed to toggle a prayer, cast a spell, or close the bank then the service API paradigm would suite your plugin well.
The query system allows you to flexibly "query", refine, and filter for dynamic game entities like:
- Players
- NPC's
- Game objects
- Ground Items
- Widgets
- Worn equipment (in the interface as well as your inventory)
- Inventory items
- and Bank items
The query paradigm wraps familiar RuneLite API objects with an Interactable interface allowing you to not
only find game entities but also interact with them in a straightforward fashion.
All interactions use network packets to communicate directly with the game servers.
The API utilizes method chaining to filter for specific game entities loaded within the scene and exposes all methods on the underlying RuneLite
API objects using the raw() method on every wrapped game entity class.
The entire query API is exposed through a single class called the game Context.
This singleton class allows you to have one lightweight dependency which functions as a facade to query just about any game entity you would want for plugin development.
For example, to attack a nearby Goblin:
@PluginDescriptor(
name = "Example",
description = "Example plugin"
)
public class ExamplePlugin extends Plugin {
@Inject
private Context ctx;
@Subscribe
private void onGameTick(GameTick e) {
Player local = ctx.players().local().raw();
if(local.isInteracting()) {
return;
}
ctx.npcs().withName("Goblin")
.except(n -> n.raw().isInteracting())
.nearest()
.interact("Attack");
}
}The entire query API is designed to be thread safe so any queries, filters, or interactions can be run on non-client threads. When callable methods need to execute on RuneLite's client thread they will be scheduled there, blocking until the method executes. This helps ensure your plugin code is fully thread safe, predictable, and easy to read.
To see specific examples of various queries check out the API tests which utilize a real RuneLite plugin to query and find various game entities around Varrock east bank.
β οΈ When running on non-client threads the action must be scheduled on the client thread and is thus asynchronous in nature.
The Kraken API exposes both high and low level functions for working with game objects, NPC's, movement, pathing, simulations, network packets and more. The documentation below describes the most likely packages developers will use when writing scripts or plugins.
core- The package contains abstract base class logic which is used internally by different API methods and exposes theScriptclass.core.packet- The package includes low and high level API's to send network packets to game servers for automation actions.core.packet.entity- Generally most packet layer use cases will use thecore.packet.entityAPI for interaction with Game Objects, NPC's, interfaces, and players.
service- The package contains high level API's for directly interacting with static/global game elements such as (banking, prayer, spells, etc...) and use thecore.packetpackage to form the backbone for the interactionsquery- Contains the query API classes for finding and interacting with dynamic game elements like: inventory, npcs, players, game objects and more.overlay- Contains simple and common overlays which can be directly used in RuneLite plugins e.g. Mouse positionsim- Includes classes for simulating game ticks, NPC pathing, movement, line of sight, and players. This is useful for advanced plugins which evaluate hundreds of potential outcomes every game tick to determine the best "decision". e.g. Inferno and Colosseum plugins
For more information on writing scripts using the Kraken API check out the detailed scripting guide.
Game updates (especially new revisions) can quickly break a lot of the packet and interaction functionality in the API.
Since the packet functionality is based on the PacketUtils repository this API
is constrained to the time it takes their developers to run their update and mapping process to generate a new ObfuscatedNames.java
file.
This file maps specific fields, methods, values, and classes from the obfuscated game client to be used in order to send packets and provide much of the API's functionality correctly. The core packet logic was originally written and used by the Packet Utils plugin found here. A good portion of the code has been re-written to follow best practices (using logs, factory pattern, removing redundant code, refactoring to a library instead of plugin, etc...) however, the functionality for client analysis, obfuscated class names, and packet ops are sourced from the Packet Utils repository (credit to EthanVann and contributors on the repo for mapping obfuscated class names and packet logic).
- Check the PRs for the Packet Utils repository.
- Once the new
ObfuscatedNamesis updated copy the contents of the file intocore.packets.ObfuscatedNames - Run a build to make sure everything compiles
- Run the example plugin to make sure packets still function correctly and the right packet class can be located for the RuneLite version and revision
- Commit and open a PR to build a new version of the API
This project is unique in that it functions exclusively within a RuneLite game client environment. This means that automated tests through a framework like JUnit don't provide as much value. Sure, you can test functionality within the API but does is really find NPC's within 10 tiles of your player? The only way to know for sure is to run tests within the game client.
You can run tests by running the main class in ExamplePluginTest.java. This will launch a new game client which loads a custom "Testing" plugin
called "API Tests" which you will see within RuneLite. Through this plugin you can run specific tests which cover various query and service related classes
and dump output into the console for PASS/FAIL.
Most of the tests are fully self-sufficient, that is, they set themselves up with the necessary in game items before running the tests. However, there are a few conditions:
- The tests are designed to be run from Varrock West Bank where nearby "Guard" NPCs are present.
- Rune Full Helm, Platebody, Platelegs, and Scimitar must be present in your bank
- Lobster and Swordfish must be present in your bank
- Law, fire, and air runes must be present within your bank
- Protect from Melee prayer must be unlocked
- Must be on the standard spellbook
- Player tests require a nearby player and it will "follow" them
- Create a new branch from
master - Implement or update your plugin/feature for the API
- Add tests for new functionality
- Run
./gradlew buildto verify that the API builds and tests pass - Commit your changes with a clear message
git commit -m "feat(api): Add feature X to Kraken API" - Open a Pull Request
The Kraken API is automatically built and deployed via GitHub actions on every push to the master branch.
The latest version can be found in the releases section of the repository.
The deployment is fully automated and consists of:
- Building the API JAR
- Publishing a new version to the GitHub Releases section
- This will be picked up by Github Packages for easy integration into other gradle projects.
- Uploading the JAR file to the Minio storage server used by the Kraken Client at runtime.
Please read CONTRIBUTING.md for details on our code of conduct and the process for submitting pull requests.
We use Semantic Versioning. See the tags on this repository for available releases.
CI will automatically bump the patch version on each merge to master i.e. 1.1.4 -> 1.1.5. If you want to bump
a minor or major version then update the version.txt file in the root of the repository with the new version you
want to use as a base.
For example, moving from version: 1.3.5 -> 1.4.0 the version.txt should be 1.4.0.
This project is licensed under the GNU General Public License 3.0.
- RuneLite β For API's to work with and view in game data for Old School RuneScape
- Packet Utils - Plugin from Ethan Vann providing access to complex packet sending functionality which was used to develop the
core.packetpackage of the API - Microbot β For clever ideas on client and plugin interaction.