Skip to content
Open
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
21 changes: 21 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,24 @@ target/*
.lsp/*

output/*

# Claude Code
.claude/

# Debug / decompilation artifacts
*.log
data/
RuneLite_parent_decompiled.java
clientui_bytecode.txt
clientui_decompile.txt
clientui_out.txt
rl_decompile_full.txt
rl_err.txt
rl_full.txt
runelite_bytecode.txt
runelite_decompile.txt
runelite_err.txt
runelite_parent_bytecode.txt

# Scripts
start-script.sh
Binary file modified OSRSBot.jar
Binary file not shown.
9 changes: 7 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ dependencies {
implementation group: 'org.clojure', name: 'clojure', version: '1.9.0'
implementation group: 'org.clojure', name: 'tools.nrepl', version: '0.2.12'
implementation group: 'net.runelite', name: 'client', version: runeLiteVersion
implementation group: 'net.runelite', name: 'cache', version: runeLiteVersion
implementation(group: 'net.runelite', name: 'cache', version: runeLiteVersion) {
exclude group: 'org.slf4j', module: 'slf4j-simple'
}
implementation 'org.projectlombok:lombok:1.18.24'
annotationProcessor 'org.projectlombok:lombok:1.18.24'

Expand All @@ -56,7 +58,7 @@ dependencies {
exclude group: 'ch.qos.logback', module: 'logback-classic'
}

implementation 'com.github.OSRSB:OSRSBPlugin:main-SNAPSHOT'
// implementation 'com.github.OSRSB:OSRSBPlugin:main-SNAPSHOT' // JitPack can't resolve
implementation group: 'com.github.joonasvali.naturalmouse', name: 'naturalmouse', version: '2.0.3'
implementation group: 'javassist', name: 'javassist', version: '3.12.1.GA'
implementation group: 'net.sf.jopt-simple', name:'jopt-simple', version: '5.0.4'
Expand All @@ -67,6 +69,9 @@ sourceSets {
java {
srcDirs= ["src/main/java"]
}
resources {
srcDirs= ["src/main/resources"]
}
}
}

Expand Down
56 changes: 56 additions & 0 deletions launch-bot.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
@echo off
REM ============================================================
REM OsrsBot Launcher with Jagex Authentication Support
REM ============================================================
REM
REM FIRST-TIME SETUP (one-time only):
REM 1. Open "RuneLite (configure)" from Start Menu
REM (or manually edit %LOCALAPPDATA%\RuneLite\settings.json)
REM 2. In "Client arguments", add: --insecure-write-credentials
REM 3. Open Jagex Launcher and click Play OSRS (RuneLite)
REM 4. Log in to your account, then close RuneLite
REM 5. Verify %USERPROFILE%\.runelite\credentials.properties exists
REM 6. Remove --insecure-write-credentials from client arguments
REM 7. Now you can run this script to launch the bot!
REM
REM Tokens persist until you click "End sessions" on runescape.com
REM ============================================================

set JAVA_HOME=C:\Program Files\Eclipse Adoptium\jdk-17.0.18.8-hotspot
set JAVA="%JAVA_HOME%\bin\java.exe"

if not exist %JAVA% (
echo ERROR: Java 17 not found at %JAVA_HOME%
echo Please install Eclipse Adoptium JDK 17
pause
exit /b 1
)

REM Load Jagex credentials as environment variables so the game client
REM can authenticate via System.getenv("JX_ACCESS_TOKEN") etc.
set CREDS=%USERPROFILE%\.runelite\credentials.properties
if exist "%CREDS%" (
echo Loading Jagex credentials from %CREDS%
for /f "usebackq tokens=1,* delims==" %%a in ("%CREDS%") do (
REM Skip comments (lines starting with #)
echo %%a | findstr /b "#" >nul 2>&1
if errorlevel 1 (
set "%%a=%%b"
echo Set env: %%a
)
)
) else (
echo WARNING: No credentials.properties found!
echo.
echo You need to set up Jagex authentication first:
echo 1. Open "RuneLite (configure)" from Start Menu
echo 2. Add --insecure-write-credentials to "Client arguments"
echo 3. Launch RuneLite via Jagex Launcher and log in
echo 4. Close RuneLite, then run this script again
echo.
echo Launching without credentials - you may not be able to log in...
echo.
)

cd /d "%~dp0"
%JAVA% -Xmx2g -XX:ReservedCodeCacheSize=512m -XX:HeapBaseMinAddress=0x10000000 -jar OSRSBot.jar --bot-runelite --developer-mode %*
59 changes: 59 additions & 0 deletions launch-bot.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/bin/bash
# ============================================================
# OsrsBot Launcher with Jagex Authentication Support
# ============================================================
#
# FIRST-TIME SETUP (one-time only):
# 1. Open "RuneLite (configure)" from Start Menu
# (or manually edit %LOCALAPPDATA%\RuneLite\settings.json)
# 2. In "Client arguments", add: --insecure-write-credentials
# 3. Open Jagex Launcher and click Play OSRS (RuneLite)
# 4. Log in to your account, then close RuneLite
# 5. Verify ~/.runelite/credentials.properties exists
# 6. Remove --insecure-write-credentials from client arguments
# 7. Now you can run this script!
#
# Tokens persist until you click "End sessions" on runescape.com
# ============================================================

export JAVA_HOME="/c/Program Files/Eclipse Adoptium/jdk-17.0.18.8-hotspot"
JAVA="$JAVA_HOME/bin/java.exe"

if [ ! -f "$JAVA" ]; then
echo "ERROR: Java 17 not found at $JAVA_HOME"
exit 1
fi

# Load Jagex credentials as environment variables so the game client
# can authenticate via System.getenv("JX_ACCESS_TOKEN") etc.
CREDS="$HOME/.runelite/credentials.properties"
if [ -f "$CREDS" ]; then
echo "Loading Jagex credentials from $CREDS"
while IFS='=' read -r key value; do
# Skip comments and blank lines
case "$key" in
\#*|"") continue ;;
esac
# Trim whitespace
key=$(echo "$key" | xargs)
value=$(echo "$value" | xargs)
if [ -n "$key" ] && [ -n "$value" ]; then
export "$key=$value"
echo " Set env: $key"
fi
done < "$CREDS"
else
echo "WARNING: No credentials.properties found at $CREDS"
echo ""
echo "You need to set up Jagex authentication first:"
echo " 1. Open 'RuneLite (configure)' from Start Menu"
echo " 2. Add --insecure-write-credentials to 'Client arguments'"
echo " 3. Launch RuneLite via Jagex Launcher and log in"
echo " 4. Close RuneLite, then run this script again"
echo ""
echo "Launching without credentials - you may not be able to log in..."
echo ""
fi

cd "$(dirname "$0")"
"$JAVA" -Xmx2g -XX:ReservedCodeCacheSize=512m -XX:HeapBaseMinAddress=0x10000000 -jar OSRSBot.jar --bot-runelite --developer-mode "$@"
Binary file added scripts/osrsbot-learning-0.1.0-SNAPSHOT.jar
Binary file not shown.
14 changes: 3 additions & 11 deletions src/main/java/net/runelite/client/modified/BotModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import com.google.inject.binder.ConstantBindingBuilder;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
import java.applet.Applet;
import java.io.File;
import java.util.Map;
import java.util.Properties;
Expand Down Expand Up @@ -47,7 +46,7 @@
public class BotModule extends AbstractModule {

private final OkHttpClient okHttpClient;
private final Supplier<Applet> clientLoader;
private final Supplier<Client> clientLoader;
private final RuntimeConfigLoader configSupplier;
private final boolean developerMode;
private final boolean safeMode;
Expand All @@ -60,7 +59,7 @@ public class BotModule extends AbstractModule {
private final boolean noupdate = false;


public BotModule(OkHttpClient okHttpClient, Supplier<Applet> clientLoader, RuntimeConfigLoader configSupplier, boolean developerMode, boolean safeMode, File sessionfile, File config) {
public BotModule(OkHttpClient okHttpClient, Supplier<Client> clientLoader, RuntimeConfigLoader configSupplier, boolean developerMode, boolean safeMode, File sessionfile, File config) {
this.okHttpClient = okHttpClient;
this.clientLoader = clientLoader;
this.configSupplier = configSupplier;
Expand Down Expand Up @@ -142,18 +141,11 @@ else if (entry.getValue() instanceof Double)

@Provides
@Singleton
Applet provideApplet()
Client provideClient()
{
return clientLoader.get();
}

@Provides
@Singleton
Client provideClient(@Nullable Applet applet)
{
return applet instanceof Client ? (Client) applet : null;
}

@Provides
@Singleton
RuntimeConfig provideRuntimeConfig()
Expand Down
67 changes: 36 additions & 31 deletions src/main/java/net/runelite/client/modified/RuneLite.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import com.google.inject.Inject;
import com.google.inject.Injector;

import java.applet.Applet;
import java.io.File;
import java.io.IOException;
import java.lang.management.ManagementFactory;
Expand All @@ -35,7 +34,6 @@
import javax.swing.*;

import joptsimple.*;
import joptsimple.util.EnumConverter;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.*;
Expand All @@ -49,7 +47,6 @@
import net.runelite.client.game.WorldService;
import net.runelite.client.plugins.PluginManager;
import net.runelite.client.rs.ClientLoader;
import net.runelite.client.rs.ClientUpdateCheckMode;
import net.runelite.client.ui.FontManager;
import net.runelite.client.ui.overlay.WidgetOverlay;
import net.runelite.rsb.botLauncher.BotLite;
Expand Down Expand Up @@ -124,10 +121,6 @@ public class RuneLite extends net.runelite.client.RuneLite {
@Nullable
public Client client;

@Inject
@Nullable
public Applet applet;

@Inject
@Nullable
private RuntimeConfig runtimeConfig;
Expand Down Expand Up @@ -175,23 +168,11 @@ public static ArgumentAcceptingOptionSpec<?>[] handleParsing(OptionParser parser
.withValuesConvertedBy(new ConfigFileConverter())
.defaultsTo(DEFAULT_CONFIG_FILE);

final ArgumentAcceptingOptionSpec<ClientUpdateCheckMode> updateMode = parser
.accepts("rs", "Select client type")
.withRequiredArg()
.ofType(ClientUpdateCheckMode.class)
.defaultsTo(ClientUpdateCheckMode.AUTO)
.withValuesConvertedBy(new EnumConverter<>(ClientUpdateCheckMode.class) {
@Override
public ClientUpdateCheckMode convert(String v) {
return super.convert(v.toUpperCase());
}
});

final ArgumentAcceptingOptionSpec<String> proxyInfo = parser
.accepts("proxy", "Designates a proxy ip address to be used to make the bot server connections")
.withRequiredArg().ofType(String.class);

return (ArgumentAcceptingOptionSpec<?>[]) new ArgumentAcceptingOptionSpec[]{sessionfile, configfile, updateMode, proxyInfo};
return (ArgumentAcceptingOptionSpec<?>[]) new ArgumentAcceptingOptionSpec[]{sessionfile, configfile, proxyInfo};
}

/**
Expand Down Expand Up @@ -260,7 +241,6 @@ public static void initializeClient(ArgumentAcceptingOptionSpec<?>[] optionSpecs
{
final RuntimeConfigLoader runtimeConfigLoader = new RuntimeConfigLoader(okHttpClient);
final ClientLoader clientLoader = new ClientLoader(okHttpClient,
options.valueOf(optionSpecs[Options.UPDATE_MODE.getIndex()].ofType(ClientUpdateCheckMode.class)),
runtimeConfigLoader,
(String) options.valueOf("jav_config"));

Expand All @@ -277,7 +257,7 @@ public static void initializeClient(ArgumentAcceptingOptionSpec<?>[] optionSpecs

injector = Guice.createInjector(new BotModule(
okHttpClient,
clientLoader,
clientLoader::get,
runtimeConfigLoader,
options.has("developer-mode"),
false,
Expand Down Expand Up @@ -319,25 +299,20 @@ public void bareStart() throws Exception {
injector.injectMembers(client);
}

// Start the applet
if (applet != null)
// Initialize the client via GameEngine API
if (client != null)
{
// Client size must be set prior to init
applet.setSize(Constants.GAME_FIXED_SIZE);

System.setProperty("jagex.disableBouncyCastle", "true");
// Change user.home so the client places jagexcache in the .runelite directory
String oldHome = System.setProperty("user.home", RUNELITE_DIR.getAbsolutePath());
try
{
applet.init();
client.initialize();
}
finally
{
System.setProperty("user.home", oldHome);
}

applet.start();
}

// Load user configuration
Expand Down Expand Up @@ -367,6 +342,36 @@ public void bareStart() throws Exception {
}
}

/**
* Overrides parent RuneLite.start() to fix sidebar initialization order.
* The parent's start() loads and starts plugins BEFORE calling clientUI.init(),
* which causes NPEs when plugins try to add navigation buttons to a null sidebar.
* This override ensures the sidebar is created first via bareStart(), then loads
* and starts plugins, then shows the UI.
*/
@Override
public void start() throws Exception {
// Step 1: Client init, config loading, sidebar creation (clientUI.init())
bareStart();

// Step 2: Load plugins — sidebar now exists for addNavigation calls
pluginManager.loadCorePlugins();
pluginManager.loadSideLoadPlugins();
externalPluginManager.loadExternalPlugins();
pluginManager.loadDefaultPluginConfiguration(null);

// Step 3: Start plugins — startUp() calls addNavigation safely now
pluginManager.startPlugins();

// Step 4: Discord, show UI, unblock client
discordService.init();
eventBus.register(discordService);
clientUI.show();
if (client != null) {
client.unblockStartup();
}
}

/**
* RuneLite method
* Converts config files paths to whatever directory needed
Expand Down Expand Up @@ -527,7 +532,7 @@ private void setupSystemProps()
* The values assigned are their positions within the relating ArgumentAcceptingOptionSpec array
*/
enum Options {
SESSION_FILE(0),CONFIG_FILE(1), UPDATE_MODE(2), PROXY_INFO(3);
SESSION_FILE(0), CONFIG_FILE(1), PROXY_INFO(2);

private int index;

Expand Down
Loading