Merge branch 'master' into externalserror1

This commit is contained in:
Tyler Bochard
2020-03-12 22:33:30 -04:00
committed by GitHub
96 changed files with 2094 additions and 2758 deletions
+13 -2
View File
@@ -16,9 +16,17 @@ jobs:
with: with:
title-regex: '^([\w-/]+): \w+' title-regex: '^([\w-/]+): \w+'
build: validate:
name: Validate gradle wrapper
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: gradle/wrapper-validation-action@v1
build:
name: Build name: Build
needs: [pr-lint, validate]
runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
@@ -40,8 +48,9 @@ jobs:
run: ./gradlew build --stacktrace -x test -x checkstyleMain -x checkstyleTest --console=plain run: ./gradlew build --stacktrace -x test -x checkstyleMain -x checkstyleTest --console=plain
test: test:
runs-on: ubuntu-latest
name: Test name: Test
needs: [pr-lint, validate]
runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
@@ -64,6 +73,7 @@ jobs:
checkstyleMain: checkstyleMain:
name: Checkstyle main name: Checkstyle main
needs: [pr-lint, validate]
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
@@ -87,6 +97,7 @@ jobs:
checkstyleTest: checkstyleTest:
name: Checkstyle test name: Checkstyle test
needs: [pr-lint, validate]
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
-1
View File
@@ -19,4 +19,3 @@ jobs:
exempt-issue-label: 'awaiting-approval' exempt-issue-label: 'awaiting-approval'
exempt-pr-label: 'awaiting-approval' exempt-pr-label: 'awaiting-approval'
days-before-stale: 60 days-before-stale: 60
days-before-close: 30
+2 -1
View File
@@ -58,7 +58,7 @@ fun isNonStable(version: String): Boolean {
allprojects { allprojects {
group = "com.openosrs" group = "com.openosrs"
version = ProjectVersions.rlVersion version = ProjectVersions.openosrsVersion
apply<MavenPublishPlugin>() apply<MavenPublishPlugin>()
} }
@@ -90,6 +90,7 @@ subprojects {
} }
filter { filter {
includeModule("net.runelite", "fernflower") includeModule("net.runelite", "fernflower")
includeModule("com.openosrs.rxrelay3", "rxrelay")
} }
} }
} }
+3 -3
View File
@@ -44,10 +44,10 @@ open class BootstrapTask @Inject constructor(@Input val type: String) : DefaultT
val version = splat[2] val version = splat[2]
lateinit var path: String lateinit var path: String
if (it.file.name.contains(ProjectVersions.rlVersion)) { if (it.file.name.contains(ProjectVersions.openosrsVersion)) {
path = "https://github.com/open-osrs/hosting/raw/master/${type}/${it.file.name}" path = "https://github.com/open-osrs/hosting/raw/master/${type}/${it.file.name}"
} else if (it.file.name.contains("injection-annotations")) { } else if (it.file.name.contains("injection-annotations") || it.file.name.contains("rxrelay")) {
path = "https://github.com/open-osrs/hosting/raw/master/" + group.replace(".", "/") + "/${name}/$version/${it.file.name}" path = "https://github.com/open-osrs/hosting/raw/master/" + group.replace(".", "/") + "/${name}/$version/${it.file.name}"
} else if (!group.contains("runelite")) { } else if (!group.contains("runelite")) {
path = "https://repo.maven.apache.org/maven2/" + group.replace(".", "/") + "/${name}/$version/${name}-$version" path = "https://repo.maven.apache.org/maven2/" + group.replace(".", "/") + "/${name}/$version/${name}-$version"
if (it.classifier != null && it.classifier != "no_aop") { if (it.classifier != null && it.classifier != "no_aop") {
+21 -23
View File
@@ -25,9 +25,9 @@
object ProjectVersions { object ProjectVersions {
const val launcherVersion = "2.0.4" const val launcherVersion = "2.0.4"
const val rlVersion = "1.6.8" const val rlVersion = "1.6.9"
const val openosrsVersion = "3.0.6" const val openosrsVersion = "3.1.0"
const val rsversion = 188 const val rsversion = 188
const val cacheversion = 165 const val cacheversion = 165
@@ -47,12 +47,12 @@ object Plugins {
object Libraries { object Libraries {
private object Versions { private object Versions {
const val annotations = "18.0.0" const val annotations = "19.0.0"
const val antlr = "4.7.2" const val antlr = "4.8-1"
const val apacheCommonsCompress = "1.19" const val apacheCommonsCompress = "1.20"
const val apacheCommonsCsv = "1.7" const val apacheCommonsCsv = "1.8"
const val apacheCommonsText = "1.8" const val apacheCommonsText = "1.8"
const val asm = "7.2" const val asm = "7.3.1"
const val commonsCli = "1.4" const val commonsCli = "1.4"
const val discord = "1.1" const val discord = "1.1"
const val fernflower = "07082019" const val fernflower = "07082019"
@@ -67,27 +67,26 @@ object Libraries {
const val jna = "5.5.0" const val jna = "5.5.0"
const val jogamp = "2.3.2" const val jogamp = "2.3.2"
const val jopt = "5.0.4" const val jopt = "5.0.4"
const val jooq = "3.12.3" const val jooq = "3.13.0"
const val junit = "4.13" const val junit = "4.13"
const val jupiter = "5.6.0-M1" const val jupiter = "5.6.0"
const val logback = "1.2.3" const val logback = "1.2.3"
const val lombok = "1.18.10" const val lombok = "1.18.12"
const val mavenPluginAnnotations = "3.6.0" const val mavenPluginAnnotations = "3.6.0"
const val mavenPluginApi = "3.6.3" const val mavenPluginApi = "3.6.3"
const val mockito = "3.2.4" const val mockito = "3.3.1"
const val naturalMouse = "2.0.2" const val netty = "4.1.45.Final"
const val netty = "4.1.44.Final" const val okhttp3 = "4.4.0"
const val okhttp3 = "4.3.0"
const val orangeExtensions = "1.0" const val orangeExtensions = "1.0"
const val petitparser = "2.3.1" const val petitparser = "2.3.1"
const val pf4j = "3.2.0" const val pf4j = "3.2.0"
const val pf4jUpdate = "2.2.0" const val pf4jUpdate = "2.3.0"
const val plexus = "3.3.0"
const val radiance = "2.5.1" const val radiance = "2.5.1"
const val rxjava = "2.2.16" const val rxjava = "3.0.0"
const val rxrelay = "2.1.1" const val rxrelay = "3.0.0-SNAPSHOT"
const val sisu = "0.3.4" const val sisu = "0.3.4"
const val sentry = "1.7.29" const val sentry = "1.7.30"
const val semver = "0.9.0"
const val slf4j = "1.7.30" const val slf4j = "1.7.30"
} }
@@ -135,7 +134,6 @@ object Libraries {
const val mavenPluginApi = "org.apache.maven:maven-plugin-api:${Versions.mavenPluginApi}" const val mavenPluginApi = "org.apache.maven:maven-plugin-api:${Versions.mavenPluginApi}"
const val mockitoCore = "org.mockito:mockito-core:${Versions.mockito}" const val mockitoCore = "org.mockito:mockito-core:${Versions.mockito}"
const val mockitoInline = "org.mockito:mockito-inline:${Versions.mockito}" const val mockitoInline = "org.mockito:mockito-inline:${Versions.mockito}"
const val naturalMouse = "com.github.joonasvali.naturalmouse:naturalmouse:${Versions.naturalMouse}"
const val nettyBuffer = "io.netty:netty-buffer:${Versions.netty}" const val nettyBuffer = "io.netty:netty-buffer:${Versions.netty}"
const val okhttp3 = "com.squareup.okhttp3:okhttp:${Versions.okhttp3}" const val okhttp3 = "com.squareup.okhttp3:okhttp:${Versions.okhttp3}"
const val okhttp3Webserver = "com.squareup.okhttp3:mockwebserver:${Versions.okhttp3}" const val okhttp3Webserver = "com.squareup.okhttp3:mockwebserver:${Versions.okhttp3}"
@@ -143,14 +141,14 @@ object Libraries {
const val petitparser = "com.github.petitparser:java-petitparser:${Versions.petitparser}" const val petitparser = "com.github.petitparser:java-petitparser:${Versions.petitparser}"
const val pf4j = "org.pf4j:pf4j:${Versions.pf4j}" const val pf4j = "org.pf4j:pf4j:${Versions.pf4j}"
const val pf4jUpdate = "org.pf4j:pf4j-update:${Versions.pf4jUpdate}" const val pf4jUpdate = "org.pf4j:pf4j-update:${Versions.pf4jUpdate}"
const val plexus = "org.codehaus.plexus:plexus-utils:${Versions.plexus}" const val rxjava = "io.reactivex.rxjava3:rxjava:${Versions.rxjava}"
const val rxjava = "io.reactivex.rxjava2:rxjava:${Versions.rxjava}" const val rxrelay = "com.openosrs.rxrelay3:rxrelay:${Versions.rxrelay}"
const val rxrelay = "com.jakewharton.rxrelay2:rxrelay:${Versions.rxrelay}"
const val sisu = "org.eclipse.sisu:org.eclipse.sisu.inject:${Versions.sisu}" const val sisu = "org.eclipse.sisu:org.eclipse.sisu.inject:${Versions.sisu}"
const val slf4jApi = "org.slf4j:slf4j-api:${Versions.slf4j}" const val slf4jApi = "org.slf4j:slf4j-api:${Versions.slf4j}"
const val slf4jNop = "org.slf4j:slf4j-nop:${Versions.slf4j}" const val slf4jNop = "org.slf4j:slf4j-nop:${Versions.slf4j}"
const val slf4jSimple = "org.slf4j:slf4j-simple:${Versions.slf4j}" const val slf4jSimple = "org.slf4j:slf4j-simple:${Versions.slf4j}"
const val sentry = "io.sentry:sentry:${Versions.sentry}" const val sentry = "io.sentry:sentry:${Versions.sentry}"
const val semver = "com.github.zafarkhaja:java-semver:${Versions.semver}"
const val substance = "org.pushing-pixels:radiance-substance:${Versions.radiance}" const val substance = "org.pushing-pixels:radiance-substance:${Versions.radiance}"
const val trident = "org.pushing-pixels:radiance-trident:${Versions.radiance}" const val trident = "org.pushing-pixels:radiance-trident:${Versions.radiance}"
const val vanilla = "net.runelite.rs:vanilla:${ProjectVersions.rsversion}" const val vanilla = "net.runelite.rs:vanilla:${ProjectVersions.rsversion}"
@@ -35,8 +35,8 @@ public class KitDefinition
public short[] retextureToFind; public short[] retextureToFind;
public short[] retextureToReplace; public short[] retextureToReplace;
public int bodyPartId = -1; public int bodyPartId = -1;
public int[] modelIds; public int[] models;
public int[] models = new int[] public int[] chatheadModels = new int[]
{ {
-1, -1, -1, -1, -1 -1, -1, -1, -1, -1
}; };
@@ -53,11 +53,11 @@ public class KitLoader
else if (opcode == 2) else if (opcode == 2)
{ {
int length = is.readUnsignedByte(); int length = is.readUnsignedByte();
def.modelIds = new int[length]; def.models = new int[length];
for (int index = 0; index < length; ++index) for (int index = 0; index < length; ++index)
{ {
def.modelIds[index] = is.readUnsignedShort(); def.models[index] = is.readUnsignedShort();
} }
} }
else if (opcode == 3) else if (opcode == 3)
@@ -90,7 +90,7 @@ public class KitLoader
} }
else if (opcode >= 60 && opcode < 70) else if (opcode >= 60 && opcode < 70)
{ {
def.models[opcode - 60] = is.readShort(); def.chatheadModels[opcode - 60] = is.readUnsignedShort();
} }
} }
+1 -1
View File
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.2.1-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-6.2.2-all.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
@@ -64,7 +64,6 @@ public class RuneLiteAPI
private static final String WSBASE = "https://api.runelite.net/ws"; private static final String WSBASE = "https://api.runelite.net/ws";
private static final String STATICBASE = "https://static.runelite.net"; private static final String STATICBASE = "https://static.runelite.net";
private static final String OPENOSRS_BASE = /*"https://api.openosrs.com*/ "https://api.runelitepl.us";
private static final String OPENOSRS_SESSION = "http://session.openosrs.dev"; private static final String OPENOSRS_SESSION = "http://session.openosrs.dev";
private static final String OPENOSRS_XTEA = "http://xtea.openosrs.dev"; private static final String OPENOSRS_XTEA = "http://xtea.openosrs.dev";
private static final String OPENOSRS_ANIMATIONS = "http://animations.openosrs.dev"; private static final String OPENOSRS_ANIMATIONS = "http://animations.openosrs.dev";
@@ -151,11 +150,6 @@ public class RuneLiteAPI
return HttpUrl.parse(BASE + "/runelite-" + getVersion()); return HttpUrl.parse(BASE + "/runelite-" + getVersion());
} }
public static HttpUrl getOpenOSRSApiBase()
{
return HttpUrl.parse(OPENOSRS_BASE + "/http-service-" + getRlpVersion());
}
public static HttpUrl getStaticBase() public static HttpUrl getStaticBase()
{ {
final String prop = System.getProperty("runelite.static.url"); final String prop = System.getProperty("runelite.static.url");
@@ -25,7 +25,7 @@
package net.runelite.http.api.account; package net.runelite.http.api.account;
import com.google.gson.JsonParseException; import com.google.gson.JsonParseException;
import io.reactivex.Observable; import io.reactivex.rxjava3.core.Observable;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
@@ -27,8 +27,6 @@ package net.runelite.http.api.chat;
import com.google.gson.JsonParseException; import com.google.gson.JsonParseException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import net.runelite.http.api.RuneLiteAPI; import net.runelite.http.api.RuneLiteAPI;
import okhttp3.HttpUrl; import okhttp3.HttpUrl;
@@ -40,9 +38,6 @@ public class ChatClient
{ {
private static final RequestBody body = RequestBody.Companion.create(new byte[0], null); private static final RequestBody body = RequestBody.Companion.create(new byte[0], null);
private static final Predicate<String> LAYOUT_VALIDATOR = Pattern
.compile("\\[[A-Z]+]:(\\s*\\w+\\s*(\\([A-Za-z]+\\))?,?)+")
.asPredicate();
public boolean submitKc(String username, String boss, int kc) throws IOException public boolean submitKc(String username, String boss, int kc) throws IOException
{ {
@@ -56,7 +51,7 @@ public class ChatClient
Request request = new Request.Builder() Request request = new Request.Builder()
.post(body) .post(RequestBody.create(null, new byte[0]))
.url(url) .url(url)
.build(); .build();
@@ -99,7 +94,7 @@ public class ChatClient
.build(); .build();
Request request = new Request.Builder() Request request = new Request.Builder()
.post(body) .post(RequestBody.create(null, new byte[0]))
.url(url) .url(url)
.build(); .build();
@@ -144,7 +139,7 @@ public class ChatClient
.build(); .build();
Request request = new Request.Builder() Request request = new Request.Builder()
.post(body) .post(RequestBody.create(null, new byte[0]))
.url(url) .url(url)
.build(); .build();
@@ -193,7 +188,7 @@ public class ChatClient
.build(); .build();
Request request = new Request.Builder() Request request = new Request.Builder()
.post(body) .post(RequestBody.create(null, new byte[0]))
.url(url) .url(url)
.build(); .build();
@@ -236,7 +231,7 @@ public class ChatClient
.build(); .build();
Request request = new Request.Builder() Request request = new Request.Builder()
.post(body) .post(RequestBody.create(null, new byte[0]))
.url(url) .url(url)
.build(); .build();
@@ -268,31 +263,6 @@ public class ChatClient
} }
} }
public boolean submitLayout(String username, String layout) throws IOException
{
if (!testLayout(layout))
{
throw new IOException("Layout " + layout + " is not valid!");
}
HttpUrl url = RuneLiteAPI.getOpenOSRSApiBase().newBuilder()
.addPathSegment("chat")
.addPathSegment("layout")
.addQueryParameter("name", username)
.addQueryParameter("layout", layout)
.build();
Request request = new Request.Builder()
.post(body)
.url(url)
.build();
try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute())
{
return response.isSuccessful();
}
}
public boolean submitDuels(String username, int wins, int losses, int winningStreak, int losingStreak) throws IOException public boolean submitDuels(String username, int wins, int losses, int winningStreak, int losingStreak) throws IOException
{ {
HttpUrl url = RuneLiteAPI.getApiBase().newBuilder() HttpUrl url = RuneLiteAPI.getApiBase().newBuilder()
@@ -306,7 +276,7 @@ public class ChatClient
.build(); .build();
Request request = new Request.Builder() Request request = new Request.Builder()
.post(body) .post(RequestBody.create(null, new byte[0]))
.url(url) .url(url)
.build(); .build();
@@ -316,40 +286,6 @@ public class ChatClient
} }
} }
public boolean testLayout(String layout)
{
return LAYOUT_VALIDATOR.test(layout);
}
public House[] getHosts(int world, String location) throws IOException
{
HttpUrl url = RuneLiteAPI.getOpenOSRSApiBase().newBuilder()
.addPathSegment("chat")
.addPathSegment("hosts")
.addQueryParameter("world", Integer.toString(world))
.addQueryParameter("location", location)
.build();
Request request = new Request.Builder()
.url(url)
.build();
try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute())
{
if (!response.isSuccessful())
{
throw new IOException("Unable to look up hosts!");
}
InputStream in = response.body().byteStream();
return RuneLiteAPI.GSON.fromJson(new InputStreamReader(in), House[].class);
}
catch (JsonParseException ex)
{
throw new IOException(ex);
}
}
public Duels getDuels(String username) throws IOException public Duels getDuels(String username) throws IOException
{ {
@@ -379,63 +315,6 @@ public class ChatClient
} }
} }
public boolean submitHost(int world, String location, House house) throws IOException
{
HttpUrl url = RuneLiteAPI.getOpenOSRSApiBase().newBuilder()
.addPathSegment("chat")
.addPathSegment("hosts")
.addQueryParameter("world", Integer.toString(world))
.addQueryParameter("location", location)
.addQueryParameter("owner", house.getOwner())
.addQueryParameter("guildedAltar", Boolean.toString(house.isGuildedAltarPresent()))
.addQueryParameter("occultAltar", Boolean.toString(house.isOccultAltarPresent()))
.addQueryParameter("spiritTree", Boolean.toString(house.isSpiritTreePresent()))
.addQueryParameter("fairyRing", Boolean.toString(house.isFairyRingPresent()))
.addQueryParameter("wildernessObelisk", Boolean.toString(house.isWildernessObeliskPresent()))
.addQueryParameter("repairStand", Boolean.toString(house.isRepairStandPresent()))
.addQueryParameter("combatDummy", Boolean.toString(house.isCombatDummyPresent()))
.build();
Request request = new Request.Builder()
.post(body)
.url(url)
.build();
try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute())
{
return response.isSuccessful();
}
}
public boolean removeHost(int world, String location, House house) throws IOException
{
HttpUrl url = RuneLiteAPI.getOpenOSRSApiBase().newBuilder()
.addPathSegment("chat")
.addPathSegment("hosts")
.addQueryParameter("world", Integer.toString(world))
.addQueryParameter("location", location)
.addQueryParameter("owner", house.getOwner())
.addQueryParameter("guildedAltar", Boolean.toString(house.isGuildedAltarPresent()))
.addQueryParameter("occultAltar", Boolean.toString(house.isOccultAltarPresent()))
.addQueryParameter("spiritTree", Boolean.toString(house.isSpiritTreePresent()))
.addQueryParameter("fairyRing", Boolean.toString(house.isFairyRingPresent()))
.addQueryParameter("wildernessObelisk", Boolean.toString(house.isWildernessObeliskPresent()))
.addQueryParameter("repairStand", Boolean.toString(house.isRepairStandPresent()))
.addQueryParameter("combatDummy", Boolean.toString(house.isCombatDummyPresent()))
.addQueryParameter("remove", Boolean.toString(true))
.build();
Request request = new Request.Builder()
.post(body)
.url(url)
.build();
try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute())
{
return response.isSuccessful();
}
}
public boolean submitLayout(String username, LayoutRoom[] rooms) throws IOException public boolean submitLayout(String username, LayoutRoom[] rooms) throws IOException
{ {
HttpUrl url = RuneLiteAPI.getApiBase().newBuilder() HttpUrl url = RuneLiteAPI.getApiBase().newBuilder()
@@ -27,7 +27,7 @@ package net.runelite.http.api.item;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.gson.JsonParseException; import com.google.gson.JsonParseException;
import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonReader;
import io.reactivex.Observable; import io.reactivex.rxjava3.core.Observable;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@@ -25,7 +25,7 @@
package net.runelite.http.api.osbuddy; package net.runelite.http.api.osbuddy;
import com.google.gson.JsonParseException; import com.google.gson.JsonParseException;
import io.reactivex.Observable; import io.reactivex.rxjava3.core.Observable;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
@@ -37,13 +37,21 @@ public class Hitsplat
public enum HitsplatType public enum HitsplatType
{ {
/** /**
* Blocking damage (blue). * Blocking damage by me (blue).
*/ */
BLOCK, BLOCK_ME,
/** /**
* Taking damage (red). * Blocking damage by others (blue).
*/ */
DAMAGE, BLOCK_OTHER,
/**
* Taking damage by me (red).
*/
DAMAGE_ME,
/**
* Taking damage by others (red).
*/
DAMAGE_OTHER,
/** /**
* Damage from poison (green). * Damage from poison (green).
*/ */
@@ -72,8 +80,10 @@ public class Hitsplat
{ {
switch (type) switch (type)
{ {
case 0: return BLOCK; case 12: return BLOCK_ME;
case 1: return DAMAGE; case 13: return BLOCK_OTHER;
case 16: return DAMAGE_ME;
case 17: return DAMAGE_OTHER;
case 2: return POISON; case 2: return POISON;
case 4: return DISEASE; case 4: return DISEASE;
case 5: return VENOM; case 5: return VENOM;
@@ -57,6 +57,10 @@ public enum InventoryID
* Monkey madness puzzle box inventory. * Monkey madness puzzle box inventory.
*/ */
MONKEY_MADNESS_PUZZLE_BOX(221), MONKEY_MADNESS_PUZZLE_BOX(221),
/**
* Drift net fishing reward
*/
DRIFT_NET_FISHING_REWARD(307),
/** /**
* Looting Bag inventory * Looting Bag inventory
*/ */
@@ -1,5 +1,7 @@
package net.runelite.api; package net.runelite.api;
import javax.annotation.Nullable;
/** /**
* Represents the template of a specific item type. * Represents the template of a specific item type.
*/ */
@@ -127,4 +129,29 @@ public interface ItemDefinition
* @param id The itemID of the item with desired model * @param id The itemID of the item with desired model
*/ */
void setModelOverride(int id); void setModelOverride(int id);
/**
* Gets the model ID of the inventory item.
*
* @return the model ID
*/
int getInventoryModel();
/**
* Since the client reuses item models, it stores colors that can be replaced.
* This returns what colors the item model will be replaced with.
*
* @return the colors to replace with
*/
@Nullable
short[] getColorToReplaceWith();
/**
* Since the client reuses item models, it stores textures that can be replaced.
* This returns what textures the item model will be replaced with.
*
* @return the textures to replace with
*/
@Nullable
short[] getTextureToReplaceWith();
} }
@@ -7347,7 +7347,7 @@ public final class ItemID
public static final int ABSORPTION_2 = 11736; public static final int ABSORPTION_2 = 11736;
public static final int ABSORPTION_1 = 11737; public static final int ABSORPTION_1 = 11737;
public static final int HERB_BOX = 11738; public static final int HERB_BOX = 11738;
public static final int OPENED_HERB_BOX = 11739; public static final int OPEN_HERB_BOX = 11739;
public static final int SCROLL_OF_REDIRECTION = 11740; public static final int SCROLL_OF_REDIRECTION = 11740;
public static final int RIMMINGTON_TELEPORT = 11741; public static final int RIMMINGTON_TELEPORT = 11741;
public static final int TAVERLEY_TELEPORT = 11742; public static final int TAVERLEY_TELEPORT = 11742;
@@ -7481,6 +7481,7 @@ public final class ItemID
public static final int BOX_OF_CHOCOLATE_STRAWBERRIES = 11912; public static final int BOX_OF_CHOCOLATE_STRAWBERRIES = 11912;
public static final int BOX_OF_CHOCOLATE_STRAWBERRIES_11914 = 11914; public static final int BOX_OF_CHOCOLATE_STRAWBERRIES_11914 = 11914;
public static final int SLICE_OF_BIRTHDAY_CAKE = 11916; public static final int SLICE_OF_BIRTHDAY_CAKE = 11916;
public static final int SLICE_OF_BIRTHDAY_CAKE_11917 = 11917;
public static final int BIRTHDAY_PRESENT = 11918; public static final int BIRTHDAY_PRESENT = 11918;
public static final int COW_MASK = 11919; public static final int COW_MASK = 11919;
public static final int DRAGON_PICKAXE = 11920; public static final int DRAGON_PICKAXE = 11920;
@@ -11391,8 +11392,8 @@ public final class ItemID
public static final int TWISTED_RELICHUNTER_T3_ARMOUR_SET = 24475; public static final int TWISTED_RELICHUNTER_T3_ARMOUR_SET = 24475;
public static final int OPEN_HERB_SACK = 24478; public static final int OPEN_HERB_SACK = 24478;
public static final int SPICE_RACK = 24479; public static final int SPICE_RACK = 24479;
public static final int OPENED_COAL_BAG = 24480; public static final int OPEN_COAL_BAG = 24480;
public static final int OPENED_GEM_BAG = 24481; public static final int OPEN_GEM_BAG = 24481;
public static final int OPEN_SEED_BOX = 24482; public static final int OPEN_SEED_BOX = 24482;
public static final int PHOENIX_24483 = 24483; public static final int PHOENIX_24483 = 24483;
public static final int PHOENIX_24484 = 24484; public static final int PHOENIX_24484 = 24484;
@@ -11407,11 +11408,9 @@ public final class ItemID
public static final int VOLATILE_ORB = 24514; public static final int VOLATILE_ORB = 24514;
public static final int ELDRITCH_ORB = 24517; public static final int ELDRITCH_ORB = 24517;
public static final int VICTORS_CAPE_1000 = 24520; public static final int VICTORS_CAPE_1000 = 24520;
public static final int CAT_EARS = 24522; public static final int CAT_EARS = 24525;
public static final int LOOSE_CAT_HAIR = 24523;
public static final int GERTRUDES_COMB = 24524;
public static final int CAT_EARS_24525 = 24525;
public static final int HELL_CAT_EARS = 24527; public static final int HELL_CAT_EARS = 24527;
public static final int LAMP_OF_THE_GATHERER = 24528; public static final int LAMP_OF_THE_GATHERER = 24528;
public static final int HARMONY = 24529;
/* This file is automatically generated. Do not edit. */ /* This file is automatically generated. Do not edit. */
} }
@@ -27,7 +27,7 @@ package net.runelite.api;
/** /**
* Represents a message in the chatbox. * Represents a message in the chatbox.
*/ */
public interface MessageNode public interface MessageNode extends Node
{ {
/** /**
* Get the id for this message node * Get the id for this message node
@@ -8429,6 +8429,15 @@ public final class NpcID
public static final int SHURA = 9413; public static final int SHURA = 9413;
public static final int SHURA_9414 = 9414; public static final int SHURA_9414 = 9414;
public static final int ACORN = 9415; public static final int ACORN = 9415;
public static final int PHOSANIS_NIGHTMARE = 9416;
public static final int PHOSANIS_NIGHTMARE_9417 = 9417;
public static final int PHOSANIS_NIGHTMARE_9418 = 9418;
public static final int PHOSANIS_NIGHTMARE_9419 = 9419;
public static final int PHOSANIS_NIGHTMARE_9420 = 9420;
public static final int PHOSANIS_NIGHTMARE_9421 = 9421;
public static final int PHOSANIS_NIGHTMARE_9422 = 9422;
public static final int PHOSANIS_NIGHTMARE_9423 = 9423;
public static final int PHOSANIS_NIGHTMARE_9424 = 9424;
public static final int THE_NIGHTMARE = 9425; public static final int THE_NIGHTMARE = 9425;
public static final int THE_NIGHTMARE_9426 = 9426; public static final int THE_NIGHTMARE_9426 = 9426;
public static final int THE_NIGHTMARE_9427 = 9427; public static final int THE_NIGHTMARE_9427 = 9427;
@@ -8466,12 +8475,12 @@ public final class NpcID
public static final int THE_NIGHTMARE_9463 = 9463; public static final int THE_NIGHTMARE_9463 = 9463;
public static final int THE_NIGHTMARE_9464 = 9464; public static final int THE_NIGHTMARE_9464 = 9464;
public static final int INFERNAL_PYRELORD = 9465; public static final int INFERNAL_PYRELORD = 9465;
public static final int DRAUL_LEPTOC_9467 = 9467; public static final int HUSK_9466 = 9466;
public static final int HORACIO_9468 = 9468; public static final int HUSK_9467 = 9467;
public static final int WISE_OLD_MAN_9469 = 9469; public static final int PARASITE_9468 = 9468;
public static final int HANS_9470 = 9470; public static final int PARASITE_9469 = 9469;
public static final int KING_ROALD_9471 = 9471; public static final int SLEEPWALKER_9470 = 9470;
public static final int ELLAMARIA_9472 = 9472; public static final int SISTER_SENGA = 9471;
public static final int GNOME_CHILD_9473 = 9473; public static final int SISTER_SENGA_9472 = 9472;
/* This file is automatically generated. Do not edit. */ /* This file is automatically generated. Do not edit. */
} }
@@ -4321,7 +4321,6 @@ public final class NullItemID
public static final int NULL_11911 = 11911; public static final int NULL_11911 = 11911;
public static final int NULL_11913 = 11913; public static final int NULL_11913 = 11913;
public static final int NULL_11915 = 11915; public static final int NULL_11915 = 11915;
public static final int NULL_11917 = 11917;
public static final int NULL_11921 = 11921; public static final int NULL_11921 = 11921;
public static final int NULL_11925 = 11925; public static final int NULL_11925 = 11925;
public static final int NULL_11927 = 11927; public static final int NULL_11927 = 11927;
@@ -12906,6 +12905,10 @@ public final class NullItemID
public static final int NULL_24518 = 24518; public static final int NULL_24518 = 24518;
public static final int NULL_24519 = 24519; public static final int NULL_24519 = 24519;
public static final int NULL_24521 = 24521; public static final int NULL_24521 = 24521;
public static final int NULL_24522 = 24522;
public static final int NULL_24523 = 24523;
public static final int NULL_24524 = 24524;
public static final int NULL_24526 = 24526; public static final int NULL_24526 = 24526;
public static final int NULL_24530 = 24530;
/* This file is automatically generated. Do not edit. */ /* This file is automatically generated. Do not edit. */
} }
@@ -13894,7 +13894,8 @@ public final class NullObjectID
public static final int NULL_29702 = 29702; public static final int NULL_29702 = 29702;
public static final int NULL_29703 = 29703; public static final int NULL_29703 = 29703;
public static final int NULL_29704 = 29704; public static final int NULL_29704 = 29704;
public static final int NULL_29706 = 29706; public static final int NULL_29709 = 29709;
public static final int NULL_29710 = 29710;
public static final int NULL_29713 = 29713; public static final int NULL_29713 = 29713;
public static final int NULL_29714 = 29714; public static final int NULL_29714 = 29714;
public static final int NULL_29715 = 29715; public static final int NULL_29715 = 29715;
@@ -18160,7 +18161,6 @@ public final class NullObjectID
public static final int NULL_37722 = 37722; public static final int NULL_37722 = 37722;
public static final int NULL_37723 = 37723; public static final int NULL_37723 = 37723;
public static final int NULL_37724 = 37724; public static final int NULL_37724 = 37724;
public static final int NULL_37725 = 37725;
public static final int NULL_37732 = 37732; public static final int NULL_37732 = 37732;
public static final int NULL_37733 = 37733; public static final int NULL_37733 = 37733;
public static final int NULL_37734 = 37734; public static final int NULL_37734 = 37734;
@@ -18329,34 +18329,5 @@ public final class NullObjectID
public static final int NULL_37934 = 37934; public static final int NULL_37934 = 37934;
public static final int NULL_37935 = 37935; public static final int NULL_37935 = 37935;
public static final int NULL_37950 = 37950; public static final int NULL_37950 = 37950;
public static final int NULL_37952 = 37952;
public static final int NULL_37953 = 37953;
public static final int NULL_37954 = 37954;
public static final int NULL_37962 = 37962;
public static final int NULL_37963 = 37963;
public static final int NULL_37964 = 37964;
public static final int NULL_37965 = 37965;
public static final int NULL_37966 = 37966;
public static final int NULL_37967 = 37967;
public static final int NULL_37971 = 37971;
public static final int NULL_37972 = 37972;
public static final int NULL_37973 = 37973;
public static final int NULL_37975 = 37975;
public static final int NULL_37977 = 37977;
public static final int NULL_37978 = 37978;
public static final int NULL_37979 = 37979;
public static final int NULL_37980 = 37980;
public static final int NULL_37981 = 37981;
public static final int NULL_37982 = 37982;
public static final int NULL_37984 = 37984;
public static final int NULL_37985 = 37985;
public static final int NULL_37986 = 37986;
public static final int NULL_37987 = 37987;
public static final int NULL_37988 = 37988;
public static final int NULL_37989 = 37989;
public static final int NULL_37990 = 37990;
public static final int NULL_37991 = 37991;
public static final int NULL_37992 = 37992;
public static final int NULL_37994 = 37994;
/* This file is automatically generated. Do not edit. */ /* This file is automatically generated. Do not edit. */
} }
@@ -15800,6 +15800,9 @@ public final class ObjectID
public static final int CARVED_REDWOOD_29681 = 29681; public static final int CARVED_REDWOOD_29681 = 29681;
public static final int CARVED_REDWOOD_29682 = 29682; public static final int CARVED_REDWOOD_29682 = 29682;
public static final int CRACK_29705 = 29705; public static final int CRACK_29705 = 29705;
public static final int POOL_OF_NIGHTMARES = 29706;
public static final int POOL_OF_NIGHTMARES_29707 = 29707;
public static final int SCOREBOARD_29708 = 29708;
public static final int NOTICEBOARD_29718 = 29718; public static final int NOTICEBOARD_29718 = 29718;
public static final int BALLISTA_29719 = 29719; public static final int BALLISTA_29719 = 29719;
public static final int STAIRCASE_29720 = 29720; public static final int STAIRCASE_29720 = 29720;
@@ -19580,16 +19583,5 @@ public final class ObjectID
public static final int DOOR_37938 = 37938; public static final int DOOR_37938 = 37938;
public static final int SCOREBOARD_37949 = 37949; public static final int SCOREBOARD_37949 = 37949;
public static final int COFFIN_37951 = 37951; public static final int COFFIN_37951 = 37951;
public static final int LIGHT_37955 = 37955;
public static final int LIGHT_37956 = 37956;
public static final int LIGHT_37957 = 37957;
public static final int LIGHT_37958 = 37958;
public static final int LIGHT_37959 = 37959;
public static final int LIGHT_37960 = 37960;
public static final int BANQUET_TABLE_37968 = 37968;
public static final int PRESENT_TABLE = 37969;
public static final int BIRTHDAY_HAT_TABLE = 37970;
public static final int PARTY_BALLOONS = 37974;
public static final int TABLE_37976 = 37976;
/* This file is automatically generated. Do not edit. */ /* This file is automatically generated. Do not edit. */
} }
@@ -36,6 +36,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import static net.runelite.api.Constants.TILE_FLAG_BRIDGE; import static net.runelite.api.Constants.TILE_FLAG_BRIDGE;
import net.runelite.api.coords.LocalPoint; import net.runelite.api.coords.LocalPoint;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.geometry.RectangleUnion; import net.runelite.api.geometry.RectangleUnion;
import net.runelite.api.geometry.Shapes; import net.runelite.api.geometry.Shapes;
import net.runelite.api.geometry.SimplePolygon; import net.runelite.api.geometry.SimplePolygon;
@@ -760,4 +761,119 @@ public class Perspective
return new Point(xOffset, yOffset); return new Point(xOffset, yOffset);
} }
/**
* Calculates a polygon line from 2 LocalPoints
*
* @param client the game client
* @param startLocation start location of the polygon
* @param endLocation end location of the polygon
* @return a {@link Polygon}
*/
private static Polygon linePoly(@Nonnull Client client, @Nonnull LocalPoint startLocation, @Nonnull LocalPoint endLocation)
{
LocalPoint startPoint = new LocalPoint(
startLocation.getX() - (LOCAL_TILE_SIZE / 2),
startLocation.getY() + (LOCAL_TILE_SIZE / 2));
LocalPoint endPoint = new LocalPoint(
endLocation.getX() - (LOCAL_TILE_SIZE / 2),
endLocation.getY() + (LOCAL_TILE_SIZE / 2));
int plane = client.getPlane();
Point p1 = Perspective.localToCanvas(client, startPoint, plane);
Point p2 = Perspective.localToCanvas(client, endPoint, plane);
if (p1 != null && p2 != null)
{
Polygon polygon = new Polygon();
polygon.addPoint(p1.getX(), p1.getY());
polygon.addPoint(p2.getX(), p2.getY());
return polygon;
}
return null;
}
/**
* Calculates a list of polygon lines with 2 Worldpoints
* Start location is the South-West WorldPoint, end location is the North-East WorldPoint
* @param client the game client
* @param startLocation start location of the polygon
* @param endLocation end location of the polygon
* @return a {@link List} of {@link Polygon}
*/
public static List<Polygon> getLinePolyList(@Nonnull Client client, @Nonnull WorldPoint startLocation, @Nonnull WorldPoint endLocation)
{
List<Polygon> pList = new ArrayList<>();
int sizeX = Math.abs(endLocation.getX() - startLocation.getX()) + 1;
int sizeY = Math.abs(endLocation.getY() - startLocation.getY()) + 1;
//HANDLE NORTH
for (int i = 0; i < sizeX; i++)
{
WorldPoint startPoint = new WorldPoint(startLocation.getX() + i, startLocation.getY() + sizeY - 1, startLocation.getPlane());
WorldPoint endPoint = new WorldPoint(startLocation.getX() + (i + 1), startLocation.getY() + sizeY - 1, startLocation.getPlane());
LocalPoint localPointStart = LocalPoint.fromWorld(client, startPoint);
LocalPoint localPointEnd = LocalPoint.fromWorld(client, endPoint);
if (localPointStart != null && localPointEnd != null)
{
Polygon p = linePoly(client, localPointStart, localPointEnd);
if (p != null)
{
pList.add(p);
}
}
}
//HANDLE SOUTH
for (int i = 0; i < sizeX; i++)
{
WorldPoint startPoint = new WorldPoint(startLocation.getX() + i, startLocation.getY() - 1, startLocation.getPlane());
WorldPoint endPoint = new WorldPoint(startLocation.getX() + (i + 1), startLocation.getY() - 1, startLocation.getPlane());
LocalPoint localPointStart = LocalPoint.fromWorld(client, startPoint);
LocalPoint localPointEnd = LocalPoint.fromWorld(client, endPoint);
if (localPointStart != null && localPointEnd != null)
{
Polygon p = linePoly(client, localPointStart, localPointEnd);
if (p != null)
{
pList.add(p);
}
}
}
//HANDLE WEST
for (int j = 0; j < sizeY; j++)
{
WorldPoint startPoint = new WorldPoint(startLocation.getX(), startLocation.getY() + (j - 1), startLocation.getPlane());
WorldPoint endPoint = new WorldPoint(startLocation.getX(), startLocation.getY() + j, startLocation.getPlane());
LocalPoint localPointStart = LocalPoint.fromWorld(client, startPoint);
LocalPoint localPointEnd = LocalPoint.fromWorld(client, endPoint);
if (localPointStart != null && localPointEnd != null)
{
Polygon p = linePoly(client, localPointStart, localPointEnd);
if (p != null)
{
pList.add(p);
}
}
}
//HANDLE EAST
for (int j = 0; j < sizeY; j++)
{
WorldPoint startPoint = new WorldPoint(startLocation.getX() + sizeX, startLocation.getY() + (j - 1), startLocation.getPlane());
WorldPoint endPoint = new WorldPoint(startLocation.getX() + sizeX, startLocation.getY() + j, startLocation.getPlane());
LocalPoint localPointStart = LocalPoint.fromWorld(client, startPoint);
LocalPoint localPointEnd = LocalPoint.fromWorld(client, endPoint);
if (localPointStart != null && localPointEnd != null)
{
Polygon p = linePoly(client, localPointStart, localPointEnd);
if (p != null)
{
pList.add(p);
}
}
}
return pList;
}
} }
@@ -24,46 +24,17 @@
*/ */
package net.runelite.api; package net.runelite.api;
import lombok.Value;
/** /**
* A two-dimensional coordinate on the canvas. * A two-dimensional coordinate on the canvas.
*/ */
@Value
public class Point public class Point
{ {
private final int x; private final int x;
private final int y; private final int y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
@Override
public String toString()
{
return "Point{" + "x=" + x + ", y=" + y + '}';
}
/**
* Gets the x-axis coordinate of the point.
*
* @return the x-axis coordinate
*/
public int getX()
{
return x;
}
/**
* Gets the y-axis coordinate of the point.
*
* @return the y-axis coordinate
*/
public int getY()
{
return y;
}
/** /**
* Gets the distance between this point and another. * Gets the distance between this point and another.
* *
@@ -74,36 +45,4 @@ public class Point
{ {
return (int) Math.hypot(getX() - other.getX(), getY() - other.getY()); return (int) Math.hypot(getX() - other.getX(), getY() - other.getY());
} }
@Override
public int hashCode()
{
int hash = 3;
hash = 23 * hash + this.x;
hash = 23 * hash + this.y;
return hash;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
if (obj == null)
{
return false;
}
if (getClass() != obj.getClass())
{
return false;
}
final Point other = (Point) obj;
if (this.x != other.x)
{
return false;
}
return this.y == other.y;
}
} }
@@ -227,5 +227,48 @@ public final class ScriptID
@ScriptArguments(string = 1) @ScriptArguments(string = 1)
public static final int CLAN_SEND_KICK = 215; public static final int CLAN_SEND_KICK = 215;
/**
* Toggles the bank search
*
* <ul>
* <li>int 1 (must be 1 or script immediately returns)</li>
* </ul>
*
* Also takes 17 widget IDs corresponding to various bank widgets.
* These can be retrieved from the getOnInvTransmit of BANK_ITEM_CONTAINER. Note that this array also
* contains the script ID for the bank layout script in the first index
*/
@ScriptArguments(integer = 18)
public static final int BANKMAIN_SEARCH_TOGGLE = 281;
/**
* Builds the items kept on death widget
*/
@ScriptArguments(integer = 4, string = 2)
public static final int DEATH_KEEP_BUILD = 1601;
/**
* Builds the widget that holds all of the players inside a clan chat
*/
@ScriptArguments(integer = 15)
public static final int CLAN_CHAT_CHANNEL_BUILD = 1658;
/**
* Builds the widget for making an offer in Grand Exchange
*/
@ScriptArguments(integer = 15)
public static final int GE_OFFERS_SETUP_BUILD = 779;
/**
* Builds the quest list inside the quest tab that shows each quest's progress
*/
@ScriptArguments(integer = 3)
public static final int QUESTLIST_PROGRESS_LIST_SHOW = 1354;
/**
* Procedure called when the toplevel interface is resized
*/
@ScriptArguments(integer = 2)
public static final int TOPLEVEL_RESIZE = 909;
} }
@@ -1293,7 +1293,7 @@ public final class SpriteID
public static final int SPELL_REANIMATE_CROPS_DISABLED = 1327; public static final int SPELL_REANIMATE_CROPS_DISABLED = 1327;
/* Unmapped: 1328~1337 */ /* Unmapped: 1328~1337 */
public static final int WORLD_SWITCHER_WORLD_STAR_BLUE = 1338; public static final int WORLD_SWITCHER_WORLD_STAR_BLUE = 1338;
public static final int GAMEBLAST16_PROMO_BANNER = 1339; public static final int HITSPLAT_DARK_GREEN_VENOM = 1339;
public static final int FAIRY_RING_REMOVE_FAVOURITE = 1340; public static final int FAIRY_RING_REMOVE_FAVOURITE = 1340;
public static final int FAIRY_RING_ADD_FAVOURITE = 1341; public static final int FAIRY_RING_ADD_FAVOURITE = 1341;
public static final int BANK_PLACEHOLDERS_LOCK = 1342; public static final int BANK_PLACEHOLDERS_LOCK = 1342;
@@ -1317,7 +1317,7 @@ public final class SpriteID
public static final int HITSPLAT_GREEN_POISON = 1360; public static final int HITSPLAT_GREEN_POISON = 1360;
public static final int HITSPLAT_ORANGE = 1361; public static final int HITSPLAT_ORANGE = 1361;
public static final int HITSPLAT_ORANGE_DISEASE = 1362; public static final int HITSPLAT_ORANGE_DISEASE = 1362;
public static final int HITSPLAT_DARK_GREEN_VENOM = 1363; public static final int HITSPLAT_GREY = 1363;
public static final int BOUNTY_HUNTER_SKIP_TARGET = 1364; public static final int BOUNTY_HUNTER_SKIP_TARGET = 1364;
public static final int BOUNTY_HUNTER_SKIP_TARGET_HOVERED = 1365; public static final int BOUNTY_HUNTER_SKIP_TARGET_HOVERED = 1365;
public static final int HOUSE_VIEWER_ROTATE_CLOCKWISE = 1366; public static final int HOUSE_VIEWER_ROTATE_CLOCKWISE = 1366;
@@ -405,6 +405,15 @@ public enum Varbits
*/ */
KINGDOM_FAVOR(72), KINGDOM_FAVOR(72),
KINGDOM_COFFER(74), KINGDOM_COFFER(74),
KINGDOM_WORKERS_WOOD(81),
KINGDOM_WORKERS_HERBS(82),
KINGDOM_WORKERS_FISHING(83),
KINGDOM_WORKERS_MINING(84),
KINGDOM_WORKERS_FISH_COOKED_BUTTON(135), // 0 - Raw, 1 - Cooked
KINGDOM_WORKERS_HARDWOOD(2131),
KINGDOM_WORKERS_FARM(2132),
KINGDOM_WORKERS_HARDWOOD_BUTTON(2133), // 0 - Mahogany, 1 - Teak, 2 - Both
KINGDOM_WORKERS_HERBS_BUTTON(2134), // 0 - Herbs, 1 - Flax
/** /**
* The Hand in the Sand quest status * The Hand in the Sand quest status
@@ -501,6 +510,7 @@ public enum Varbits
SUPERIOR_ENABLED(5362), SUPERIOR_ENABLED(5362),
FOSSIL_ISLAND_WYVERN_DISABLE(6251), FOSSIL_ISLAND_WYVERN_DISABLE(6251),
BANK_REARRANGE_MODE(3959),
CURRENT_BANK_TAB(4150), CURRENT_BANK_TAB(4150),
WORLDHOPPER_FAVROITE_1(4597), WORLDHOPPER_FAVROITE_1(4597),
@@ -0,0 +1,17 @@
package net.runelite.api.events.player.headicon;
import lombok.Data;
import net.runelite.api.HeadIcon;
import net.runelite.api.Player;
import net.runelite.api.events.Event;
@Data
public class OverheadPrayerChanged implements Event
{
private final Player player;
private final HeadIcon oldHeadIcon;
private final HeadIcon newHeadIcon;
}
@@ -0,0 +1,17 @@
package net.runelite.api.events.player.headicon;
import lombok.Data;
import net.runelite.api.Player;
import net.runelite.api.SkullIcon;
import net.runelite.api.events.Event;
@Data
public class PlayerSkullChanged implements Event
{
private final Player player;
private final SkullIcon oldSkullIcon;
private final SkullIcon newSkullIcon;
}
@@ -33,11 +33,12 @@ import java.util.Collection;
import java.util.List; import java.util.List;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.WordUtils; import org.apache.commons.text.WordUtils;
import org.apache.commons.text.similarity.JaroWinklerDistance;
public class Text public class Text
{ {
private static final StringBuilder SB = new StringBuilder(64); private static final StringBuilder SB = new StringBuilder(64);
public static final JaroWinklerDistance DISTANCE = new JaroWinklerDistance();
public static final Splitter COMMA_SPLITTER = Splitter public static final Splitter COMMA_SPLITTER = Splitter
.on(",") .on(",")
.omitEmptyStrings() .omitEmptyStrings()
@@ -292,4 +293,22 @@ public class Text
return toString; return toString;
} }
/**
* Checks if all the search terms in the given list matches at least one keyword.
*
* @return true if all search terms matches at least one keyword, or false if otherwise.
*/
public static boolean matchesSearchTerms(String[] searchTerms, final Collection<String> keywords)
{
for (String term : searchTerms)
{
if (keywords.stream().noneMatch((t) -> t.contains(term) ||
DISTANCE.apply(t, term) > 0.9))
{
return false;
}
}
return true;
}
} }
@@ -124,6 +124,7 @@ public class WidgetID
public static final int WORLD_SWITCHER_GROUP_ID = 69; public static final int WORLD_SWITCHER_GROUP_ID = 69;
public static final int DIALOG_OPTION_GROUP_ID = 219; public static final int DIALOG_OPTION_GROUP_ID = 219;
public static final int DIALOG_PLAYER_GROUP_ID = 217; public static final int DIALOG_PLAYER_GROUP_ID = 217;
public static final int DRIFT_NET_FISHING_REWARD_GROUP_ID = 607;
public static final int FOSSIL_ISLAND_OXYGENBAR_ID = 609; public static final int FOSSIL_ISLAND_OXYGENBAR_ID = 609;
public static final int MINIGAME_TAB_ID = 76; public static final int MINIGAME_TAB_ID = 76;
public static final int SPELLBOOK_GROUP_ID = 218; public static final int SPELLBOOK_GROUP_ID = 218;
@@ -164,6 +165,9 @@ public class WidgetID
public static final int OPTIONS_GROUP_ID = 261; public static final int OPTIONS_GROUP_ID = 261;
public static final int THEATRE_OF_BLOOD_PARTY_GROUP_ID = 28; public static final int THEATRE_OF_BLOOD_PARTY_GROUP_ID = 28;
public static final int GWD_KC_GROUP_ID = 406; public static final int GWD_KC_GROUP_ID = 406;
public static final int ADVENTURE_LOG_ID = 187;
public static final int COUNTERS_LOG_GROUP_ID = 625;
public static final int GAUNTLET_TIMER_GROUP_ID = 637;
static class WorldMap static class WorldMap
{ {
@@ -726,6 +730,7 @@ public class WidgetID
static final int LIGHT_BOX = 1; static final int LIGHT_BOX = 1;
static final int LIGHT_BOX_WINDOW = 2; static final int LIGHT_BOX_WINDOW = 2;
static final int LIGHT_BULB_CONTAINER = 3; static final int LIGHT_BULB_CONTAINER = 3;
static final int LIGHT_BOX_BUTTON_CONTAINER = 6;
static final int BUTTON_A = 8; static final int BUTTON_A = 8;
static final int BUTTON_B = 9; static final int BUTTON_B = 9;
static final int BUTTON_C = 10; static final int BUTTON_C = 10;
@@ -1190,15 +1195,6 @@ public class WidgetID
static final int INVENTORY = 7; static final int INVENTORY = 7;
} }
static class Lms
{
static final int INFO = 3;
}
static class LmsKDA
{
static final int INFO = 4;
}
static class JewelBox static class JewelBox
{ {
@@ -1212,9 +1208,9 @@ public class WidgetID
static class Options static class Options
{ {
static final int MUSIC_SLIDER = 38; static final int MUSIC_SLIDER = 37;
static final int SOUND_EFFECT_SLIDER = 44; static final int SOUND_EFFECT_SLIDER = 43;
static final int AREA_SOUND_SLIDER = 50; static final int AREA_SOUND_SLIDER = 49;
} }
static class AchievementDiary static class AchievementDiary
@@ -1227,4 +1223,29 @@ public class WidgetID
static final int CONTAINER = 0; static final int CONTAINER = 0;
} }
static class Lms
{
static final int INFO = 3;
}
static class LmsKDA
{
static final int INFO = 5;
}
static class AdventureLog
{
static final int CONTAINER = 0;
}
static class CountersLog
{
static final int OWNER = 4;
static final int TEXT = 6;
}
static class GauntletTimer
{
static final int CONTAINER = 2;
}
} }
@@ -443,6 +443,7 @@ public enum WidgetInfo
LIGHT_BOX(WidgetID.LIGHT_BOX_GROUP_ID, WidgetID.LightBox.LIGHT_BOX), LIGHT_BOX(WidgetID.LIGHT_BOX_GROUP_ID, WidgetID.LightBox.LIGHT_BOX),
LIGHT_BOX_CONTENTS(WidgetID.LIGHT_BOX_GROUP_ID, WidgetID.LightBox.LIGHT_BULB_CONTAINER), LIGHT_BOX_CONTENTS(WidgetID.LIGHT_BOX_GROUP_ID, WidgetID.LightBox.LIGHT_BULB_CONTAINER),
LIGHT_BOX_BUTTON_CONTAINER(WidgetID.LIGHT_BOX_GROUP_ID, WidgetID.LightBox.LIGHT_BOX_BUTTON_CONTAINER),
LIGHT_BOX_BUTTON_A(WidgetID.LIGHT_BOX_GROUP_ID, WidgetID.LightBox.BUTTON_A), LIGHT_BOX_BUTTON_A(WidgetID.LIGHT_BOX_GROUP_ID, WidgetID.LightBox.BUTTON_A),
LIGHT_BOX_BUTTON_B(WidgetID.LIGHT_BOX_GROUP_ID, WidgetID.LightBox.BUTTON_B), LIGHT_BOX_BUTTON_B(WidgetID.LIGHT_BOX_GROUP_ID, WidgetID.LightBox.BUTTON_B),
LIGHT_BOX_BUTTON_C(WidgetID.LIGHT_BOX_GROUP_ID, WidgetID.LightBox.BUTTON_C), LIGHT_BOX_BUTTON_C(WidgetID.LIGHT_BOX_GROUP_ID, WidgetID.LightBox.BUTTON_C),
@@ -515,6 +516,10 @@ public enum WidgetInfo
KILL_LOG_KILLS(WidgetID.KILL_LOGS_GROUP_ID, WidgetID.KillLog.KILLS), KILL_LOG_KILLS(WidgetID.KILL_LOGS_GROUP_ID, WidgetID.KillLog.KILLS),
KILL_LOG_STREAK(WidgetID.KILL_LOGS_GROUP_ID, WidgetID.KillLog.STREAK), KILL_LOG_STREAK(WidgetID.KILL_LOGS_GROUP_ID, WidgetID.KillLog.STREAK),
ADVENTURE_LOG(WidgetID.ADVENTURE_LOG_ID, WidgetID.AdventureLog.CONTAINER),
COUNTERS_LOG_TEXT(WidgetID.COUNTERS_LOG_GROUP_ID, WidgetID.CountersLog.TEXT),
WORLD_SWITCHER_LIST(WidgetID.WORLD_SWITCHER_GROUP_ID, WidgetID.WorldSwitcher.WORLD_LIST), WORLD_SWITCHER_LIST(WidgetID.WORLD_SWITCHER_GROUP_ID, WidgetID.WorldSwitcher.WORLD_LIST),
FOSSIL_ISLAND_OXYGENBAR(WidgetID.FOSSIL_ISLAND_OXYGENBAR_ID, WidgetID.FossilOxygen.FOSSIL_ISLAND_OXYGEN_BAR), FOSSIL_ISLAND_OXYGENBAR(WidgetID.FOSSIL_ISLAND_OXYGENBAR_ID, WidgetID.FossilOxygen.FOSSIL_ISLAND_OXYGEN_BAR),
@@ -793,7 +798,9 @@ public enum WidgetInfo
SKILLS_CONTAINER(WidgetID.SKILLS_GROUP_ID, WidgetID.Skills.CONTAINER), SKILLS_CONTAINER(WidgetID.SKILLS_GROUP_ID, WidgetID.Skills.CONTAINER),
TRADING_WITH(WidgetID.PLAYER_TRADE_SCREEN_GROUP_ID, WidgetID.TradeScreen.FIRST_TRADING_WITH); TRADING_WITH(WidgetID.PLAYER_TRADE_SCREEN_GROUP_ID, WidgetID.TradeScreen.FIRST_TRADING_WITH),
GAUNTLET_TIMER_CONTAINER(WidgetID.GAUNTLET_TIMER_GROUP_ID, WidgetID.GauntletTimer.CONTAINER);
private final int groupId; private final int groupId;
private final int childId; private final int childId;
+3 -11
View File
@@ -41,6 +41,8 @@ dependencies {
annotationProcessor(Libraries.lombok) annotationProcessor(Libraries.lombok)
annotationProcessor(Libraries.pf4j) annotationProcessor(Libraries.pf4j)
api(project(":runelite-api"))
compileOnly(Libraries.javax) compileOnly(Libraries.javax)
compileOnly(Libraries.lombok) compileOnly(Libraries.lombok)
compileOnly(Libraries.orangeExtensions) compileOnly(Libraries.orangeExtensions)
@@ -66,14 +68,13 @@ dependencies {
implementation(Libraries.jooqCodegen) implementation(Libraries.jooqCodegen)
implementation(Libraries.jooqMeta) implementation(Libraries.jooqMeta)
implementation(Libraries.sentry) implementation(Libraries.sentry)
implementation(Libraries.semver)
implementation(Libraries.slf4jApi) implementation(Libraries.slf4jApi)
implementation(Libraries.pf4j) { implementation(Libraries.pf4j) {
exclude(group = "org.slf4j") exclude(group = "org.slf4j")
} }
implementation(Libraries.pf4jUpdate) implementation(Libraries.pf4jUpdate)
implementation(project(":http-api")) implementation(project(":http-api"))
api(project(":runelite-api"))
implementation(Libraries.naturalMouse)
runtimeOnly(Libraries.trident) runtimeOnly(Libraries.trident)
runtimeOnly(Libraries.jogampGluegenLinuxAmd64) runtimeOnly(Libraries.jogampGluegenLinuxAmd64)
@@ -105,16 +106,8 @@ fun formatDate(date: Date?) = with(date ?: Date()) {
SimpleDateFormat("MM-dd-yyyy").format(this) SimpleDateFormat("MM-dd-yyyy").format(this)
} }
fun launcherVersion(): String {
if (project.hasProperty("releaseBuild")) {
return ProjectVersions.launcherVersion
}
return "-1"
}
fun pluginPath(): String { fun pluginPath(): String {
if (project.hasProperty("pluginPath")) { if (project.hasProperty("pluginPath")) {
print(project.property("pluginPath").toString())
return project.property("pluginPath").toString() return project.property("pluginPath").toString()
} }
return "" return ""
@@ -135,7 +128,6 @@ tasks {
"rs.version" to ProjectVersions.rsversion.toString(), "rs.version" to ProjectVersions.rsversion.toString(),
"open.osrs.version" to ProjectVersions.openosrsVersion, "open.osrs.version" to ProjectVersions.openosrsVersion,
"open.osrs.builddate" to formatDate(Date()), "open.osrs.builddate" to formatDate(Date()),
"launcher.version" to launcherVersion(),
"plugin.path" to pluginPath() "plugin.path" to pluginPath()
) )
@@ -24,7 +24,7 @@
*/ */
package net.runelite.client; package net.runelite.client;
import io.reactivex.schedulers.Schedulers; import io.reactivex.rxjava3.schedulers.Schedulers;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
import java.util.UUID; import java.util.UUID;
import javax.inject.Inject; import javax.inject.Inject;
@@ -30,8 +30,8 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.inject.Guice; import com.google.inject.Guice;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Injector; import com.google.inject.Injector;
import io.reactivex.Completable; import io.reactivex.rxjava3.core.Completable;
import io.reactivex.schedulers.Schedulers; import io.reactivex.rxjava3.schedulers.Schedulers;
import io.sentry.Sentry; import io.sentry.Sentry;
import io.sentry.SentryClient; import io.sentry.SentryClient;
import java.io.File; import java.io.File;
@@ -39,14 +39,18 @@ import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean; import java.lang.management.RuntimeMXBean;
import java.net.Authenticator; import java.net.Authenticator;
import java.net.PasswordAuthentication; import java.net.PasswordAuthentication;
import java.nio.file.Paths;
import java.util.Locale; import java.util.Locale;
import java.util.Optional; import java.util.Optional;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.inject.Provider; import javax.inject.Provider;
import javax.inject.Singleton; import javax.inject.Singleton;
import joptsimple.ArgumentAcceptingOptionSpec; import joptsimple.ArgumentAcceptingOptionSpec;
import joptsimple.OptionException;
import joptsimple.OptionParser; import joptsimple.OptionParser;
import joptsimple.OptionSet; import joptsimple.OptionSet;
import joptsimple.ValueConversionException;
import joptsimple.ValueConverter;
import joptsimple.util.EnumConverter; import joptsimple.util.EnumConverter;
import lombok.Getter; import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -85,6 +89,7 @@ import net.runelite.client.ui.overlay.arrow.ArrowWorldOverlay;
import net.runelite.client.ui.overlay.infobox.InfoBoxOverlay; import net.runelite.client.ui.overlay.infobox.InfoBoxOverlay;
import net.runelite.client.ui.overlay.tooltip.TooltipOverlay; import net.runelite.client.ui.overlay.tooltip.TooltipOverlay;
import net.runelite.client.ui.overlay.worldmap.WorldMapOverlay; import net.runelite.client.ui.overlay.worldmap.WorldMapOverlay;
import net.runelite.client.util.AppLock;
import net.runelite.client.util.WorldUtil; import net.runelite.client.util.WorldUtil;
import net.runelite.client.ws.PartyService; import net.runelite.client.ws.PartyService;
import net.runelite.http.api.worlds.World; import net.runelite.http.api.worlds.World;
@@ -105,6 +110,7 @@ public class RuneLite
public static final File SCREENSHOT_DIR = new File(RUNELITE_DIR, "screenshots"); public static final File SCREENSHOT_DIR = new File(RUNELITE_DIR, "screenshots");
public static final File LOGS_DIR = new File(RUNELITE_DIR, "logs"); public static final File LOGS_DIR = new File(RUNELITE_DIR, "logs");
public static final File PLUGINS_DIR = new File(RUNELITE_DIR, "plugins"); public static final File PLUGINS_DIR = new File(RUNELITE_DIR, "plugins");
public static final File DEFAULT_CONFIG_FILE = new File(RUNELITE_DIR, "runeliteplus.properties");
public static final Locale SYSTEM_LOCALE = Locale.getDefault(); public static final Locale SYSTEM_LOCALE = Locale.getDefault();
public static boolean allowPrivateServer = false; public static boolean allowPrivateServer = false;
@@ -201,6 +207,9 @@ public class RuneLite
@Inject @Inject
private Scheduler scheduler; private Scheduler scheduler;
@Inject
private AppLock appLock;
public static void main(String[] args) throws Exception public static void main(String[] args) throws Exception
{ {
Locale.setDefault(Locale.ENGLISH); Locale.setDefault(Locale.ENGLISH);
@@ -215,6 +224,11 @@ public class RuneLite
final ArgumentAcceptingOptionSpec<Integer> worldInfo = parser final ArgumentAcceptingOptionSpec<Integer> worldInfo = parser
.accepts("world") .accepts("world")
.withRequiredArg().ofType(Integer.class); .withRequiredArg().ofType(Integer.class);
final ArgumentAcceptingOptionSpec<File> configfile = parser.accepts("config", "Use a specified config file")
.withRequiredArg()
.withValuesConvertedBy(new ConfigFileConverter())
.defaultsTo(DEFAULT_CONFIG_FILE);
final ArgumentAcceptingOptionSpec<ClientUpdateCheckMode> updateMode = parser final ArgumentAcceptingOptionSpec<ClientUpdateCheckMode> updateMode = parser
.accepts("rs", "Select client type") .accepts("rs", "Select client type")
.withRequiredArg() .withRequiredArg()
@@ -230,7 +244,18 @@ public class RuneLite
}); });
parser.accepts("help", "Show this text").forHelp(); parser.accepts("help", "Show this text").forHelp();
OptionSet options = parser.parse(args);
OptionSet options = parser.parse("");
try
{
options = parser.parse(args);
}
catch (OptionException e)
{
log.warn("Error parsing launch args: {}", e.getMessage());
log.warn("Proceeding with no arguments.");
}
if (options.has("help")) if (options.has("help"))
{ {
@@ -297,18 +322,6 @@ public class RuneLite
RuneLiteSplashScreen.init(); RuneLiteSplashScreen.init();
} }
final boolean developerMode = options.has("developer-mode");
if (developerMode)
{
boolean assertions = false;
assert assertions = true;
if (!assertions)
{
log.warn("Developers should enable assertions; Add `-ea` to your JVM arguments`");
}
}
Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> Thread.setDefaultUncaughtExceptionHandler((thread, throwable) ->
{ {
log.error("Uncaught exception:", throwable); log.error("Uncaught exception:", throwable);
@@ -327,7 +340,7 @@ public class RuneLite
injector = Guice.createInjector(new RuneLiteModule( injector = Guice.createInjector(new RuneLiteModule(
clientLoader, clientLoader,
true)); options.valueOf(configfile)));
injector.getInstance(RuneLite.class).start(); injector.getInstance(RuneLite.class).start();
final long end = System.currentTimeMillis(); final long end = System.currentTimeMillis();
@@ -368,9 +381,11 @@ public class RuneLite
externalPluginManager.startExternalUpdateManager(); externalPluginManager.startExternalUpdateManager();
externalPluginManager.startExternalPluginManager(); externalPluginManager.startExternalPluginManager();
if (appLock.lock(this.getClass().getName()))
RuneLiteSplashScreen.stage(.59, "Updating external plugins"); {
externalPluginManager.update(); RuneLiteSplashScreen.stage(.59, "Updating external plugins");
externalPluginManager.update();
}
// Load the plugins, but does not start them yet. // Load the plugins, but does not start them yet.
// This will initialize configuration // This will initialize configuration
@@ -387,7 +402,7 @@ public class RuneLite
pluginManager.loadDefaultPluginConfiguration(); pluginManager.loadDefaultPluginConfiguration();
// Start client session // Start client session
RuneLiteSplashScreen.stage(.80, "Starting core interface"); RuneLiteSplashScreen.stage(.77, "Starting core interface");
clientSessionManager.start(); clientSessionManager.start();
//Set the world if specified via CLI args - will not work until clientUI.init is called //Set the world if specified via CLI args - will not work until clientUI.init is called
@@ -395,7 +410,7 @@ public class RuneLite
worldArg.ifPresent(this::setWorld); worldArg.ifPresent(this::setWorld);
// Initialize UI // Initialize UI
RuneLiteSplashScreen.stage(.77, "Initialize UI"); RuneLiteSplashScreen.stage(.80, "Initialize UI");
clientUI.init(this); clientUI.init(this);
// Initialize Discord service // Initialize Discord service
@@ -487,8 +502,47 @@ public class RuneLite
public void shutdown() public void shutdown()
{ {
configManager.sendConfig();
clientSessionManager.shutdown(); clientSessionManager.shutdown();
discordService.close(); discordService.close();
appLock.release();
}
private static class ConfigFileConverter implements ValueConverter<File>
{
@Override
public File convert(String fileName)
{
final File file;
if (Paths.get(fileName).isAbsolute()
|| fileName.startsWith("./")
|| fileName.startsWith(".\\"))
{
file = new File(fileName);
}
else
{
file = new File(RuneLite.RUNELITE_DIR, fileName);
}
if (file.exists() && (!file.isFile() || !file.canWrite()))
{
throw new ValueConversionException(String.format("File %s is not accessible", file.getAbsolutePath()));
}
return file;
}
@Override
public Class<? extends File> valueType()
{
return File.class;
}
@Override
public String valuePattern()
{
return null;
}
} }
} }
@@ -41,6 +41,7 @@ import net.runelite.client.callback.Hooks;
import net.runelite.client.chat.ChatMessageManager; import net.runelite.client.chat.ChatMessageManager;
import net.runelite.client.config.ChatColorConfig; import net.runelite.client.config.ChatColorConfig;
import net.runelite.client.config.ConfigManager; import net.runelite.client.config.ConfigManager;
import net.runelite.client.config.LauncherConfig;
import net.runelite.client.config.OpenOSRSConfig; import net.runelite.client.config.OpenOSRSConfig;
import net.runelite.client.config.RuneLiteConfig; import net.runelite.client.config.RuneLiteConfig;
import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.EventBus;
@@ -61,18 +62,18 @@ public class RuneLiteModule extends AbstractModule
private static final int MAX_OKHTTP_CACHE_SIZE = 20 * 1024 * 1024; // 20mb private static final int MAX_OKHTTP_CACHE_SIZE = 20 * 1024 * 1024; // 20mb
private final Supplier<Applet> clientLoader; private final Supplier<Applet> clientLoader;
private final boolean developerMode; private final File config;
public RuneLiteModule(final Supplier<Applet> clientLoader, boolean developerMode) public RuneLiteModule(final Supplier<Applet> clientLoader, File config)
{ {
this.clientLoader = clientLoader; this.clientLoader = clientLoader;
this.developerMode = developerMode; this.config = config;
} }
@Override @Override
protected void configure() protected void configure()
{ {
bindConstant().annotatedWith(Names.named("developerMode")).to(developerMode); bind(File.class).annotatedWith(Names.named("config")).toInstance(config);
bind(ScheduledExecutorService.class).toInstance(new ExecutorServiceExceptionLogger(Executors.newSingleThreadScheduledExecutor())); bind(ScheduledExecutorService.class).toInstance(new ExecutorServiceExceptionLogger(Executors.newSingleThreadScheduledExecutor()));
bind(OkHttpClient.class).toInstance(RuneLiteAPI.CLIENT.newBuilder() bind(OkHttpClient.class).toInstance(RuneLiteAPI.CLIENT.newBuilder()
.cache(new Cache(new File(RuneLite.CACHE_DIR, "okhttp"), MAX_OKHTTP_CACHE_SIZE)) .cache(new Cache(new File(RuneLite.CACHE_DIR, "okhttp"), MAX_OKHTTP_CACHE_SIZE))
@@ -132,4 +133,11 @@ public class RuneLiteModule extends AbstractModule
{ {
return configManager.getConfig(ChatColorConfig.class); return configManager.getConfig(ChatColorConfig.class);
} }
@Provides
@Singleton
LauncherConfig provideLauncherConfig(ConfigManager configManager)
{
return configManager.getConfig(LauncherConfig.class);
}
} }
@@ -136,8 +136,7 @@ public class RuneLiteProperties
@Nullable @Nullable
public static String getLauncherVersion() public static String getLauncherVersion()
{ {
String launcherVersion = properties.getProperty(LAUNCHER_VERSION_PROPERTY); return System.getProperty(LAUNCHER_VERSION_PROPERTY);
return launcherVersion.equals("-1") ? null : launcherVersion;
} }
@Nullable @Nullable
@@ -24,8 +24,8 @@
*/ */
package net.runelite.client; package net.runelite.client;
import io.reactivex.Completable; import io.reactivex.rxjava3.core.Completable;
import io.reactivex.Observable; import io.reactivex.rxjava3.core.Observable;
import java.io.IOException; import java.io.IOException;
import java.util.UUID; import java.util.UUID;
import net.runelite.http.api.RuneLiteAPI; import net.runelite.http.api.RuneLiteAPI;
@@ -25,7 +25,7 @@
package net.runelite.client.account; package net.runelite.client.account;
import com.google.gson.Gson; import com.google.gson.Gson;
import io.reactivex.schedulers.Schedulers; import io.reactivex.rxjava3.schedulers.Schedulers;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileWriter; import java.io.FileWriter;
@@ -25,8 +25,8 @@
package net.runelite.client.callback; package net.runelite.client.callback;
import com.google.inject.Inject; import com.google.inject.Inject;
import io.reactivex.plugins.RxJavaPlugins; import io.reactivex.rxjava3.plugins.RxJavaPlugins;
import io.reactivex.schedulers.Schedulers; import io.reactivex.rxjava3.schedulers.Schedulers;
import java.util.Iterator; import java.util.Iterator;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
@@ -59,6 +59,7 @@ import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.runelite.api.coords.WorldPoint; import net.runelite.api.coords.WorldPoint;
@@ -75,20 +76,20 @@ import org.apache.commons.lang3.StringUtils;
@Slf4j @Slf4j
public class ConfigManager public class ConfigManager
{ {
private static final String SETTINGS_FILE_NAME = "runeliteplus.properties";
private static final String STANDARD_SETTINGS_FILE_NAME = "settings.properties"; private static final String STANDARD_SETTINGS_FILE_NAME = "settings.properties";
private static final File SETTINGS_FILE = new File(RuneLite.RUNELITE_DIR, SETTINGS_FILE_NAME);
private static final File STANDARD_SETTINGS_FILE = new File(RuneLite.RUNELITE_DIR, STANDARD_SETTINGS_FILE_NAME); private static final File STANDARD_SETTINGS_FILE = new File(RuneLite.RUNELITE_DIR, STANDARD_SETTINGS_FILE_NAME);
private final ConfigInvocationHandler handler = new ConfigInvocationHandler(this); private final ConfigInvocationHandler handler = new ConfigInvocationHandler(this);
private final Properties properties = new Properties(); private final Properties properties = new Properties();
private final Map<String, String> pendingChanges = new HashMap<>(); private final Map<String, String> pendingChanges = new HashMap<>();
private final File settingsFileInput;
@Inject @Inject
EventBus eventBus; EventBus eventBus;
@Inject @Inject
public ConfigManager(ScheduledExecutorService scheduledExecutorService) public ConfigManager(@Named("config") File config, ScheduledExecutorService scheduledExecutorService)
{ {
this.settingsFileInput = config;
scheduledExecutorService.scheduleWithFixedDelay(this::sendConfig, 30, 30, TimeUnit.SECONDS); scheduledExecutorService.scheduleWithFixedDelay(this::sendConfig, 30, 30, TimeUnit.SECONDS);
} }
@@ -414,7 +415,7 @@ public class ConfigManager
handler.invalidate(); handler.invalidate();
properties.clear(); properties.clear();
try (FileInputStream in = new FileInputStream(SETTINGS_FILE)) try (FileInputStream in = new FileInputStream(settingsFileInput))
{ {
properties.load(new InputStreamReader(in, StandardCharsets.UTF_8)); properties.load(new InputStreamReader(in, StandardCharsets.UTF_8));
} }
@@ -460,9 +461,9 @@ public class ConfigManager
private void saveToFile() throws IOException private void saveToFile() throws IOException
{ {
ConfigManager.SETTINGS_FILE.getParentFile().mkdirs(); settingsFileInput.getParentFile().mkdirs();
File tempFile = new File(RuneLite.RUNELITE_DIR, SETTINGS_FILE_NAME + ".tmp"); File tempFile = new File(RuneLite.RUNELITE_DIR, RuneLite.DEFAULT_CONFIG_FILE.getName() + ".tmp");
try (FileOutputStream out = new FileOutputStream(tempFile)) try (FileOutputStream out = new FileOutputStream(tempFile))
{ {
@@ -473,12 +474,12 @@ public class ConfigManager
try try
{ {
Files.move(tempFile.toPath(), ConfigManager.SETTINGS_FILE.toPath(), StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE); Files.move(tempFile.toPath(), settingsFileInput.toPath(), StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE);
} }
catch (AtomicMoveNotSupportedException ex) catch (AtomicMoveNotSupportedException ex)
{ {
log.debug("atomic move not supported", ex); log.debug("atomic move not supported", ex);
Files.move(tempFile.toPath(), ConfigManager.SETTINGS_FILE.toPath(), StandardCopyOption.REPLACE_EXISTING); Files.move(tempFile.toPath(), settingsFileInput.toPath(), StandardCopyOption.REPLACE_EXISTING);
} }
} }
@@ -0,0 +1,174 @@
/*
* Copyright (c) 2019 Owain van Brakel <https://github.com/Owain94>
* 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.config;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
@ConfigGroup("openosrs")
public interface LauncherConfig extends Config
{
@Getter(AccessLevel.PRIVATE)
@AllArgsConstructor
enum BootstrapMode
{
STABLE("Stable"),
NIGHTLY("Nightly");
private String name;
@Override
public String toString()
{
return getName();
}
}
@ConfigTitleSection(
keyName = "launcherTitle",
name = "Launcher",
description = "",
position = -1
)
default Title launcherTitle()
{
return new Title();
}
@ConfigTitleSection(
keyName = "updateChannelTitle",
name = "Update channel",
description = "",
position = 1,
titleSection = "launcherTitle"
)
default Title updateChannelTitle()
{
return new Title();
}
@ConfigItem(
position = 2,
keyName = "askMode",
name = "Prompt for update channel",
description = "Ask for nightly or stable every startup",
titleSection = "updateChannelTitle"
)
default boolean askMode()
{
return true;
}
@ConfigItem(
keyName = "bootstrapMode",
name = "Update channel",
description = "Select the update channel",
titleSection = "updateChannelTitle",
position = 3,
hide = "askMode"
)
default BootstrapMode bootstrapMode()
{
return BootstrapMode.STABLE;
}
@ConfigTitleSection(
keyName = "miscLauncherTitle",
name = "Miscellaneous",
description = "",
position = 4,
titleSection = "launcherTitle"
)
default Title miscLauncherTitle()
{
return new Title();
}
@ConfigItem(
position = 5,
keyName = "disableHw",
name = "Disable hardware acceleration",
description = "Enable this if you have graphical issues",
titleSection = "miscLauncherTitle",
warning = "Toggling this setting requires a restart of the client"
)
default boolean disableHw()
{
return false;
}
@ConfigTitleSection(
keyName = "advancedTitle",
name = "Advanced",
description = "",
position = 6,
titleSection = "launcherTitle"
)
default Title advancedTitle()
{
return new Title();
}
@ConfigItem(
position = 7,
keyName = "noJvm",
name = "Use system java (caution!)",
description = "Enable this if you want to make use of the system java version instead of the launcher bundled version",
titleSection = "advancedTitle",
warning = "Toggling this setting requires a restart of the client"
)
default boolean noJvm()
{
return false;
}
@ConfigItem(
position = 8,
keyName = "useProxy",
name = "Use SOCKS5 proxy",
description = "Enable the client to use a proxy",
titleSection = "advancedTitle",
warning = "Toggling this setting requires a restart of the client"
)
default boolean useProxy()
{
return false;
}
@ConfigItem(
keyName = "proxyDetails",
name = "Proxy details",
description = "The format for this field is ip:port or ip:port:user:pass",
titleSection = "advancedTitle",
position = 9,
hidden = true,
unhide = "useProxy"
)
default String proxyDetails()
{
return "";
}
}
@@ -31,7 +31,7 @@ import lombok.Value;
/** /**
* Represents Discord Rich Presence RPC data * Represents Discord Rich Presence RPC data
*/ */
@Builder @Builder(toBuilder = true)
@Value @Value
public class DiscordPresence public class DiscordPresence
{ {
@@ -1,7 +1,7 @@
package net.runelite.client.eventbus; package net.runelite.client.eventbus;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import io.reactivex.functions.Consumer; import io.reactivex.rxjava3.functions.Consumer;
import java.lang.invoke.CallSite; import java.lang.invoke.CallSite;
import java.lang.invoke.LambdaMetafactory; import java.lang.invoke.LambdaMetafactory;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;
@@ -1,18 +1,18 @@
package net.runelite.client.eventbus; package net.runelite.client.eventbus;
import com.jakewharton.rxrelay2.PublishRelay; import com.jakewharton.rxrelay3.PublishRelay;
import com.jakewharton.rxrelay2.Relay; import com.jakewharton.rxrelay3.Relay;
import io.reactivex.ObservableTransformer; import io.reactivex.rxjava3.annotations.NonNull;
import io.reactivex.Scheduler; import io.reactivex.rxjava3.core.ObservableTransformer;
import io.reactivex.annotations.NonNull; import io.reactivex.rxjava3.core.Scheduler;
import io.reactivex.annotations.Nullable; import io.reactivex.rxjava3.disposables.CompositeDisposable;
import io.reactivex.disposables.CompositeDisposable; import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.disposables.Disposable; import io.reactivex.rxjava3.functions.Consumer;
import io.reactivex.functions.Consumer;
import io.sentry.Sentry; import io.sentry.Sentry;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import javax.annotation.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -1,7 +1,7 @@
package net.runelite.client.eventbus; package net.runelite.client.eventbus;
import io.reactivex.annotations.NonNull; import io.reactivex.rxjava3.annotations.NonNull;
import io.reactivex.functions.Consumer; import io.reactivex.rxjava3.functions.Consumer;
import net.runelite.api.events.Event; import net.runelite.api.events.Event;
public interface EventBusInterface public interface EventBusInterface
@@ -1,9 +1,9 @@
package net.runelite.client.eventbus; package net.runelite.client.eventbus;
import io.reactivex.Scheduler; import io.reactivex.rxjava3.core.Scheduler;
import io.reactivex.annotations.Nullable; import io.reactivex.rxjava3.functions.Supplier;
import io.reactivex.schedulers.Schedulers; import io.reactivex.rxjava3.schedulers.Schedulers;
import java.util.function.Supplier; import javax.annotation.Nullable;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
@AllArgsConstructor @AllArgsConstructor
@@ -22,6 +22,14 @@ public enum EventScheduler
@Nullable @Nullable
public Scheduler get() public Scheduler get()
{ {
return scheduler.get(); try
{
return scheduler.get();
}
catch (Throwable ignored)
{
}
return null;
} }
} }
@@ -1,6 +1,6 @@
package net.runelite.client.eventbus; package net.runelite.client.eventbus;
import io.reactivex.functions.Consumer; import io.reactivex.rxjava3.functions.Consumer;
import lombok.Value; import lombok.Value;
@Value @Value
@@ -28,8 +28,8 @@ import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader; import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache; import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import io.reactivex.Completable; import io.reactivex.rxjava3.core.Completable;
import io.reactivex.schedulers.Schedulers; import io.reactivex.rxjava3.schedulers.Schedulers;
import java.awt.Color; import java.awt.Color;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.util.ArrayList; import java.util.ArrayList;
@@ -27,8 +27,8 @@ package net.runelite.client.game;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonReader;
import io.reactivex.Completable; import io.reactivex.rxjava3.core.Completable;
import io.reactivex.schedulers.Schedulers; import io.reactivex.rxjava3.schedulers.Schedulers;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@@ -28,11 +28,14 @@ package net.runelite.client.game.chatbox;
import com.google.common.primitives.Ints; import com.google.common.primitives.Ints;
import com.google.inject.Inject; import com.google.inject.Inject;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.function.Consumer; import java.util.function.Consumer;
import javax.inject.Singleton; import javax.inject.Singleton;
import lombok.Getter; import lombok.Getter;
import lombok.Value;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.api.ItemDefinition; import net.runelite.api.ItemDefinition;
import net.runelite.api.widgets.ItemQuantityMode; import net.runelite.api.widgets.ItemQuantityMode;
@@ -66,6 +69,14 @@ public class ChatboxItemSearch extends ChatboxTextInput
@Getter @Getter
private Consumer<Integer> onItemSelected; private Consumer<Integer> onItemSelected;
@Value
private static class ItemIcon
{
private final int modelId;
private final short[] colorsToReplace;
private final short[] texturesToReplace;
}
@Inject @Inject
private ChatboxItemSearch(ChatboxPanelManager chatboxPanelManager, ClientThread clientThread, private ChatboxItemSearch(ChatboxPanelManager chatboxPanelManager, ClientThread clientThread,
ItemManager itemManager, Client client) ItemManager itemManager, Client client)
@@ -287,15 +298,26 @@ public class ChatboxItemSearch extends ChatboxTextInput
return; return;
} }
Set<ItemIcon> itemIcons = new HashSet<>();
for (int i = 0; i < client.getItemCount() && results.size() < MAX_RESULTS; i++) for (int i = 0; i < client.getItemCount() && results.size() < MAX_RESULTS; i++)
{ {
ItemDefinition itemComposition = itemManager.getItemDefinition(itemManager.canonicalize(i)); ItemDefinition itemComposition = itemManager.getItemDefinition(itemManager.canonicalize(i));
String name = itemComposition.getName().toLowerCase(); String name = itemComposition.getName().toLowerCase();
// The client assigns "null" to item names of items it doesn't know about // The client assigns "null" to item names of items it doesn't know about
if (!name.equals("null") && name.contains(search)) // and the item might already be in the results from canonicalize
if (!name.equals("null") && name.contains(search) && !results.containsKey(itemComposition.getId()))
{ {
// This may already be in the map due to canonicalize mapping the item to something we've already seen // Check if the results already contain the same item image
results.putIfAbsent(itemComposition.getId(), itemComposition); ItemIcon itemIcon = new ItemIcon(itemComposition.getInventoryModel(),
itemComposition.getColorToReplaceWith(), itemComposition.getTextureToReplaceWith());
if (itemIcons.contains(itemIcon))
{
continue;
}
itemIcons.add(itemIcon);
results.put(itemComposition.getId(), itemComposition);
} }
} }
} }
@@ -17,6 +17,7 @@ import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@@ -49,7 +50,9 @@ import net.runelite.client.config.OpenOSRSConfig;
import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.EventBus;
import net.runelite.client.events.ExternalPluginChanged; import net.runelite.client.events.ExternalPluginChanged;
import net.runelite.client.events.ExternalRepositoryChanged; import net.runelite.client.events.ExternalRepositoryChanged;
import net.runelite.client.ui.ClientUI;
import net.runelite.client.ui.RuneLiteSplashScreen; import net.runelite.client.ui.RuneLiteSplashScreen;
import net.runelite.client.util.MiscUtils;
import net.runelite.client.util.SwingUtil; import net.runelite.client.util.SwingUtil;
import org.pf4j.DefaultPluginManager; import org.pf4j.DefaultPluginManager;
import org.pf4j.DependencyResolver; import org.pf4j.DependencyResolver;
@@ -77,7 +80,7 @@ class ExternalPluginManager
{ {
public static ArrayList<ClassLoader> pluginClassLoaders = new ArrayList<>(); public static ArrayList<ClassLoader> pluginClassLoaders = new ArrayList<>();
private final PluginManager runelitePluginManager; private final PluginManager runelitePluginManager;
private final org.pf4j.PluginManager externalPluginManager; private org.pf4j.PluginManager externalPluginManager;
@Getter(AccessLevel.PUBLIC) @Getter(AccessLevel.PUBLIC)
private final List<UpdateRepository> repositories = new ArrayList<>(); private final List<UpdateRepository> repositories = new ArrayList<>();
private final OpenOSRSConfig openOSRSConfig; private final OpenOSRSConfig openOSRSConfig;
@@ -85,7 +88,6 @@ class ExternalPluginManager
private final ConfigManager configManager; private final ConfigManager configManager;
private final List<Plugin> plugins = new CopyOnWriteArrayList<>(); private final List<Plugin> plugins = new CopyOnWriteArrayList<>();
private final Map<String, String> pluginsMap = new HashMap<>(); private final Map<String, String> pluginsMap = new HashMap<>();
@Getter(AccessLevel.PUBLIC) @Getter(AccessLevel.PUBLIC)
private UpdateManager updateManager; private UpdateManager updateManager;
@@ -104,9 +106,16 @@ class ExternalPluginManager
//noinspection ResultOfMethodCallIgnored //noinspection ResultOfMethodCallIgnored
EXTERNALPLUGIN_DIR.mkdirs(); EXTERNALPLUGIN_DIR.mkdirs();
initPluginManager();
}
private void initPluginManager()
{
boolean debug = RuneLiteProperties.getLauncherVersion() == null && RuneLiteProperties.getPluginPath() != null; boolean debug = RuneLiteProperties.getLauncherVersion() == null && RuneLiteProperties.getPluginPath() != null;
this.externalPluginManager = new DefaultPluginManager(debug ? Paths.get(RuneLiteProperties.getPluginPath() + File.separator + "release") : EXTERNALPLUGIN_DIR.toPath()) this.externalPluginManager = new DefaultPluginManager(
debug ? Paths.get(RuneLiteProperties.getPluginPath() + File.separator + "release")
: EXTERNALPLUGIN_DIR.toPath())
{ {
@Override @Override
protected PluginDescriptorFinder createPluginDescriptorFinder() protected PluginDescriptorFinder createPluginDescriptorFinder()
@@ -117,7 +126,27 @@ class ExternalPluginManager
@Override @Override
protected PluginRepository createPluginRepository() protected PluginRepository createPluginRepository()
{ {
return new JarPluginRepository(getPluginsRoot()); return new JarPluginRepository(getPluginsRoot())
{
@Override
public List<Path> getPluginPaths()
{
File[] files = pluginsRoot.toFile().listFiles(filter);
if ((files == null) || files.length == 0)
{
return Collections.emptyList();
}
List<Path> paths = new ArrayList<>(files.length);
for (File file : files)
{
paths.add(file.toPath());
}
return paths;
}
};
} }
@Override @Override
@@ -184,22 +213,41 @@ class ExternalPluginManager
this.externalPluginManager.setSystemVersion(SYSTEM_VERSION); this.externalPluginManager.setSystemVersion(SYSTEM_VERSION);
} }
public boolean doesGhRepoExist(String owner, String name)
{
return doesRepoExist("gh:" + owner + "/" + name);
}
/**
* Note that {@link org.pf4j.update.UpdateManager#addRepository} checks if the repo exists, however it throws an exception which is bad
*/
public boolean doesRepoExist(String id)
{
return repositories.stream().anyMatch((repo) -> repo.getId().equals(id));
}
private static URL toRepositoryUrl(String owner, String name) throws MalformedURLException private static URL toRepositoryUrl(String owner, String name) throws MalformedURLException
{ {
return new URL("https://raw.githubusercontent.com/" + owner + "/" + name + "/master/"); return new URL("https://raw.githubusercontent.com/" + owner + "/" + name + "/master/");
} }
public static boolean testRepository(String owner, String name) public static boolean testGHRepository(String owner, String name)
{ {
final List<UpdateRepository> repositories = new ArrayList<>();
try try
{ {
repositories.add(new DefaultUpdateRepository("github", new URL("https://raw.githubusercontent.com/" + owner + "/" + name + "/master/"))); return testRepository(toRepositoryUrl(owner, name));
} }
catch (MalformedURLException e) catch (MalformedURLException e)
{ {
return true; e.printStackTrace();
} }
return false;
}
public static boolean testRepository(URL url)
{
final List<UpdateRepository> repositories = new ArrayList<>();
repositories.add(new DefaultUpdateRepository("repository-testing", url));
DefaultPluginManager testPluginManager = new DefaultPluginManager(EXTERNALPLUGIN_DIR.toPath()); DefaultPluginManager testPluginManager = new DefaultPluginManager(EXTERNALPLUGIN_DIR.toPath());
UpdateManager updateManager = new UpdateManager(testPluginManager, repositories); UpdateManager updateManager = new UpdateManager(testPluginManager, repositories);
@@ -238,9 +286,63 @@ class ExternalPluginManager
} }
public void startExternalUpdateManager() public void startExternalUpdateManager()
{
if (!tryLoadNewFormat())
{
loadOldFormat();
}
this.updateManager = new UpdateManager(this.externalPluginManager, repositories);
saveConfig();
}
public boolean tryLoadNewFormat()
{ {
try try
{ {
for (String keyval : openOSRSConfig.getExternalRepositories().split(";"))
{
String[] split = keyval.split("\\|");
if (split.length != 2)
{
repositories.clear();
return false;
}
String id = split[0];
String url = split[1];
if (!url.endsWith("/"))
{
url = url.concat("/");
}
if (id.contains("https://raw.githubusercontent.com/"))
{
id = "gh:" + id.substring(id.indexOf("https://raw.githubusercontent.com/")).replace("/master", "")
.replace("https://raw.githubusercontent.com/", "");
if (id.endsWith("/"))
{
id = id.substring(0, id.lastIndexOf("/"));
}
}
repositories.add(new DefaultUpdateRepository(id, new URL(url)));
}
}
catch (ArrayIndexOutOfBoundsException | MalformedURLException e)
{
repositories.clear();
return false;
}
return true;
}
public void loadOldFormat()
{
try
{
repositories.clear();
for (String keyval : openOSRSConfig.getExternalRepositories().split(";")) for (String keyval : openOSRSConfig.getExternalRepositories().split(";"))
{ {
String id = keyval.substring(0, keyval.lastIndexOf(":https")); String id = keyval.substring(0, keyval.lastIndexOf(":https"));
@@ -262,14 +364,11 @@ class ExternalPluginManager
this.updateManager = new UpdateManager(this.externalPluginManager, repositories); this.updateManager = new UpdateManager(this.externalPluginManager, repositories);
} }
public void addRepository(String owner, String name) public void addGHRepository(String owner, String name)
{ {
try try
{ {
DefaultUpdateRepository respository = new DefaultUpdateRepository(owner + toRepositoryUrl(owner, name), toRepositoryUrl(owner, name)); addRepository("gh:" + owner + "/" + name, toRepositoryUrl(owner, name));
updateManager.addRepository(respository);
eventBus.post(ExternalRepositoryChanged.class, new ExternalRepositoryChanged(owner + toRepositoryUrl(owner, name), true));
saveConfig();
} }
catch (MalformedURLException e) catch (MalformedURLException e)
{ {
@@ -277,6 +376,14 @@ class ExternalPluginManager
} }
} }
public void addRepository(String key, URL url)
{
DefaultUpdateRepository respository = new DefaultUpdateRepository(key, url);
updateManager.addRepository(respository);
eventBus.post(ExternalRepositoryChanged.class, new ExternalRepositoryChanged(key, true));
saveConfig();
}
public void removeRepository(String owner) public void removeRepository(String owner)
{ {
updateManager.removeRepository(owner); updateManager.removeRepository(owner);
@@ -291,8 +398,8 @@ class ExternalPluginManager
for (UpdateRepository repository : updateManager.getRepositories()) for (UpdateRepository repository : updateManager.getRepositories())
{ {
config.append(repository.getId()); config.append(repository.getId());
config.append(":"); config.append("|");
config.append(repository.getUrl().toString()); config.append(MiscUtils.urlToStringEncoded(repository.getUrl()));
config.append(";"); config.append(";");
} }
config.deleteCharAt(config.lastIndexOf(";")); config.deleteCharAt(config.lastIndexOf(";"));
@@ -333,7 +440,8 @@ class ExternalPluginManager
} }
else if (pluginDescriptor.type() == PluginType.EXTERNAL) else if (pluginDescriptor.type() == PluginType.EXTERNAL)
{ {
log.error("Class {} is using the the new external plugin loader, it should not use PluginType.EXTERNAL", clazz); log.error("Class {} is using the the new external plugin loader, it should not use PluginType.EXTERNAL",
clazz);
continue; continue;
} }
@@ -373,16 +481,21 @@ class ExternalPluginManager
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private Plugin instantiate(List<Plugin> scannedPlugins, Class<Plugin> clazz, boolean init, boolean initConfig) throws PluginInstantiationException private Plugin instantiate(List<Plugin> scannedPlugins, Class<Plugin> clazz, boolean init, boolean initConfig)
throws PluginInstantiationException
{ {
net.runelite.client.plugins.PluginDependency[] pluginDependencies = clazz.getAnnotationsByType(net.runelite.client.plugins.PluginDependency.class); net.runelite.client.plugins.PluginDependency[] pluginDependencies =
clazz.getAnnotationsByType(net.runelite.client.plugins.PluginDependency.class);
List<Plugin> deps = new ArrayList<>(); List<Plugin> deps = new ArrayList<>();
for (net.runelite.client.plugins.PluginDependency pluginDependency : pluginDependencies) for (net.runelite.client.plugins.PluginDependency pluginDependency : pluginDependencies)
{ {
Optional<Plugin> dependency = Stream.concat(runelitePluginManager.getPlugins().stream(), scannedPlugins.stream()).filter(p -> p.getClass() == pluginDependency.value()).findFirst(); Optional<Plugin> dependency =
Stream.concat(runelitePluginManager.getPlugins().stream(), scannedPlugins.stream())
.filter(p -> p.getClass() == pluginDependency.value()).findFirst();
if (!dependency.isPresent()) if (!dependency.isPresent())
{ {
throw new PluginInstantiationException("Unmet dependency for " + clazz.getSimpleName() + ": " + pluginDependency.value().getSimpleName()); throw new PluginInstantiationException(
"Unmet dependency for " + clazz.getSimpleName() + ": " + pluginDependency.value().getSimpleName());
} }
deps.add(dependency.get()); deps.add(dependency.get());
} }
@@ -444,7 +557,9 @@ class ExternalPluginManager
{ {
runelitePluginManager.startPlugin(plugin); runelitePluginManager.startPlugin(plugin);
runelitePluginManager.add(plugin); runelitePluginManager.add(plugin);
eventBus.post(ExternalPluginChanged.class, new ExternalPluginChanged(pluginsMap.get(plugin.getClass().getSimpleName()), plugin, true)); eventBus.post(ExternalPluginChanged.class,
new ExternalPluginChanged(pluginsMap.get(plugin.getClass().getSimpleName()), plugin,
true));
} }
catch (PluginInstantiationException e) catch (PluginInstantiationException e)
{ {
@@ -479,6 +594,21 @@ class ExternalPluginManager
for (PluginWrapper plugin : startedPlugins) for (PluginWrapper plugin : startedPlugins)
{ {
boolean depsLoaded = true;
for (PluginDependency dependency : plugin.getDescriptor().getDependencies())
{
if (startedPlugins.stream().noneMatch(pl -> pl.getPluginId().equals(dependency.getPluginId())))
{
depsLoaded = false;
}
}
if (!depsLoaded)
{
// This should never happen but can crash the client
continue;
}
scannedPlugins.addAll(loadPlugin(plugin.getPluginId())); scannedPlugins.addAll(loadPlugin(plugin.getPluginId()));
} }
@@ -630,7 +760,7 @@ class ExternalPluginManager
try try
{ {
SwingUtil.syncExec(() -> SwingUtil.syncExec(() ->
JOptionPane.showMessageDialog(null, JOptionPane.showMessageDialog(ClientUI.getFrame(),
pluginId + " is outdated and cannot be installed", pluginId + " is outdated and cannot be installed",
"Installation error", "Installation error",
JOptionPane.ERROR_MESSAGE)); JOptionPane.ERROR_MESSAGE));
@@ -678,6 +808,7 @@ class ExternalPluginManager
public void update() public void update()
{ {
boolean error = false;
if (updateManager.hasUpdates()) if (updateManager.hasUpdates())
{ {
List<PluginInfo> updates = updateManager.getUpdates(); List<PluginInfo> updates = updateManager.getUpdates();
@@ -692,14 +823,24 @@ class ExternalPluginManager
if (!updated) if (!updated)
{ {
log.warn("Cannot update plugin '{}'", plugin.id); log.warn("Cannot update plugin '{}'", plugin.id);
error = true;
} }
} }
catch (PluginRuntimeException ex) catch (PluginRuntimeException ex)
{ {
log.warn("Cannot update plugin '{}', the user probably has another client open", plugin.id); log.warn("Cannot update plugin '{}', the user probably has another client open", plugin.id);
error = true;
break;
} }
} }
} }
if (error)
{
initPluginManager();
startExternalUpdateManager();
startExternalPluginManager();
}
} }
public Set<String> getDependencies() public Set<String> getDependencies()
@@ -28,7 +28,7 @@ import com.google.common.collect.ImmutableSet;
import com.google.inject.Binder; import com.google.inject.Binder;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.Module; import com.google.inject.Module;
import io.reactivex.functions.Consumer; import io.reactivex.rxjava3.functions.Consumer;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Set; import java.util.Set;
import lombok.AccessLevel; import lombok.AccessLevel;
@@ -53,8 +53,6 @@ public @interface PluginDescriptor
*/ */
boolean hidden() default false; boolean hidden() default false;
boolean developerPlugin() default false;
boolean loadWhenOutdated() default false; boolean loadWhenOutdated() default false;
PluginType type() default PluginType.UNCATEGORIZED; PluginType type() default PluginType.UNCATEGORIZED;
@@ -56,7 +56,6 @@ import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider; import javax.inject.Provider;
import javax.inject.Singleton; import javax.inject.Singleton;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
@@ -87,7 +86,6 @@ public class PluginManager
*/ */
private static final String PLUGIN_PACKAGE = "net.runelite.client.plugins"; private static final String PLUGIN_PACKAGE = "net.runelite.client.plugins";
private final boolean developerMode;
private final EventBus eventBus; private final EventBus eventBus;
private final Scheduler scheduler; private final Scheduler scheduler;
private final ConfigManager configManager; private final ConfigManager configManager;
@@ -108,13 +106,11 @@ public class PluginManager
@Inject @Inject
@VisibleForTesting @VisibleForTesting
PluginManager( PluginManager(
@Named("developerMode") final boolean developerMode,
final EventBus eventBus, final EventBus eventBus,
final Scheduler scheduler, final Scheduler scheduler,
final ConfigManager configManager, final ConfigManager configManager,
final Provider<GameEventManager> sceneTileManager) final Provider<GameEventManager> sceneTileManager)
{ {
this.developerMode = developerMode;
this.eventBus = eventBus; this.eventBus = eventBus;
this.scheduler = scheduler; this.scheduler = scheduler;
this.configManager = configManager; this.configManager = configManager;
@@ -355,11 +351,6 @@ public class PluginManager
continue; continue;
} }
if (pluginDescriptor.developerPlugin() && !developerMode)
{
continue;
}
@SuppressWarnings("unchecked") Class<Plugin> pluginClass = (Class<Plugin>) clazz; @SuppressWarnings("unchecked") Class<Plugin> pluginClass = (Class<Plugin>) clazz;
graph.addNode(pluginClass); graph.addNode(pluginClass);
} }
@@ -462,10 +453,12 @@ public class PluginManager
} }
catch (ThreadDeath e) catch (ThreadDeath e)
{ {
activePlugins.remove(plugin);
throw e; throw e;
} }
catch (Throwable ex) catch (Throwable ex)
{ {
activePlugins.remove(plugin);
throw new PluginInstantiationException(ex); throw new PluginInstantiationException(ex);
} }
@@ -41,7 +41,6 @@ import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.text.DecimalFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.HashMap; import java.util.HashMap;
@@ -672,11 +671,7 @@ class ConfigPanel extends PluginPanel
if (units != null) if (units != null)
{ {
DecimalFormat df = ((JSpinner.NumberEditor) spinner.getEditor()).getFormat(); spinnerTextField.setFormatterFactory(new UnitFormatterFactory(units));
df.setPositiveSuffix(units.value());
df.setNegativeSuffix(units.value());
// Force update the spinner to have it add the units initially
spinnerTextField.setValue(value);
} }
item.add(spinner, BorderLayout.EAST); item.add(spinner, BorderLayout.EAST);
@@ -812,11 +807,7 @@ class ConfigPanel extends PluginPanel
if (units != null) if (units != null)
{ {
DecimalFormat df = ((JSpinner.NumberEditor) widthSpinner.getEditor()).getFormat(); widthSpinnerTextField.setFormatterFactory(new UnitFormatterFactory(units));
df.setPositiveSuffix(units.value());
df.setNegativeSuffix(units.value());
// Force update the spinner to have it add the units initially
widthSpinnerTextField.setValue(width);
} }
SpinnerModel heightModel = new SpinnerNumberModel(height, 0, Integer.MAX_VALUE, 1); SpinnerModel heightModel = new SpinnerNumberModel(height, 0, Integer.MAX_VALUE, 1);
@@ -827,11 +818,7 @@ class ConfigPanel extends PluginPanel
if (units != null) if (units != null)
{ {
DecimalFormat df = ((JSpinner.NumberEditor) heightSpinner.getEditor()).getFormat(); heightSpinnerTextField.setFormatterFactory(new UnitFormatterFactory(units));
df.setPositiveSuffix(units.value());
df.setNegativeSuffix(units.value());
// Force update the spinner to have it add the units initially
heightSpinnerTextField.setValue(height);
} }
ChangeListener listener = e -> ChangeListener listener = e ->
@@ -24,13 +24,16 @@
*/ */
package net.runelite.client.plugins.config; package net.runelite.client.plugins.config;
import com.github.zafarkhaja.semver.Version;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Provider; import javax.inject.Provider;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import net.runelite.api.MenuOpcode; import net.runelite.api.MenuOpcode;
import net.runelite.client.RuneLiteProperties;
import net.runelite.client.config.ChatColorConfig; import net.runelite.client.config.ChatColorConfig;
import net.runelite.client.config.ConfigManager; import net.runelite.client.config.ConfigManager;
import net.runelite.client.config.LauncherConfig;
import net.runelite.client.config.OpenOSRSConfig; import net.runelite.client.config.OpenOSRSConfig;
import net.runelite.client.config.RuneLiteConfig; import net.runelite.client.config.RuneLiteConfig;
import net.runelite.client.eventbus.Subscribe; import net.runelite.client.eventbus.Subscribe;
@@ -69,6 +72,9 @@ public class ConfigPlugin extends Plugin
@Inject @Inject
private ChatColorConfig chatColorConfig; private ChatColorConfig chatColorConfig;
@Inject
private LauncherConfig launcherConfig;
private PluginListPanel pluginListPanel; private PluginListPanel pluginListPanel;
private NavigationButton navButton; private NavigationButton navButton;
@@ -92,6 +98,18 @@ public class ConfigPlugin extends Plugin
"Chat Color", "Recolor chat text", PluginType.MISCELLANEOUS, new String[]{"colour", "messages"}, "Chat Color", "Recolor chat text", PluginType.MISCELLANEOUS, new String[]{"colour", "messages"},
null, chatColorConfig, configManager.getConfigDescriptor(chatColorConfig) null, chatColorConfig, configManager.getConfigDescriptor(chatColorConfig)
)); ));
// Support for this has been added in launcher version 2.2.0
if (launcherVersion("2.2.0"))
{
pluginListPanel.addFakePlugin(
new PluginConfigurationDescriptor(
"Launcher", "Launcher settings", PluginType.IMPORTANT,
new String[]{"hw", "nightly", "stable", "proxy", "bootstrap"},
null, launcherConfig, configManager.getConfigDescriptor(launcherConfig)
));
}
pluginListPanel.rebuildPluginList(); pluginListPanel.rebuildPluginList();
final BufferedImage icon = ImageUtil.getResourceStreamFromClass(getClass(), "config_icon.png"); final BufferedImage icon = ImageUtil.getResourceStreamFromClass(getClass(), "config_icon.png");
@@ -137,4 +155,16 @@ public class ConfigPlugin extends Plugin
}); });
} }
} }
private boolean launcherVersion(String version)
{
String launcherVersion = RuneLiteProperties.getLauncherVersion();
if (launcherVersion == null)
{
return false;
}
return Version.valueOf(launcherVersion).greaterThanOrEqualTo(Version.valueOf(version));
}
} }
@@ -45,12 +45,9 @@ import net.runelite.client.ui.ColorScheme;
import net.runelite.client.ui.PluginPanel; import net.runelite.client.ui.PluginPanel;
import net.runelite.client.util.ImageUtil; import net.runelite.client.util.ImageUtil;
import net.runelite.client.util.SwingUtil; import net.runelite.client.util.SwingUtil;
import org.apache.commons.text.similarity.JaroWinklerDistance;
public class PluginListItem extends JPanel public class PluginListItem extends JPanel
{ {
private static final JaroWinklerDistance DISTANCE = new JaroWinklerDistance();
private static final ImageIcon CONFIG_ICON; private static final ImageIcon CONFIG_ICON;
private static final ImageIcon CONFIG_ICON_HOVER; private static final ImageIcon CONFIG_ICON_HOVER;
private static final ImageIcon ON_STAR; private static final ImageIcon ON_STAR;
@@ -61,6 +58,7 @@ public class PluginListItem extends JPanel
@Getter @Getter
private final PluginConfigurationDescriptor pluginConfig; private final PluginConfigurationDescriptor pluginConfig;
@Getter
private final List<String> keywords = new ArrayList<>(); private final List<String> keywords = new ArrayList<>();
public JLabel nameLabel; public JLabel nameLabel;
@@ -201,24 +199,6 @@ public class PluginListItem extends JPanel
onOffToggle.setSelected(enabled); onOffToggle.setSelected(enabled);
} }
/**
* Checks if all the search terms in the given list matches at least one keyword.
*
* @return true if all search terms matches at least one keyword, or false if otherwise.
*/
boolean matchesSearchTerms(String[] searchTerms)
{
for (String term : searchTerms)
{
if (keywords.stream().noneMatch((t) -> t.contains(term) ||
DISTANCE.apply(t, term) > 0.9))
{
return false;
}
}
return true;
}
private void openGroupConfigPanel() private void openGroupConfigPanel()
{ {
pluginListPanel.openConfigurationPanel(pluginConfig); pluginListPanel.openConfigurationPanel(pluginConfig);
@@ -381,7 +381,7 @@ public class PluginListPanel extends PluginPanel
final String[] searchTerms = text.toLowerCase().split(" "); final String[] searchTerms = text.toLowerCase().split(" ");
pluginList.forEach(listItem -> pluginList.forEach(listItem ->
{ {
if (pinned == listItem.isPinned() && listItem.matchesSearchTerms(searchTerms)) if (pinned == listItem.isPinned() && Text.matchesSearchTerms(searchTerms, listItem.getKeywords()))
{ {
if (openOSRSConfig.pluginSortMode() == OpenOSRSConfig.SortStyle.ALPHABETICALLY || !openOSRSConfig.enableCategories()) if (openOSRSConfig.pluginSortMode() == OpenOSRSConfig.SortStyle.ALPHABETICALLY || !openOSRSConfig.enableCategories())
{ {
@@ -0,0 +1,86 @@
/*
* Copyright (c) 2020, Hydrox6 <ikada@protonmail.ch>
* 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.config;
import java.text.ParseException;
import java.util.HashMap;
import java.util.Map;
import javax.swing.JFormattedTextField;
import lombok.RequiredArgsConstructor;
import net.runelite.client.config.Units;
final class UnitFormatter extends JFormattedTextField.AbstractFormatter
{
private final String units;
UnitFormatter(Units units)
{
this.units = units.value();
}
@Override
public Object stringToValue(final String text) throws ParseException
{
final String trimmedText;
// Using the spinner controls causes the value to have the unit on the end, so remove it
if (text.endsWith(units))
{
trimmedText = text.substring(0, text.length() - units.length());
}
else
{
trimmedText = text;
}
try
{
return Integer.valueOf(trimmedText);
}
catch (NumberFormatException e)
{
throw new ParseException(trimmedText + " is not an integer.", 0);
}
}
@Override
public String valueToString(final Object value)
{
return value + units;
}
}
@RequiredArgsConstructor
final class UnitFormatterFactory extends JFormattedTextField.AbstractFormatterFactory
{
private final Units units;
private final Map<JFormattedTextField, JFormattedTextField.AbstractFormatter> formatters = new HashMap<>();
@Override
public JFormattedTextField.AbstractFormatter getFormatter(final JFormattedTextField tf)
{
return formatters.computeIfAbsent(tf, (key) -> new UnitFormatter(units));
}
}
@@ -79,11 +79,14 @@ class InfoPanel extends PluginPanel
} }
private JPanel syncPanel; private JPanel syncPanel;
@Inject @Inject
@Nullable @Nullable
private Client client; private Client client;
@Inject @Inject
private ConfigManager configManager; private ConfigManager configManager;
@Inject @Inject
private InfoPlugin plugin; private InfoPlugin plugin;
@@ -104,8 +107,12 @@ class InfoPanel extends PluginPanel
JLabel version = new JLabel(htmlLabel("RuneLite version: ", RuneLiteProperties.getVersion())); JLabel version = new JLabel(htmlLabel("RuneLite version: ", RuneLiteProperties.getVersion()));
version.setFont(smallFont); version.setFont(smallFont);
JLabel plusVersion = new JLabel(htmlLabel("OpenOSRS version: ", RuneLiteProperties.getPlusVersion())); JLabel openOsrsVersion = new JLabel(htmlLabel("OpenOSRS version: ", RuneLiteProperties.getPlusVersion()));
plusVersion.setFont(smallFont); openOsrsVersion.setFont(smallFont);
String launcher = RuneLiteProperties.getLauncherVersion();
JLabel launcherVersion = new JLabel(htmlLabel("Launcher version: ", launcher));
launcherVersion.setFont(smallFont);
JLabel revision = new JLabel(); JLabel revision = new JLabel();
revision.setFont(smallFont); revision.setFont(smallFont);
@@ -119,7 +126,11 @@ class InfoPanel extends PluginPanel
revision.setText(htmlLabel("Oldschool revision: ", engineVer)); revision.setText(htmlLabel("Oldschool revision: ", engineVer));
versionPanel.add(version); versionPanel.add(version);
versionPanel.add(plusVersion); versionPanel.add(openOsrsVersion);
if (launcher != null)
{
versionPanel.add(launcherVersion);
}
versionPanel.add(revision); versionPanel.add(revision);
JPanel actionsContainer = new JPanel(); JPanel actionsContainer = new JPanel();
@@ -6,6 +6,8 @@ import java.awt.Dimension;
import java.awt.event.MouseAdapter; import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import javax.inject.Inject; import javax.inject.Inject;
import javax.swing.ImageIcon; import javax.swing.ImageIcon;
@@ -18,23 +20,28 @@ import javax.swing.JTextField;
import javax.swing.border.EmptyBorder; import javax.swing.border.EmptyBorder;
import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.EventBus;
import net.runelite.client.plugins.ExternalPluginManager; import net.runelite.client.plugins.ExternalPluginManager;
import net.runelite.client.ui.ClientUI;
import net.runelite.client.ui.ColorScheme; import net.runelite.client.ui.ColorScheme;
import net.runelite.client.ui.PluginPanel; import net.runelite.client.ui.PluginPanel;
import net.runelite.client.util.ImageUtil; import net.runelite.client.util.ImageUtil;
public class ExternalPluginManagerPanel extends PluginPanel public class ExternalPluginManagerPanel extends PluginPanel
{ {
private static final ImageIcon ADD_ICON; private static final ImageIcon ADD_ICON_RAW;
private static final ImageIcon ADD_HOVER_ICON; private static final ImageIcon ADD_HOVER_ICON_RAW;
private static final ImageIcon ADD_ICON_GH;
private static final ImageIcon ADD_HOVER_ICON_GH;
static static
{ {
final BufferedImage addIcon = final BufferedImage addIconRaw =
ImageUtil.recolorImage( ImageUtil.getResourceStreamFromClass(ExternalPluginManagerPanel.class, "add_raw_icon.png");
ImageUtil.getResourceStreamFromClass(ExternalPluginManagerPanel.class, "add_icon.png"), ColorScheme.BRAND_BLUE final BufferedImage addIconGh = ImageUtil
); .resizeImage(ImageUtil.getResourceStreamFromClass(ExternalPluginManagerPanel.class, "gh_icon.png"), 14, 14);
ADD_ICON = new ImageIcon(addIcon); ADD_ICON_RAW = new ImageIcon(addIconRaw);
ADD_HOVER_ICON = new ImageIcon(ImageUtil.alphaOffset(addIcon, 0.53f)); ADD_HOVER_ICON_RAW = new ImageIcon(ImageUtil.alphaOffset(addIconRaw, 0.53f));
ADD_ICON_GH = new ImageIcon(addIconGh);
ADD_HOVER_ICON_GH = new ImageIcon(ImageUtil.alphaOffset(addIconGh, 0.53f));
} }
private final ExternalPluginManager externalPluginManager; private final ExternalPluginManager externalPluginManager;
@@ -73,13 +80,17 @@ public class ExternalPluginManagerPanel extends PluginPanel
titlePanel.setBorder(new EmptyBorder(10, 10, 10, 10)); titlePanel.setBorder(new EmptyBorder(10, 10, 10, 10));
JLabel title = new JLabel(); JLabel title = new JLabel();
JLabel addRepo = new JLabel(ADD_ICON); JLabel addGHRepo = new JLabel(ADD_ICON_GH);
JLabel addRawRepo = new JLabel(ADD_ICON_RAW);
JPanel buttonHolder = new JPanel(new BorderLayout());
buttonHolder.setBorder(new EmptyBorder(0, 0, 0, 0));
title.setText("External Plugin Manager"); title.setText("External Plugin Manager");
title.setForeground(Color.WHITE); title.setForeground(Color.WHITE);
addRepo.setToolTipText("Add new repository"); addGHRepo.setToolTipText("Add new GitHub repository");
addRepo.addMouseListener(new MouseAdapter() addGHRepo.addMouseListener(new MouseAdapter()
{ {
@Override @Override
public void mousePressed(MouseEvent mouseEvent) public void mousePressed(MouseEvent mouseEvent)
@@ -91,36 +102,120 @@ public class ExternalPluginManagerPanel extends PluginPanel
"Github Repository name:", name "Github Repository name:", name
}; };
int option = JOptionPane.showConfirmDialog(null, message, "Add repository", JOptionPane.OK_CANCEL_OPTION); int option =
JOptionPane.showConfirmDialog(ClientUI.getFrame(), message, "Add repository", JOptionPane.OK_CANCEL_OPTION);
if (option != JOptionPane.OK_OPTION || owner.getText().equals("") || name.getText().equals("")) if (option != JOptionPane.OK_OPTION || owner.getText().equals("") || name.getText().equals(""))
{ {
return; return;
} }
if (ExternalPluginManager.testRepository(owner.getText(), name.getText())) if (externalPluginManager.doesGhRepoExist(owner.getText(), name.getText()))
{ {
JOptionPane.showMessageDialog(null, "This doesn't appear to be a valid repository.", "Error!", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(ClientUI.getFrame(), "This repository already exists.", "Error!",
JOptionPane.ERROR_MESSAGE);
return; return;
} }
externalPluginManager.addRepository(owner.getText(), name.getText()); if (ExternalPluginManager.testGHRepository(owner.getText(), name.getText()))
{
JOptionPane.showMessageDialog(ClientUI.getFrame(), "This doesn't appear to be a valid repository.", "Error!",
JOptionPane.ERROR_MESSAGE);
return;
}
externalPluginManager.addGHRepository(owner.getText(), name.getText());
} }
@Override @Override
public void mouseEntered(MouseEvent mouseEvent) public void mouseEntered(MouseEvent mouseEvent)
{ {
addRepo.setIcon(ADD_HOVER_ICON); addGHRepo.setIcon(ADD_HOVER_ICON_GH);
} }
@Override @Override
public void mouseExited(MouseEvent mouseEvent) public void mouseExited(MouseEvent mouseEvent)
{ {
addRepo.setIcon(ADD_ICON); addGHRepo.setIcon(ADD_ICON_GH);
} }
}); });
addGHRepo.setBorder(new EmptyBorder(0, 3, 0, 0));
addRawRepo.setToolTipText("Add new raw repository");
addRawRepo.addMouseListener(new MouseAdapter()
{
@Override
public void mousePressed(MouseEvent mouseEvent)
{
JTextField id = new JTextField();
JTextField url = new JTextField();
Object[] message = {
"Repository ID:", id,
"Repository URL:", url
};
int option =
JOptionPane.showConfirmDialog(ClientUI.getFrame(), message, "Add repository", JOptionPane.OK_CANCEL_OPTION);
if (option != JOptionPane.OK_OPTION || id.getText().equals("") || url.getText().equals(""))
{
return;
}
if (id.getText().startsWith("gh:") || id.getText().contains("|"))
{
JOptionPane.showMessageDialog(ClientUI.getFrame(),
"Repository id cannot begin with \"gh:\"\nor contain the pipe character '|'.", "Error!",
JOptionPane.ERROR_MESSAGE);
return;
}
if (externalPluginManager.doesRepoExist(id.getText()))
{
JOptionPane.showMessageDialog(ClientUI.getFrame(),
String.format("The repository with id %s already exists.", id.getText()), "Error!",
JOptionPane.ERROR_MESSAGE);
return;
}
URL urlActual;
try
{
urlActual = new URL(url.getText());
}
catch (MalformedURLException e)
{
JOptionPane.showMessageDialog(ClientUI.getFrame(), "This doesn't appear to be a valid repository.", "Error!",
JOptionPane.ERROR_MESSAGE);
return;
}
if (ExternalPluginManager.testRepository(urlActual))
{
JOptionPane.showMessageDialog(ClientUI.getFrame(), "This doesn't appear to be a valid repository.", "Error!",
JOptionPane.ERROR_MESSAGE);
return;
}
externalPluginManager.addRepository(id.getText(), urlActual);
}
@Override
public void mouseEntered(MouseEvent mouseEvent)
{
addRawRepo.setIcon(ADD_HOVER_ICON_RAW);
}
@Override
public void mouseExited(MouseEvent mouseEvent)
{
addRawRepo.setIcon(ADD_ICON_RAW);
}
});
addRawRepo.setBorder(new EmptyBorder(0, 0, 0, 3));
titlePanel.add(title, BorderLayout.WEST); titlePanel.add(title, BorderLayout.WEST);
titlePanel.add(addRepo, BorderLayout.EAST); buttonHolder.add(addRawRepo, BorderLayout.WEST);
buttonHolder.add(addGHRepo, BorderLayout.EAST);
titlePanel.add(buttonHolder, BorderLayout.EAST);
return titlePanel; return titlePanel;
} }
@@ -30,11 +30,13 @@ import javax.swing.SwingConstants;
import javax.swing.SwingWorker; import javax.swing.SwingWorker;
import javax.swing.border.EmptyBorder; import javax.swing.border.EmptyBorder;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import static net.runelite.api.util.Text.DISTANCE;
import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.EventBus;
import net.runelite.client.events.ExternalPluginChanged; import net.runelite.client.events.ExternalPluginChanged;
import net.runelite.client.events.ExternalRepositoryChanged; import net.runelite.client.events.ExternalRepositoryChanged;
import net.runelite.client.plugins.ExternalPluginManager; import net.runelite.client.plugins.ExternalPluginManager;
import static net.runelite.client.plugins.openosrs.externals.ExternalPluginManagerPanel.wrapContainer; import static net.runelite.client.plugins.openosrs.externals.ExternalPluginManagerPanel.wrapContainer;
import net.runelite.client.ui.ClientUI;
import net.runelite.client.ui.ColorScheme; import net.runelite.client.ui.ColorScheme;
import net.runelite.client.ui.FontManager; import net.runelite.client.ui.FontManager;
import net.runelite.client.ui.PluginPanel; import net.runelite.client.ui.PluginPanel;
@@ -43,7 +45,6 @@ import net.runelite.client.ui.components.shadowlabel.JShadowedLabel;
import net.runelite.client.util.DeferredDocumentChangedListener; import net.runelite.client.util.DeferredDocumentChangedListener;
import net.runelite.client.util.ImageUtil; import net.runelite.client.util.ImageUtil;
import net.runelite.client.util.SwingUtil; import net.runelite.client.util.SwingUtil;
import org.apache.commons.text.similarity.JaroWinklerDistance;
import org.pf4j.update.PluginInfo; import org.pf4j.update.PluginInfo;
import org.pf4j.update.UpdateManager; import org.pf4j.update.UpdateManager;
import org.pf4j.update.UpdateRepository; import org.pf4j.update.UpdateRepository;
@@ -52,7 +53,6 @@ import org.pf4j.update.VerifyException;
@Slf4j @Slf4j
public class PluginsPanel extends JPanel public class PluginsPanel extends JPanel
{ {
private static final JaroWinklerDistance DISTANCE = new JaroWinklerDistance();
private static final ImageIcon ADD_ICON; private static final ImageIcon ADD_ICON;
private static final ImageIcon ADD_HOVER_ICON; private static final ImageIcon ADD_HOVER_ICON;
private static final ImageIcon DELETE_ICON; private static final ImageIcon DELETE_ICON;
@@ -257,7 +257,7 @@ public class PluginsPanel extends JPanel
if (availablePlugins == null || plugins == null) if (availablePlugins == null || plugins == null)
{ {
JOptionPane.showMessageDialog(null, "The external plugin list could not be loaded.", "Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(ClientUI.getFrame(), "The external plugin list could not be loaded.", "Error", JOptionPane.ERROR_MESSAGE);
return; return;
} }
@@ -465,7 +465,7 @@ public class PluginsPanel extends JPanel
{ {
if (hideAction) if (hideAction)
{ {
JOptionPane.showMessageDialog(null, "This plugin can't be uninstalled because one or more other plugins have a dependency on it.", "Error!", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(ClientUI.getFrame(), "This plugin can't be uninstalled because one or more other plugins have a dependency on it.", "Error!", JOptionPane.ERROR_MESSAGE);
} }
else else
{ {
@@ -573,7 +573,7 @@ public class PluginsPanel extends JPanel
try try
{ {
SwingUtil.syncExec(() -> SwingUtil.syncExec(() ->
JOptionPane.showMessageDialog(null, pluginInfo.name + " could not be installed, the hash could not be verified.", "Error!", JOptionPane.ERROR_MESSAGE)); JOptionPane.showMessageDialog(ClientUI.getFrame(), pluginInfo.name + " could not be installed, the hash could not be verified.", "Error!", JOptionPane.ERROR_MESSAGE));
} }
catch (InvocationTargetException | InterruptedException ignored) catch (InvocationTargetException | InterruptedException ignored)
{ {
@@ -58,8 +58,12 @@ public class RepositoryBox extends JPanel
setLayout(new BorderLayout()); setLayout(new BorderLayout());
setBackground(ColorScheme.DARKER_GRAY_COLOR); setBackground(ColorScheme.DARKER_GRAY_COLOR);
String name = updateRepository.getId().replace(updateRepository.getUrl().toString(), ""); String name = updateRepository.getId();
String urlString = updateRepository.getUrl().toString().replace("https://raw.githubusercontent.com/", "").replace("/master/", ""); String urlString = updateRepository.getUrl().toString();
if (urlString.startsWith("/"))
{
urlString = urlString.substring(1);
}
JPanel titleWrapper = new JPanel(new BorderLayout()); JPanel titleWrapper = new JPanel(new BorderLayout());
titleWrapper.setBackground(ColorScheme.DARKER_GRAY_COLOR); titleWrapper.setBackground(ColorScheme.DARKER_GRAY_COLOR);
@@ -145,11 +149,31 @@ public class RepositoryBox extends JPanel
titleWrapper.add(titleActions, BorderLayout.EAST); titleWrapper.add(titleActions, BorderLayout.EAST);
JMultilineLabel repository = new JMultilineLabel(); JMultilineLabel repository = new JMultilineLabel();
repository.setText(urlString.split("/", 2)[1]); repository.setText(formatURL(urlString));
repository.setFont(smallFont); repository.setFont(smallFont);
repository.setDisabledTextColor(Color.WHITE); repository.setDisabledTextColor(Color.WHITE);
String finalUrlString = urlString;
repository.addMouseListener(new MouseAdapter()
{
@Override
public void mouseClicked(MouseEvent e)
{
LinkBrowser.browse(formatURL(finalUrlString));
}
});
add(titleWrapper, BorderLayout.NORTH); add(titleWrapper, BorderLayout.NORTH);
add(repository, BorderLayout.CENTER); add(repository, BorderLayout.CENTER);
} }
private String formatURL(String url)
{
if (url.contains("githubusercontent"))
{
url = url.replace("raw.githubusercontent", "github").replace("/master/", "");
}
return url;
}
} }
@@ -29,7 +29,6 @@ import java.applet.Applet;
import java.awt.BorderLayout; import java.awt.BorderLayout;
import java.awt.Color; import java.awt.Color;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.swing.JFrame;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.JPanel; import javax.swing.JPanel;
import net.runelite.api.Client; import net.runelite.api.Client;
@@ -65,13 +64,13 @@ final class ClientPanel extends JPanel
{ {
String message = "Detected a bad codebase. Resetting...\n" String message = "Detected a bad codebase. Resetting...\n"
+ "Please restart client.\n"; + "Please restart client.\n";
JOptionPane.showMessageDialog(new JFrame(), message, "Bad Codebase", JOptionPane.showMessageDialog(ClientUI.getFrame(), message, "Bad Codebase",
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
StringFileUtils.writeStringToFile(RuneLite.RUNELITE_DIR + "/codebase", "http://127.0.0.1/"); StringFileUtils.writeStringToFile(RuneLite.RUNELITE_DIR + "/codebase", "http://127.0.0.1/");
} }
else else
{ {
JOptionPane.showMessageDialog(new JFrame(), "Error loading Oldschool RuneScape!", "Error", JOptionPane.showMessageDialog(ClientUI.getFrame(), "Error loading Oldschool RuneScape!", "Error",
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
Sentry.capture(e); Sentry.capture(e);
} }
@@ -667,7 +667,7 @@ public class ClientUI
return; return;
} }
final java.awt.Point hotspot = new java.awt.Point(container.getX(), container.getY()); final java.awt.Point hotspot = new java.awt.Point(0, 0);
final Cursor cursorAwt = Toolkit.getDefaultToolkit().createCustomCursor(image, hotspot, name); final Cursor cursorAwt = Toolkit.getDefaultToolkit().createCustomCursor(image, hotspot, name);
container.setCursor(cursorAwt); container.setCursor(cursorAwt);
} }
@@ -0,0 +1,247 @@
/*
* Copyright (c) 2018, Shingyx <https://github.com/Shingyx>
* 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.ui.components;
import java.awt.Component;
import java.awt.Container;
import java.awt.LayoutManager;
import java.awt.Point;
import java.awt.dnd.DragSource;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.HashMap;
import java.util.Map;
import javax.swing.BoxLayout;
import javax.swing.JLayeredPane;
/**
* Pane which allows reordering its components via drag and drop.
* <p>
* For child components' popup menus, implement the PopupMenuOwner interface in the child components.
*/
public class DragAndDropReorderPane extends JLayeredPane
{
private Point dragStartPoint;
private Component draggingComponent;
private int dragIndex = -1;
private final Map<Integer, PopupMenuOwner> popupMenuCandidates = new HashMap<>(); // keyed by mouse button
public DragAndDropReorderPane()
{
super();
setLayout(new DragAndDropReorderLayoutManager());
MouseAdapter mouseAdapter = new DragAndDropReorderMouseAdapter();
addMouseListener(mouseAdapter);
addMouseMotionListener(mouseAdapter);
}
@Override
public void setLayout(LayoutManager layoutManager)
{
if (layoutManager != null && !(layoutManager instanceof DragAndDropReorderLayoutManager))
{
throw new IllegalArgumentException("DragAndDropReorderPane only supports DragAndDropReorderLayoutManager");
}
super.setLayout(layoutManager);
}
private void startDragging(Point point)
{
draggingComponent = getDefaultLayerComponentAt(dragStartPoint);
if (draggingComponent == null)
{
dragStartPoint = null;
return;
}
dragIndex = getPosition(draggingComponent);
setLayer(draggingComponent, DRAG_LAYER);
moveDraggingComponent(point);
}
private void drag(Point point)
{
moveDraggingComponent(point);
Component component = getDefaultLayerComponentAt(point);
if (component != null)
{
int index = getPosition(component);
dragIndex = index < dragIndex ? index : index + 1;
revalidate();
}
}
private void finishDragging()
{
if (draggingComponent != null)
{
setLayer(draggingComponent, DEFAULT_LAYER, dragIndex);
revalidate();
}
dragStartPoint = null;
draggingComponent = null;
dragIndex = -1;
}
private void moveDraggingComponent(Point point)
{
// place the center of the dragging component onto the mouse cursor
int y = point.y - draggingComponent.getHeight() / 2;
// clamp the height to stay within the pane
y = Math.max(y, 0);
y = Math.min(y, getHeight() - draggingComponent.getHeight());
draggingComponent.setLocation(new Point(0, y));
}
private Component getDefaultLayerComponentAt(Point point)
{
for (Component component : getComponentsInLayer(DEFAULT_LAYER))
{
if (component.contains(point.x - component.getX(), point.y - component.getY()))
{
return component;
}
}
return null;
}
private class DragAndDropReorderLayoutManager extends BoxLayout
{
private DragAndDropReorderLayoutManager()
{
super(DragAndDropReorderPane.this, BoxLayout.Y_AXIS);
}
@Override
public void layoutContainer(Container target)
{
if (draggingComponent != null)
{
// temporarily move the dragging component to the default layer for correct layout calculation
Point location = draggingComponent.getLocation();
setLayer(draggingComponent, DEFAULT_LAYER, dragIndex);
super.layoutContainer(target);
setLayer(draggingComponent, DRAG_LAYER);
draggingComponent.setLocation(location);
}
else
{
super.layoutContainer(target);
}
}
}
private class DragAndDropReorderMouseAdapter extends MouseAdapter
{
@Override
public void mousePressed(MouseEvent e)
{
Point point = e.getPoint();
int mouseButton = e.getButton();
if (mouseButton == MouseEvent.BUTTON1)
{
// candidate for dragging
if (popupMenuCandidates.isEmpty() && getComponentCount() > 1)
{
dragStartPoint = point;
}
}
else
{
if (dragStartPoint != null)
{
finishDragging();
}
else
{
// candidate for child popup menu
Component component = getDefaultLayerComponentAt(point);
if (component instanceof PopupMenuOwner)
{
PopupMenuOwner popupMenuCandidate = (PopupMenuOwner) component;
if (e.isPopupTrigger())
{
popupMenuCandidate.getPopupMenu().show(DragAndDropReorderPane.this, point.x, point.y);
}
else
{
popupMenuCandidates.put(mouseButton, popupMenuCandidate);
}
}
}
}
}
@Override
public void mouseDragged(MouseEvent e)
{
if (dragStartPoint == null)
{
return;
}
Point point = e.getPoint();
if (contains(point))
{
if (draggingComponent == null)
{
if (point.distance(dragStartPoint) > DragSource.getDragThreshold())
{
startDragging(point);
}
}
else
{
drag(point);
}
}
else
{
finishDragging();
}
}
@Override
public void mouseReleased(MouseEvent e)
{
Point point = e.getPoint();
int mouseButton = e.getButton();
if (mouseButton == MouseEvent.BUTTON1)
{
finishDragging();
}
else
{
PopupMenuOwner popupMenuCandidate = popupMenuCandidates.remove(mouseButton);
if (popupMenuCandidate != null && e.isPopupTrigger())
{
popupMenuCandidate.getPopupMenu().show(DragAndDropReorderPane.this, point.x, point.y);
}
}
}
}
}
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2018, Shingyx <https://github.com/Shingyx>
* 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.ui.components;
import javax.swing.JPopupMenu;
/**
* Represents a UI component which has a popup menu, to be used on child components inside DragAndDropReorderPane.
* This is because using setComponentPopupMenu consumes the MouseEvents required for drag and drop reordering.
*/
public interface PopupMenuOwner
{
JPopupMenu getPopupMenu();
}
@@ -63,6 +63,7 @@ public class WidgetOverlay extends Overlay
.put(WidgetInfo.LMS_INFO, OverlayPosition.TOP_CENTER) .put(WidgetInfo.LMS_INFO, OverlayPosition.TOP_CENTER)
.put(WidgetInfo.LMS_KDA, OverlayPosition.TOP_CENTER) .put(WidgetInfo.LMS_KDA, OverlayPosition.TOP_CENTER)
.put(WidgetInfo.THEATRE_OF_BLOOD_HEALTH_ORBS, OverlayPosition.TOP_LEFT) .put(WidgetInfo.THEATRE_OF_BLOOD_HEALTH_ORBS, OverlayPosition.TOP_LEFT)
.put(WidgetInfo.GAUNTLET_TIMER_CONTAINER, OverlayPosition.TOP_LEFT)
.build(); .build();
public static Collection<WidgetOverlay> createOverlays(final Client client) public static Collection<WidgetOverlay> createOverlays(final Client client)
@@ -44,7 +44,6 @@ import net.runelite.client.ui.overlay.components.TooltipComponent;
public class TooltipOverlay extends Overlay public class TooltipOverlay extends Overlay
{ {
private static final int UNDER_OFFSET = 24; private static final int UNDER_OFFSET = 24;
private static final int ABOVE_OFFSET = -20;
private static final int PADDING = 2; private static final int PADDING = 2;
private final TooltipManager tooltipManager; private final TooltipManager tooltipManager;
private final Client client; private final Client client;
@@ -84,50 +83,28 @@ public class TooltipOverlay extends Overlay
private Dimension renderTooltips(Graphics2D graphics, List<Tooltip> tooltips) private Dimension renderTooltips(Graphics2D graphics, List<Tooltip> tooltips)
{ {
final Rectangle clientCanvasBounds = new Rectangle(client.getRealDimensions()); final int canvasWidth = client.getCanvasWidth();
final int canvasHeight = client.getCanvasHeight();
final net.runelite.api.Point mouseCanvasPosition = client.getMouseCanvasPosition(); final net.runelite.api.Point mouseCanvasPosition = client.getMouseCanvasPosition();
final int offset = runeLiteConfig.tooltipPosition() == TooltipPositionType.UNDER_CURSOR ? UNDER_OFFSET : ABOVE_OFFSET; final Rectangle prevBounds = getBounds();
final Point mousePosition = new Point(mouseCanvasPosition.getX(), mouseCanvasPosition.getY() + offset);
final Rectangle bounds = new Rectangle(getBounds());
bounds.setLocation(mousePosition);
if (!clientCanvasBounds.contains(bounds)) final int tooltipX = Math.min(canvasWidth - prevBounds.width, mouseCanvasPosition.getX());
{ final int tooltipY = runeLiteConfig.tooltipPosition() == TooltipPositionType.ABOVE_CURSOR
final int clientX = (int) clientCanvasBounds.getMaxX(); ? Math.max(0, mouseCanvasPosition.getY() - prevBounds.height)
final int clientY = (int) clientCanvasBounds.getMaxY(); : Math.min(canvasHeight - prevBounds.height, mouseCanvasPosition.getY() + UNDER_OFFSET);
final int boundsX = (int) bounds.getMaxX();
final int boundsY = (int) bounds.getMaxY();
if (boundsY > clientY) final Rectangle newBounds = new Rectangle(tooltipX, tooltipY, 0, 0);
{
graphics.translate(0, -bounds.height - offset);
}
if (boundsX > clientX)
{
graphics.translate(-bounds.width + clientCanvasBounds.width - bounds.x, 0);
}
}
final Rectangle newBounds = new Rectangle(-1, -1, 0, 0);
for (Tooltip tooltip : tooltips) for (Tooltip tooltip : tooltips)
{ {
final TooltipComponent tooltipComponent = new TooltipComponent(); final TooltipComponent tooltipComponent = new TooltipComponent();
tooltipComponent.setModIcons(client.getModIcons()); tooltipComponent.setModIcons(client.getModIcons());
tooltipComponent.setText(tooltip.getText()); tooltipComponent.setText(tooltip.getText());
tooltipComponent.setPosition(new Point(tooltipX, tooltipY + newBounds.height));
if (newBounds.contains(mousePosition))
{
mousePosition.move(mouseCanvasPosition.getX(), mouseCanvasPosition.getY() + offset + newBounds.height);
}
tooltipComponent.setPosition(mousePosition);
final Dimension dimension = tooltipComponent.render(graphics); final Dimension dimension = tooltipComponent.render(graphics);
// Create incremental tooltip newBounds // Create incremental tooltip newBounds
newBounds.x = newBounds.x != -1 ? Math.min(newBounds.x, mousePosition.x) : mousePosition.x;
newBounds.y = newBounds.y != -1 ? Math.min(newBounds.y, mousePosition.y) : mousePosition.y;
newBounds.height += dimension.height + PADDING; newBounds.height += dimension.height + PADDING;
newBounds.width = Math.max(newBounds.width, dimension.width); newBounds.width = Math.max(newBounds.width, dimension.width);
} }
@@ -0,0 +1,64 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2018 by rumatoest at github.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package net.runelite.client.util;
/**
* The Class AppLock.
*
* @author Vladislav Zablotsky
*/
public class AppLock
{
private static CrossLock lockInstance;
/**
* Set lock for application instance.
* Method must be run only one time at application start.
*
* @param lockId Unique lock identifiers
* @return true if succeeded
*/
public synchronized boolean lock(String lockId)
{
if (lockInstance == null)
{
lockInstance = new CrossLock("application_" + lockId);
}
return lockInstance.lock();
}
/**
* Trying to release application lock.
* Thus another application instances will be able to use lock with current ID.
*/
public synchronized void release()
{
if (lockInstance != null)
{
lockInstance.clear();
}
lockInstance = null;
}
}
@@ -0,0 +1,228 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2018 by rumatoest at github.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package net.runelite.client.util;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.channels.OverlappingFileLockException;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import static net.runelite.client.RuneLite.RUNELITE_DIR;
/**
* Universal cross application instances locker.
* Allow you to create simple lock like object which can be used for
* different application instances. Basic idea is simple - just a simple file lock.
* <br />
* All you need is to define unique key for each lock type.
*
* @author Vladislav Zablotsky
*/
public class CrossLock
{
private static final HashMap<String, CrossLock> locks = new HashMap<>();
private final String id;
private final File fileToLock;
private FileOutputStream fileStream;
private FileChannel fileStreamChannel;
private FileLock lockOnFile;
/**
* Will create or retrieve lock instance.
* Each lock id is unique among all you instances,
* thus only one instance can acquire lock for this id.
*
* @param lockId Unique lock identifier
* @return Not null
*/
public static CrossLock get(String lockId)
{
if (locks.containsKey(lockId))
{
return locks.get(lockId);
}
else
{
synchronized (CrossLock.class)
{
if (locks.containsKey(lockId))
{
return locks.get(lockId);
}
else
{
CrossLock cl = new CrossLock(lockId);
locks.put(lockId, cl);
return cl;
}
}
}
}
/**
* Will remove lock object for specific id and release lock if any.
*
* @param lockId Unique lock identifier
*/
public static void remove(String lockId)
{
if (locks.containsKey(lockId))
{
CrossLock lock = null;
synchronized (CrossLock.class)
{
if (locks.containsKey(lockId))
{
lock = locks.remove(lockId);
}
}
if (lock != null)
{
lock.release();
}
}
}
CrossLock(String lockId)
{
this.id = lockId;
fileToLock = new File(RUNELITE_DIR, lockId + ".app_lock");
}
/**
* Return lock instance identifier.
*/
public String id()
{
return this.id;
}
/**
* Activate lock.
* Note! This is only cross application (cross instances) lock. It will not work
* as lock inside single application instance.
*
* @return true if lock was acquire or false
*/
public synchronized boolean lock()
{
if (lockOnFile != null && lockOnFile.isValid())
{
return true;
}
else
{
release();
}
String lockContent = "#Java AppLock Object\n#Locked by key: " + id() + "\r\n";
try
{
if (fileToLock.exists())
{
fileToLock.createNewFile();
}
fileStream = new FileOutputStream(fileToLock);
fileStreamChannel = fileStream.getChannel();
lockOnFile = fileStreamChannel.tryLock();
if (lockOnFile != null)
{
fileStream.write(lockContent.getBytes());
}
}
catch (Exception ex)
{
if (!(ex instanceof OverlappingFileLockException))
{
Logger.getLogger(AppLock.class.getName()).log(Level.WARNING,
"Can not get application lock for id=" + id() + "\n" + ex.getMessage(), ex);
}
return false;
}
return lockOnFile != null;
}
/**
* Release lock associated with this object.
*/
public synchronized void release()
{
try
{
if (lockOnFile != null && lockOnFile.isValid())
{
lockOnFile.release();
}
lockOnFile = null;
if (fileStream != null)
{
fileStream.close();
fileStream = null;
}
if (fileStreamChannel != null && fileStreamChannel.isOpen())
{
fileStreamChannel.close();
}
fileStreamChannel = null;
}
catch (IOException ex)
{
Logger.getLogger(AppLock.class.getName()).log(Level.WARNING,
"Can not get application lock for id=" + id() + "\n" + ex.getMessage(), ex);
}
}
/**
* Release lock and remove lock file.
*/
public synchronized void clear()
{
release();
if (fileToLock.exists())
{
fileToLock.delete();
}
}
@Override
protected void finalize() throws Throwable
{
this.clear();
super.finalize();
}
}
@@ -24,7 +24,7 @@
*/ */
package net.runelite.client.util; package net.runelite.client.util;
import io.reactivex.annotations.NonNull; import io.reactivex.rxjava3.annotations.NonNull;
import java.util.Queue; import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import javax.inject.Inject; import javax.inject.Inject;
@@ -25,6 +25,7 @@
*/ */
package net.runelite.client.util; package net.runelite.client.util;
import com.google.common.base.Strings;
import java.awt.Toolkit; import java.awt.Toolkit;
import java.awt.TrayIcon; import java.awt.TrayIcon;
import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.Clipboard;
@@ -40,6 +41,7 @@ import java.text.SimpleDateFormat;
import java.util.Base64; import java.util.Base64;
import java.util.Date; import java.util.Date;
import java.util.EnumSet; import java.util.EnumSet;
import javax.annotation.Nullable;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@@ -80,10 +82,11 @@ public class ImageCapture
* *
* @param screenshot BufferedImage to capture. * @param screenshot BufferedImage to capture.
* @param fileName Filename to use, without file extension. * @param fileName Filename to use, without file extension.
* @param subDir Directory within the player screenshots dir to store the captured screenshot to.
* @param notify Send a notification to the system tray when the image is captured. * @param notify Send a notification to the system tray when the image is captured.
* @param imageUploadStyle which method to use to upload the screenshot (Imgur or directly to clipboard). * @param imageUploadStyle which method to use to upload the screenshot (Imgur or directly to clipboard).
*/ */
public void takeScreenshot(BufferedImage screenshot, String fileName, boolean notify, ImageUploadStyle imageUploadStyle) public void takeScreenshot(BufferedImage screenshot, String fileName, @Nullable String subDir, boolean notify, ImageUploadStyle imageUploadStyle)
{ {
if (client.getGameState() == GameState.LOGIN_SCREEN) if (client.getGameState() == GameState.LOGIN_SCREEN)
{ {
@@ -106,6 +109,12 @@ public class ImageCapture
{ {
playerDir += "-League"; playerDir += "-League";
} }
if (!Strings.isNullOrEmpty(subDir))
{
playerDir += File.separator + subDir;
}
playerFolder = new File(SCREENSHOT_DIR, playerDir); playerFolder = new File(SCREENSHOT_DIR, playerDir);
} }
else else
@@ -157,6 +166,20 @@ public class ImageCapture
} }
} }
/**
* Saves a screenshot of the client window to the screenshot folder as a PNG,
* and optionally uploads it to an image-hosting service.
*
* @param screenshot BufferedImage to capture.
* @param fileName Filename to use, without file extension.
* @param notify Send a notification to the system tray when the image is captured.
* @param imageUploadStyle which method to use to upload the screenshot (Imgur or directly to clipboard).
*/
public void takeScreenshot(BufferedImage screenshot, String fileName, boolean notify, ImageUploadStyle imageUploadStyle)
{
takeScreenshot(screenshot, fileName, null, notify, imageUploadStyle);
}
/** /**
* Uploads a screenshot to the Imgur image-hosting service, * Uploads a screenshot to the Imgur image-hosting service,
* and copies the image link to the clipboard. * and copies the image link to the clipboard.
@@ -36,6 +36,7 @@ import javax.inject.Singleton;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.runelite.client.ui.ClientUI;
/** /**
* Utility class used for web and file browser navigation * Utility class used for web and file browser navigation
@@ -249,7 +250,7 @@ public class LinkBrowser
{ {
SwingUtilities.invokeLater(() -> SwingUtilities.invokeLater(() ->
{ {
final int result = JOptionPane.showConfirmDialog(null, message, "Message", final int result = JOptionPane.showConfirmDialog(ClientUI.getFrame(), message, "Message",
JOptionPane.OK_CANCEL_OPTION); JOptionPane.OK_CANCEL_OPTION);
if (result == JOptionPane.OK_OPTION) if (result == JOptionPane.OK_OPTION)
@@ -1,12 +1,17 @@
package net.runelite.client.util; package net.runelite.client.util;
import java.awt.Polygon;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.api.Player; import net.runelite.api.Player;
import net.runelite.api.WorldType; import net.runelite.api.WorldType;
import net.runelite.api.coords.WorldPoint; import net.runelite.api.coords.WorldPoint;
import java.awt.Polygon;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class MiscUtils public class MiscUtils
{ {
@@ -170,4 +175,28 @@ public class MiscUtils
} }
return str; return str;
} }
/**
* Mostly stolen from {@link java.net.URLStreamHandler#toExternalForm(URL)}
*
* @param url URL to encode
* @return URL, with path, query and ref encoded
*/
public static String urlToStringEncoded(URL url)
{
String s;
String path = url.getPath() != null ? Stream.of(url.getPath().split("/"))
.map(s2 -> URLEncoder.encode(s2, StandardCharsets.UTF_8)).collect(Collectors.joining("/")) : "";
return url.getProtocol()
+ ':'
+ (((s = url.getAuthority()) != null && s.length() > 0) ? "//" + s : "")
+ (path)
+ (((s = url.getQuery()) != null) ? '?' + urlEncode(s) : "")
+ (((s = url.getRef()) != null) ? '#' + urlEncode(s) : "");
}
private static String urlEncode(String s)
{
return URLEncoder.encode(s, StandardCharsets.UTF_8);
}
} }
@@ -1401,11 +1401,13 @@
], ],
"coal bag": [ "coal bag": [
764, 764,
12019 12019,
24480
], ],
"gem bag": [ "gem bag": [
766, 766,
12020 12020,
24481
], ],
"phoenix crossbow": [ "phoenix crossbow": [
767, 767,
@@ -7609,6 +7611,10 @@
11736, 11736,
11737 11737
], ],
"herb box": [
11738,
11739
],
"armadyl crossbow": [ "armadyl crossbow": [
11785, 11785,
23611 23611
@@ -7815,6 +7821,10 @@
11912, 11912,
11914 11914
], ],
"slice of birthday cake": [
11916,
11917
],
"dragon pickaxe": [ "dragon pickaxe": [
11920, 11920,
12797, 12797,
@@ -8271,6 +8281,10 @@
13222, 13222,
13224 13224
], ],
"herb sack": [
13226,
24478
],
"eternal boots": [ "eternal boots": [
13235, 13235,
23644 23644
@@ -8539,6 +8553,10 @@
13576, 13576,
20785 20785
], ],
"seed box": [
13639,
24482
],
"farmers boro trousers": [ "farmers boro trousers": [
13640, 13640,
13641 13641
@@ -9692,9 +9710,5 @@
24469, 24469,
24472, 24472,
24475 24475
],
"cat ears": [
24522,
24525
] ]
} }
Binary file not shown.

After

Width:  |  Height:  |  Size: 384 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 580 B

File diff suppressed because one or more lines are too long
@@ -11,6 +11,5 @@ open.osrs.builddate=@open.osrs.builddate@
runelite.wiki.troubleshooting.link=https://github.com/open-osrs/runelite/wiki/Troubleshooting-problems-with-the-client runelite.wiki.troubleshooting.link=https://github.com/open-osrs/runelite/wiki/Troubleshooting-problems-with-the-client
runelite.wiki.building.link=https://github.com/open-osrs/runelite/wiki/Building-with-IntelliJ-IDEA runelite.wiki.building.link=https://github.com/open-osrs/runelite/wiki/Building-with-IntelliJ-IDEA
runelite.dnschange.link=https://1.1.1.1/dns/ runelite.dnschange.link=https://1.1.1.1/dns/
launcher.version=@launcher.version@
plugin.path=@plugin.path@ plugin.path=@plugin.path@
runelite.imgur.client.id=30d71e5f6860809 runelite.imgur.client.id=30d71e5f6860809
@@ -3,7 +3,17 @@
.string_stack_count 0 .string_stack_count 0
.int_var_count 35 .int_var_count 35
.string_var_count 1 .string_var_count 1
sconst "bankLayoutInit" ; callback "beforeBankLayout"
; Fired before the bank starts its layout
; Used by the TabInterface to hide fake bank items for tag tabs
;
; callback "setBankScroll"
; Fired before bank is calculated
; Used by the TabInterface to show fake bank items for tag tabs
;
; callback "isTabMenuActive"
; Used by the TabInterface to skip setting the bank title
sconst "beforeBankLayout"
runelite_callback runelite_callback
get_varbit 5102 get_varbit 5102
iconst 1 iconst 1
@@ -387,6 +397,15 @@ LABEL339:
sub sub
istore 29 istore 29
LABEL343: LABEL343:
iconst 0 ; Scroll height variable
iconst 0 ; Compare variable
iconst 0 ;
sconst "setBankScroll" ; Show fake bank items for tag tabs
runelite_callback ; If tag tab menu search isn't active
if_icmpeq CONTINUE_SEARCH ; continue to normal bank search
istore 27 ; Load scroll height into variable
jump GetTabRange ; Skip normal bank layout
CONTINUE_SEARCH:
iload 30 iload 30
iload 29 iload 29
iconst 1 iconst 1
@@ -826,12 +845,12 @@ LABEL740:
invoke 514 invoke 514
iconst 1 iconst 1
if_icmpeq LABEL744 if_icmpeq LABEL744
jump LABEL747 jump GetTabRange
LABEL744: LABEL744:
iconst 1 iconst 1
iconst 1 iconst 1
invoke 299 invoke 299
LABEL747: GetTabRange:
iconst -1 iconst -1
istore 31 istore 31
iconst -1 iconst -1
@@ -848,7 +867,7 @@ LABEL759:
iload 19 iload 19
iconst 816 iconst 816
if_icmplt LABEL763 if_icmplt LABEL763
jump LABEL843 jump SetTitle
LABEL763: LABEL763:
iload 2 iload 2
iload 19 iload 19
@@ -940,12 +959,17 @@ LABEL838:
add add
istore 19 istore 19
jump LABEL759 jump LABEL759
LABEL843: SetTitle:
iconst 0 ; Compare variable
iconst 0 ;
sconst "isTabMenuActive" ; Check if tag tab menu
runelite_callback ; is active and skip setting
if_icmpne FinishBuilding ; the bank title if it is
get_varbit 4170 get_varbit 4170
iconst 2 iconst 2
if_icmpeq LABEL847 if_icmpeq SetTitleRomanNumeral
jump LABEL857 jump SetTitleNumber
LABEL847: SetTitleRomanNumeral:
sconst "Tab " sconst "Tab "
iconst 105 iconst 105
iconst 115 iconst 115
@@ -957,8 +981,8 @@ LABEL847:
runelite_callback ; runelite_callback ;
iload 5 iload 5
if_settext if_settext
jump LABEL863 jump FinishBuilding
LABEL857: SetTitleNumber:
sconst "Tab " sconst "Tab "
get_varbit 4150 get_varbit 4150
tostring tostring
@@ -967,7 +991,7 @@ LABEL857:
runelite_callback ; runelite_callback ;
iload 5 iload 5
if_settext if_settext
LABEL863: FinishBuilding:
iload 0 iload 0
iload 1 iload 1
iload 2 iload 2
@@ -1 +1 @@
15660E39A740C416BFD71621A448A96FA6B5C5E8AD212179F3D6785AE35CAA38 A9BA4723E7D91AD151C1AB3ABEAF84971BFFD71AA8C23E763ECCC8981A8A1429
@@ -47,7 +47,7 @@ LABEL23:
get_varbit 8119 get_varbit 8119
iconst 1 iconst 1
if_icmpeq LABEL42 if_icmpeq LABEL42
jump LABEL144 jump LABEL146
LABEL42: LABEL42:
iconst 105 iconst 105
iconst 115 iconst 115
@@ -96,11 +96,13 @@ LABEL77:
iload 4 iload 4
iconst 1 iconst 1
if_icmpeq LABEL86 if_icmpeq LABEL86
jump LABEL101 jump LABEL103
LABEL86: LABEL86:
iconst 60
iconst 5 iconst 5
iload 3 iload 3
add add
invoke 1045
iconst 30 iconst 30
iconst 0 iconst 0
iconst 0 iconst 0
@@ -112,8 +114,8 @@ LABEL86:
iconst 2 iconst 2
iconst 10616871 iconst 10616871
if_setposition if_setposition
jump LABEL113 jump LABEL115
LABEL101: LABEL103:
iconst 0 iconst 0
iconst 30 iconst 30
iconst 0 iconst 0
@@ -126,26 +128,26 @@ LABEL101:
iconst 2 iconst 2
iconst 10616871 iconst 10616871
if_setposition if_setposition
LABEL113: LABEL115:
iload 3 iload 3
iconst 10616889 iconst 10616889
if_getwidth if_getwidth
if_icmpgt LABEL118 if_icmpgt LABEL120
jump LABEL124 jump LABEL126
LABEL118: LABEL120:
iconst 2 iconst 2
iconst 2 iconst 2
iconst 0 iconst 0
iconst 10616889 iconst 10616889
if_settextalign if_settextalign
jump LABEL129 jump LABEL131
LABEL124: LABEL126:
iconst 0 iconst 0
iconst 2 iconst 2
iconst 0 iconst 0
iconst 10616889 iconst 10616889
if_settextalign if_settextalign
LABEL129: LABEL131:
iconst 10616889 iconst 10616889
if_clearops if_clearops
iconst -1 iconst -1
@@ -160,8 +162,8 @@ LABEL129:
sconst "" sconst ""
iconst 10616889 iconst 10616889
if_setonop if_setonop
jump LABEL185 jump LABEL187
LABEL144: LABEL146:
iconst 105 iconst 105
iconst 115 iconst 115
iconst 1894 iconst 1894
@@ -203,7 +205,7 @@ LABEL144:
sconst "ii" sconst "ii"
iconst 10616889 iconst 10616889
if_setonop if_setonop
LABEL185: LABEL187:
sload 2 sload 2
iconst 10616889 iconst 10616889
if_settext if_settext
@@ -1 +0,0 @@
C70BDF62710D9FC0EB6707BD94FC0C4335B428DEDD1B52DD51776F811F32C9CF
@@ -1,802 +0,0 @@
.id 1658
.int_stack_count 15
.string_stack_count 0
.int_var_count 25
.string_var_count 1
; Callback "clanChatChannelRebuild" for whenever clan chat is done being built, used inside ClanChatPlugin for ignores
iload 3
iconst 6
iconst 7
iconst 6
sconst "Sort by rank"
iload 0
iload 1
iload 2
iload 3
iload 4
iload 5
iload 6
iload 7
iload 8
iload 9
iload 10
iload 11
iload 12
iload 13
iload 14
invoke 1659
iload 4
iconst 2
iconst 3
iconst 2
sconst "Sort by name"
iload 0
iload 1
iload 2
iload 3
iload 4
iload 5
iload 6
iload 7
iload 8
iload 9
iload 10
iload 11
iload 12
iload 13
iload 14
invoke 1659
iload 5
iconst 8
iconst 9
iconst 9
sconst "Sort by last world change"
iload 0
iload 1
iload 2
iload 3
iload 4
iload 5
iload 6
iload 7
iload 8
iload 9
iload 10
iload 11
iload 12
iload 13
iload 14
invoke 1659
iload 6
iconst 4
iconst 5
iconst 4
sconst "Sort by world"
iload 0
iload 1
iload 2
iload 3
iload 4
iload 5
iload 6
iload 7
iload 8
iload 9
iload 10
iload 11
iload 12
iload 13
iload 14
invoke 1659
iload 7
iconst 0
iconst 1
iconst 0
sconst "Legacy sort"
iload 0
iload 1
iload 2
iload 3
iload 4
iload 5
iload 6
iload 7
iload 8
iload 9
iload 10
iload 11
iload 12
iload 13
iload 14
invoke 1659
3644
get_varc_int 185
switch
1: LABEL109
2: LABEL112
3: LABEL115
4: LABEL184
5: LABEL212
6: LABEL118
7: LABEL148
8: LABEL178
9: LABEL181
jump LABEL239
LABEL109:
iconst 0
3645
jump LABEL239
LABEL112:
iconst 1
3646
jump LABEL239
LABEL115:
iconst 0
3646
jump LABEL239
LABEL118:
iconst 1
3657
get_varc_int 206
switch
3: LABEL125
4: LABEL128
5: LABEL135
8: LABEL142
9: LABEL145
iconst 1
3646
jump LABEL147
LABEL125:
iconst 0
3646
jump LABEL147
LABEL128:
iconst 1
3652
iconst 1
3647
iconst 1
3646
jump LABEL147
LABEL135:
iconst 1
3652
iconst 0
3647
iconst 1
3646
jump LABEL147
LABEL142:
iconst 1
3648
jump LABEL147
LABEL145:
iconst 0
3648
LABEL147:
jump LABEL239
LABEL148:
iconst 0
3657
get_varc_int 206
switch
3: LABEL155
4: LABEL158
5: LABEL165
8: LABEL172
9: LABEL175
iconst 1
3646
jump LABEL177
LABEL155:
iconst 0
3646
jump LABEL177
LABEL158:
iconst 1
3652
iconst 1
3647
iconst 1
3646
jump LABEL177
LABEL165:
iconst 1
3652
iconst 0
3647
iconst 1
3646
jump LABEL177
LABEL172:
iconst 1
3648
jump LABEL177
LABEL175:
iconst 0
3648
LABEL177:
jump LABEL239
LABEL178:
iconst 1
3648
jump LABEL239
LABEL181:
iconst 0
3648
jump LABEL239
LABEL184:
iconst 1
3652
iconst 1
3647
get_varc_int 206
switch
3: LABEL193
6: LABEL196
7: LABEL201
8: LABEL206
9: LABEL209
iconst 1
3646
jump LABEL211
LABEL193:
iconst 0
3646
jump LABEL211
LABEL196:
iconst 1
3657
iconst 1
3646
jump LABEL211
LABEL201:
iconst 0
3657
iconst 1
3646
jump LABEL211
LABEL206:
iconst 1
3648
jump LABEL211
LABEL209:
iconst 0
3648
LABEL211:
jump LABEL239
LABEL212:
iconst 1
3652
iconst 0
3647
get_varc_int 206
switch
3: LABEL221
6: LABEL224
7: LABEL229
8: LABEL234
9: LABEL237
iconst 1
3646
jump LABEL239
LABEL221:
iconst 0
3646
jump LABEL239
LABEL224:
iconst 1
3657
iconst 1
3646
jump LABEL239
LABEL229:
iconst 0
3657
iconst 1
3646
jump LABEL239
LABEL234:
iconst 1
3648
jump LABEL239
LABEL237:
iconst 0
3648
LABEL239:
3655
iload 8
cc_deleteall
clan_getchatcount
istore 15
get_varbit 6363
iconst 1
if_icmpeq LABEL248
jump LABEL296
LABEL248:
iload 15
iconst 0
if_icmpgt LABEL252
jump LABEL253
LABEL252:
clan_leavechat
LABEL253:
iconst 0
istore 15
iconst 0
iload 2
if_sethide
iconst 1
iload 9
if_sethide
iload 11
invoke 2067
pop_int
iconst -1
sconst ""
iload 11
if_setonmouserepeat
iconst -1
sconst ""
iload 11
if_setonmouseleave
iload 13
invoke 2067
pop_int
iconst -1
sconst ""
iload 13
if_setonmouserepeat
iconst -1
sconst ""
iload 13
if_setonmouseleave
sconst "<col=7f7f7f>"
sconst "---"
sconst "</col>"
join_string 3
iload 12
if_settext
iload 12
if_clearops
iconst -1
sconst ""
iload 12
if_setonop
jump LABEL341
LABEL296:
iconst 1
iload 2
if_sethide
iconst 0
iload 9
if_sethide
iload 11
invoke 486
pop_int
iconst 94
iconst -2147483645
sconst "I"
iload 11
if_setonmouserepeat
iconst 92
iconst -2147483645
sconst "I"
iload 11
if_setonmouseleave
iload 13
invoke 486
pop_int
iconst 94
iconst -2147483645
sconst "I"
iload 13
if_setonmouserepeat
iconst 92
iconst -2147483645
sconst "I"
iload 13
if_setonmouseleave
sconst "Clan Setup"
iload 12
if_settext
iconst 1
sconst "Clan Setup"
iload 12
if_setop
iconst 489
iconst -2147483644
iconst 1
sconst "ii"
iload 12
if_setonop
LABEL341:
sconst ""
sstore 0
iconst -1
istore 16
iconst -1
istore 17
clan_getchatrank
istore 18
clan_getchatminkick
istore 19
iload 3
if_getwidth
istore 20
iconst 0
istore 21
iconst 0
istore 22
iconst 15
istore 23
invoke 1972
iconst 1
if_icmpeq LABEL364
jump LABEL369
LABEL364:
iconst 8
iconst 5
iload 23
scale
istore 23
LABEL369:
iconst 0
istore 24
LABEL371:
iload 24
iload 15
if_icmplt LABEL375
jump LABEL572
LABEL375:
iload 24
clan_getchatusername
iload 24
clan_getchatuserworld
iload 24
clan_getchatuserrank
istore 17
istore 16
sstore 0
iload 8
iconst 4
iload 21
cc_create
iload 21
iconst 1
add
istore 21
iload 20
iload 23
iconst 1
iconst 0
cc_setsize
iconst 0
iload 22
iconst 2
iconst 0
cc_setposition
iconst 494
cc_settextfont
iconst 0
iconst 1
iconst 0
cc_settextalign
sload 0
cc_settext
iconst 16777215
cc_setcolour
iconst 0
cc_settextshadow
iload 8
iconst 4
iload 21
cc_create 1
iload 21
iconst 1
add
istore 21
iload 20
iload 23
iconst 1
iconst 0
cc_setsize 1
iconst 0
iload 22
iconst 2
iconst 0
cc_setposition 1
iconst 494
cc_settextfont 1
iconst 2
iconst 1
iconst 0
cc_settextalign 1
sconst "World "
iload 16
tostring
join_string 2
cc_settext 1
iload 16
map_world
if_icmpeq LABEL447
jump LABEL450
LABEL447:
iconst 901389
cc_setcolour 1
jump LABEL452
LABEL450:
iconst 16777060
cc_setcolour 1
LABEL452:
iconst 0
cc_settextshadow 1
iload 8
iconst 5
iload 21
cc_create 1
iload 21
iconst 1
add
istore 21
iconst 9
iconst 9
iconst 0
iconst 0
cc_setsize 1
iconst 1
iload 22
iload 23
iconst 9
sub
iconst 2
div
add
iconst 0
iconst 0
cc_setposition 1
iconst 105
iconst 100
iconst 706
iload 17
enum
cc_setgraphic 1
iload 24
clan_isself
iconst 0
if_icmpeq LABEL489
jump LABEL525
LABEL489:
iload 24
clan_isfriend
iconst 1
if_icmpeq LABEL494
jump LABEL501
LABEL494:
iconst 9
sconst "Remove friend"
cc_setop
iconst 9
sconst "Remove friend"
cc_setop 1
jump LABEL525
LABEL501:
iload 24
clan_isignore
iconst 1
if_icmpeq LABEL506
jump LABEL513
LABEL506:
iconst 10
sconst "Remove ignore"
cc_setop
iconst 10
sconst "Remove ignore"
cc_setop 1
jump LABEL525
LABEL513:
iconst 7
sconst "Add friend"
cc_setop
iconst 7
sconst "Add friend"
cc_setop 1
iconst 8
sconst "Add ignore"
cc_setop
iconst 8
sconst "Add ignore"
cc_setop 1
LABEL525:
invoke 1942
iconst 0
if_icmpeq LABEL529
jump LABEL543
LABEL529:
iload 18
iload 19
if_icmpge LABEL533
jump LABEL543
LABEL533:
iload 18
iload 17
if_icmpgt LABEL537
jump LABEL543
LABEL537:
iconst 6
sconst "Kick user"
cc_setop
iconst 6
sconst "Kick user"
cc_setop 1
LABEL543:
sconst "<col=ff9040>"
sload 0
sconst "</col>"
join_string 3
cc_setopbase
sconst "<col=ff9040>"
sload 0
sconst "</col>"
join_string 3
cc_setopbase 1
iconst 214
sconst "event_opbase"
iconst -2147483644
sconst "si"
cc_setonop
iconst 214
sconst "event_opbase"
iconst -2147483644
sconst "si"
cc_setonop 1
iload 24
iconst 1
add
iload 22
iload 23
add
istore 22
istore 24
jump LABEL371
LABEL572:
iload 15
iconst 1
if_icmpge LABEL576
jump LABEL580
LABEL576:
iload 22
iconst 5
add
istore 22
LABEL580:
iload 10
if_clearops
get_varbit 6363
iconst 1
if_icmpeq LABEL586
jump LABEL605
LABEL586:
sconst ""
iload 0
if_settext
sconst ""
iload 1
if_settext
sconst "<col=7f7f7f>"
sconst "---"
sconst "</col>"
join_string 3
iload 10
if_settext
iload 10
if_clearops
iconst -1
sconst ""
iload 10
if_setonop
jump LABEL672
LABEL605:
iload 15
iconst 0
if_icmpgt LABEL609
jump LABEL653
LABEL609:
sconst "<col=ffff64>"
clan_getchatdisplayname
sconst "</col>"
join_string 3
iload 0
if_settext
sconst "<col=ffffff>"
clan_getchatownername
sconst "</col>"
join_string 3
iload 1
if_settext
sconst "Leave Chat"
iload 10
if_settext
get_varbit 5432
iconst 1
if_icmpeq LABEL631
get_varbit 4289
iconst 0
if_icmpne LABEL631
jump LABEL642
LABEL631:
iconst 6
sconst "Leave Chat"
iload 10
if_setop
iconst 194
iconst -2147483644
iconst 6
sconst "ii"
iload 10
if_setonop
jump LABEL652
LABEL642:
iconst 1
sconst "Leave Chat"
iload 10
if_setop
iconst 194
iconst -2147483644
iconst 1
sconst "ii"
iload 10
if_setonop
LABEL652:
jump LABEL672
LABEL653:
sconst "Not in chat"
iload 0
if_settext
sconst "None"
iload 1
if_settext
sconst "Join Chat"
iload 10
if_settext
iconst 1
sconst "Join Chat"
iload 10
if_setop
iconst 194
iconst -2147483644
iconst 1
sconst "ii"
iload 10
if_setonop
LABEL672:
iload 22
iload 8
if_getheight
if_icmpgt LABEL677
jump LABEL687
LABEL677:
iconst 0
iload 22
iload 8
if_setscrollsize
iload 9
iload 8
iload 8
if_getscrolly
invoke 72
jump LABEL695
LABEL687:
iconst 0
iconst 0
iload 8
if_setscrollsize
iload 9
iload 8
iconst 0
invoke 72
LABEL695:
sconst "clanChatChannelRebuild"
runelite_callback
return
@@ -1 +0,0 @@
15F58F5939D9311F3D76FA2F0F3441B7B0DA1E8EAE23C654948095A7D51E07F0
@@ -1,634 +0,0 @@
.id 1601
.int_stack_count 4
.string_stack_count 2
.int_var_count 14
.string_var_count 3
; callback "itemsKeptOnDeath"
; Used by the ItemsKepthOnDeath plugin to edit the interface
; Put a rune pouch in your inventory and it shouldn't have a white outline
; in the Items kept on death screen
sload 1
iconst 262167
if_settext
iconst 0
istore 4
iconst 0
istore 5
iconst -1
istore 6
iconst 0
istore 7
sconst ""
sstore 2
iconst 0
istore 8
iconst 0
istore 9
iconst 0
istore 10
iconst 0
istore 11
iload 1
define_array 111
iconst 0
istore 12
iconst 0
istore 13
iload 0
iconst 0
if_icmpeq LABEL31
jump LABEL525
LABEL31:
iconst 93
iconst 13190
inv_total
iconst 0
if_icmpgt LABEL42
iconst 93
iconst 13192
inv_total
iconst 0
if_icmpgt LABEL42
jump LABEL44
LABEL42:
iconst 1
istore 9
LABEL44:
iload 10
iload 1
if_icmplt LABEL48
jump LABEL88
LABEL48:
iconst 584
iload 11
inv_getobj
istore 6
iload 6
iconst -1
if_icmpne LABEL56
jump LABEL85
LABEL56:
iconst 584
iload 11
inv_getnum
istore 7
LABEL60:
iload 10
iload 1
if_icmplt LABEL64
jump LABEL80
LABEL64:
iload 7
iconst 0
if_icmpgt LABEL68
jump LABEL80
LABEL68:
iload 10
iload 6
set_array_int
iload 7
iconst 1
sub
istore 7
iload 10
iconst 1
add
istore 10
jump LABEL60
LABEL80:
iload 11
iconst 1
add
istore 11
jump LABEL87
LABEL85:
iload 1
istore 10
LABEL87:
jump LABEL44
LABEL88:
iload 4
iload 1
if_icmplt LABEL92
jump LABEL147
LABEL92:
iconst 262162
iconst 5
iload 4
cc_create
iconst 36
iconst 32
iconst 0
iconst 0
cc_setsize
iconst 5
iload 4
iconst 40
multiply
add
iconst 25
iconst 0
iconst 0
cc_setposition
iload 4
get_array_int
istore 6
iload 6
iconst -1
if_icmpne LABEL117
jump LABEL144
LABEL117:
iload 6
iconst 1
cc_setobject
sconst "<col=ff981f>"
iload 6
oc_name
join_string 2
cc_setopbase
iconst 1
sconst "Item:"
cc_setop
iconst 1603
iconst 1
iconst 1
iload 6
oc_name
sconst "1is"
cc_setonop
iconst 1118481
cc_setgraphicshadow
iconst 1
cc_setoutline
iload 4
iconst 1
add
istore 4
jump LABEL146
LABEL144:
iload 1
istore 4
LABEL146:
jump LABEL88
LABEL147:
iconst 0
istore 4
LABEL149:
iload 4
iconst 468
inv_size
if_icmplt LABEL154
jump LABEL350
LABEL154:
iconst 468
iload 4
inv_getobj
istore 6
iload 6
iconst -1
if_icmpne LABEL162
jump LABEL345
LABEL162:
iconst 262165
iconst 5
iload 5
cc_create
iconst 36
iconst 32
iconst 0
iconst 0
cc_setsize
iconst 5
iload 5
iconst 8
mod
iconst 38
multiply
add
iconst 25
iconst 38
iload 5
iconst 8
div
multiply
add
iconst 0
iconst 0
cc_setposition
iload 6
iconst 468
iload 4
inv_getnum
cc_setobject
sconst "<col=ff981f>"
iload 6
oc_name
join_string 2
cc_setopbase
iconst 1
sconst "Item:"
cc_setop
iconst 1603
iconst 0
iconst 468
iload 4
inv_getnum
iload 6
oc_name
sconst "1is"
cc_setonop
iconst 1118481
cc_setgraphicshadow
iconst 111
iconst 49
iconst 879
iload 6
oc_uncert
enum
iconst 1
if_icmpeq LABEL221
jump LABEL226
LABEL221:
iconst 2
cc_setoutline
iconst 1
istore 8
jump LABEL228
LABEL226:
iconst 1
cc_setoutline
LABEL228:
iload 5
iconst 1
add
istore 5
iload 6
oc_stackable
iconst 1
if_icmpeq LABEL237
jump LABEL345
LABEL237:
iconst 0
istore 10
iconst 0
istore 13
LABEL241:
iload 10
iload 1
if_icmplt LABEL245
jump LABEL259
LABEL245:
iload 10
get_array_int
iload 6
if_icmpeq LABEL250
jump LABEL254
LABEL250:
iload 13
iconst 1
add
istore 13
LABEL254:
iload 10
iconst 1
add
istore 10
jump LABEL241
LABEL259:
iconst 2147483647
iconst 94
iload 6
inv_total
sub
iconst 93
iload 6
inv_total
sub
iload 13
add
istore 12
iconst 0
iload 12
sub
istore 12
iload 12
iconst 0
if_icmpgt LABEL279
jump LABEL345
LABEL279:
iconst 262165
iconst 5
iload 5
cc_create
iconst 36
iconst 32
iconst 0
iconst 0
cc_setsize
iconst 5
iload 5
iconst 8
mod
iconst 38
multiply
add
iconst 25
iconst 38
iload 5
iconst 8
div
multiply
add
iconst 0
iconst 0
cc_setposition
iload 6
iload 12
cc_setobject
sconst "<col=ff981f>"
iload 6
oc_name
join_string 2
cc_setopbase
iconst 1
sconst "Item:"
cc_setop
iconst 1603
iconst 0
iload 12
iload 6
oc_name
sconst "1is"
cc_setonop
iconst 1118481
cc_setgraphicshadow
iconst 111
iconst 49
iconst 879
iload 6
oc_uncert
enum
iconst 1
if_icmpeq LABEL334
jump LABEL339
LABEL334:
iconst 2
cc_setoutline
iconst 1
istore 8
jump LABEL341
LABEL339:
iconst 1
cc_setoutline
LABEL341:
iload 5
iconst 1
add
istore 5
LABEL345:
iload 4
iconst 1
add
istore 4
jump LABEL149
LABEL350:
sconst "The normal amount of items kept is "
sconst "three"
sconst "."
sconst "<br>"
sconst "<br>"
join_string 5
sstore 2
iload 3
iconst 1
if_icmpeq LABEL361
jump LABEL371
LABEL361:
sload 2
sconst "You're an "
sconst "<col=ff3333>"
sconst "Ultimate Iron Man"
sconst "<col=ff981f>"
sconst ", so you will always keep zero items."
join_string 5
append
sstore 2
jump LABEL434
LABEL371:
iload 1
iconst 0
if_icmpeq LABEL375
jump LABEL387
LABEL375:
sload 2
sconst "You're marked with a "
sconst "<col=ff3333>"
sconst "PK skull"
sconst "<col=ff981f>"
sconst ". This reduces the items you keep from "
sconst "three"
sconst " to zero!"
join_string 7
append
sstore 2
jump LABEL434
LABEL387:
iload 1
iconst 1
if_icmpeq LABEL391
jump LABEL410
LABEL391:
sload 2
sconst "You're marked with a "
sconst "<col=ff3333>"
sconst "PK skull"
sconst "<col=ff981f>"
sconst ". This reduces the items you keep from "
sconst "three"
sconst " to zero!"
sconst "<br>"
sconst "<br>"
sconst "However, you also have the "
sconst "<col=ff3333>"
sconst "Protect Items"
sconst "<col=ff981f>"
sconst " prayer active, which saves you one extra item!"
join_string 14
append
sstore 2
jump LABEL434
LABEL410:
iload 1
iconst 3
if_icmpeq LABEL414
jump LABEL419
LABEL414:
sload 2
sconst "You have no factors affecting the items you keep."
append
sstore 2
jump LABEL434
LABEL419:
iload 1
iconst 3
iconst 1
add
if_icmpeq LABEL425
jump LABEL434
LABEL425:
sload 2
sconst "You have the "
sconst "<col=ff3333>"
sconst "Protect Items"
sconst "<col=ff981f>"
sconst " prayer active, which saves you one extra item!"
join_string 5
append
sstore 2
LABEL434:
iload 8
iconst 1
if_icmpeq LABEL441
iload 9
iconst 1
if_icmpeq LABEL441
jump LABEL492
LABEL441:
iload 8
iconst 1
if_icmpeq LABEL445
jump LABEL466
LABEL445:
iload 9
iconst 1
if_icmpeq LABEL449
jump LABEL466
LABEL449:
sload 2
sconst "<br>"
sconst "<br>"
sconst "Items with a "
sconst "<col=ffffff>"
sconst "white outline"
sconst "<col=ff981f>"
sconst " will always be lost."
sconst "<br>"
sconst "<col=00ff00>"
sconst "Bonds"
sconst "</col>"
sconst " are always protected."
join_string 12
append
sstore 2
jump LABEL492
LABEL466:
iload 8
iconst 1
if_icmpeq LABEL470
jump LABEL482
LABEL470:
sload 2
sconst "<br>"
sconst "<br>"
sconst "Items with a "
sconst "<col=ffffff>"
sconst "white outline"
sconst "<col=ff981f>"
sconst " will always be lost."
join_string 7
append
sstore 2
jump LABEL492
LABEL482:
sload 2
sconst "<br>"
sconst "<br>"
sconst "<col=00ff00>"
sconst "Bonds"
sconst "</col>"
sconst " are always protected, so are not shown here."
join_string 6
append
sstore 2
LABEL492:
sload 2
iconst 262173
if_settext
sconst "<col=ffcc33>"
sconst "Max items kept on death :"
sconst "<br>"
sconst "<br>"
sconst "<col=ffcc33>"
sconst "~ "
iload 1
tostring
sconst " ~"
join_string 8
iconst 262174
if_settext
iload 2
iconst 0
if_icmpgt LABEL511
jump LABEL518
LABEL511:
sconst "Items you will keep on death:"
iconst 262161
if_settext
sconst "Items you will lose on death:"
iconst 262164
if_settext
jump LABEL524
LABEL518:
sconst "Items you will keep on death if not skulled:"
iconst 262161
if_settext
sconst "Items you will lose on death if not skulled:"
iconst 262164
if_settext
LABEL524:
jump LABEL565
LABEL525:
iconst 1
iconst 262165
if_sethide
iconst 1
iconst 262162
if_sethide
iconst 0
iconst 262175
if_sethide
sload 0
iconst 262176
if_settext
sconst "The normal amount of items kept is "
sconst "three"
sconst "."
sconst "<br>"
sconst "<br>"
join_string 5
sstore 2
sload 2
sconst "You're in a "
sconst "<col=ff3333>"
sconst "safe area"
sconst "<col=ff981f>"
sconst ". See information to the left for a more detailed description."
join_string 5
append
sstore 2
sload 2
iconst 262173
if_settext
sconst "<col=ffcc33>"
sconst "Max items kept on death :"
sconst "<br>"
sconst "<br>"
sconst "<col=ffcc33>"
sconst "All items!"
join_string 6
iconst 262174
if_settext
LABEL565:
sconst "itemsKeptOnDeath" ; push event name
runelite_callback ; invoke callback
return
@@ -1 +0,0 @@
B370DDEEF61E0F420C1990DDA4FBBEDCEE8324F3750ABAC79B072A27268D887B
@@ -1,394 +0,0 @@
.id 779
.int_stack_count 15
.string_stack_count 0
.int_var_count 16
.string_var_count 1
get_varbit 4397
iconst 1
if_icmpeq LABEL4
jump LABEL65
LABEL4:
iload 0
iload 1
cc_find
iconst 1
if_icmpeq LABEL10
jump LABEL12
LABEL10:
iconst 1
cc_sethide
LABEL12:
iload 0
iload 6
cc_find
iconst 1
if_icmpeq LABEL18
jump LABEL23
LABEL18:
iconst 0
cc_settrans
iconst -1
sconst ""
cc_setontimer
LABEL23:
iload 0
iload 12
cc_find
iconst 1
if_icmpeq LABEL29
jump LABEL31
LABEL29:
iconst 1
cc_sethide
LABEL31:
iload 0
iload 4
cc_find
iconst 1
if_icmpeq LABEL37
jump LABEL39
LABEL37:
sconst "Sell offer"
cc_settext
LABEL39:
iload 0
iload 5
cc_find
iconst 1
if_icmpeq LABEL45
jump LABEL47
LABEL45:
iconst 1119
cc_setgraphic
LABEL47:
iload 0
iload 2
cc_find
iconst 1
if_icmpeq LABEL53
jump LABEL56
LABEL53:
iconst 1
sconst "All"
cc_setop
LABEL56:
iload 0
iload 3
cc_find
iconst 1
if_icmpeq LABEL62
jump LABEL64
LABEL62:
sconst "All"
cc_settext
LABEL64:
jump LABEL130
LABEL65:
iload 0
iload 1
cc_find
iconst 1
if_icmpeq LABEL71
jump LABEL73
LABEL71:
iconst 0
cc_sethide
LABEL73:
iload 0
iload 6
cc_find
iconst 1
if_icmpeq LABEL79
jump LABEL89
LABEL79:
iconst 100
cc_settrans
iconst 811
iconst -2147483645
iconst -2147483643
clientclock
iconst 100
iconst 250
sconst "Iiiii"
cc_setontimer
LABEL89:
iload 0
iload 12
cc_find
iconst 1
if_icmpeq LABEL95
jump LABEL97
LABEL95:
iconst 0
cc_sethide
LABEL97:
iload 0
iload 4
cc_find
iconst 1
if_icmpeq LABEL103
jump LABEL105
LABEL103:
sconst "Buy offer"
cc_settext
LABEL105:
iload 0
iload 5
cc_find
iconst 1
if_icmpeq LABEL111
jump LABEL113
LABEL111:
iconst 1118
cc_setgraphic
LABEL113:
iload 0
iload 2
cc_find
iconst 1
if_icmpeq LABEL119
jump LABEL122
LABEL119:
iconst 1
sconst "+1K"
cc_setop
LABEL122:
iload 0
iload 3
cc_find
iconst 1
if_icmpeq LABEL128
jump LABEL130
LABEL128:
sconst "+1K"
cc_settext
LABEL130:
sconst ","
sstore 0
iconst 0
istore 15
get_varp 1151
iconst -1
if_icmpne LABEL138
jump LABEL274
LABEL138:
iload 0
iload 7
cc_find
iconst 1
if_icmpeq LABEL144
jump LABEL147
LABEL144:
get_varp 1151
get_varbit 4396
cc_setobject_nonum
LABEL147:
iload 0
iload 8
cc_find
iconst 1
if_icmpeq LABEL153
jump LABEL156
LABEL153:
get_varp 1151
oc_name
cc_settext
LABEL156:
iload 0
iload 9
cc_find
iconst 1
if_icmpeq LABEL162
jump LABEL166
LABEL162:
get_varbit 4396
sload 0
invoke 46
cc_settext
LABEL166:
iload 0
iload 10
cc_find
iconst 1
if_icmpeq LABEL172
jump LABEL185
LABEL172:
get_varbit 4398
iconst 1
if_icmpeq LABEL176
jump LABEL179
LABEL176:
sconst "1 coin"
cc_settext
jump LABEL185
LABEL179:
get_varbit 4398
sload 0
invoke 46
sconst " coins"
join_string 2
cc_settext
LABEL185:
get_varbit 4396
iconst 0
if_icmpgt LABEL189
jump LABEL211
LABEL189:
iconst 2147483647
get_varbit 4396
div
get_varbit 4398
if_icmplt LABEL195
jump LABEL211
LABEL195:
iload 0
iload 11
cc_find
iconst 1
if_icmpeq LABEL201
jump LABEL206
LABEL201:
sconst "<col=ff0000>"
sconst "Too much money!"
sconst "</col>"
join_string 3
cc_settext
LABEL206:
iload 0
iload 14
iload 13
invoke 780
jump LABEL273
LABEL211:
get_varbit 4396
get_varbit 4398
multiply
istore 15
iload 0
iload 11
cc_find
iconst 1
if_icmpeq LABEL221
jump LABEL234
LABEL221:
iload 15
iconst 1
if_icmpeq LABEL225
jump LABEL228
LABEL225:
sconst "1 coin"
cc_settext
jump LABEL234
LABEL228:
iload 15
sload 0
invoke 46
sconst " coins"
join_string 2
cc_settext
LABEL234:
iload 15
iconst 0
if_icmpgt LABEL238
jump LABEL269
LABEL238:
iload 13
invoke 208
pop_int
iconst 772
iconst -2147483645
sconst "I"
iload 13
if_setonmouserepeat
iconst 97
iconst -2147483645
sconst "I"
iload 13
if_setonmouseleave
iconst 489
iconst -2147483644
iconst 2
sconst "ii"
iload 13
if_setonop
iload 0
iload 14
cc_find
iconst 1
if_icmpeq LABEL263
jump LABEL268
LABEL263:
sconst "<col=ffffff>"
sconst "Confirm"
sconst "</col>"
join_string 3
cc_settext
LABEL268:
jump LABEL273
LABEL269:
iload 0
iload 14
iload 13
invoke 780
LABEL273:
jump LABEL319
LABEL274:
iload 0
iload 7
cc_find
iconst 1
if_icmpeq LABEL280
jump LABEL283
LABEL280:
iconst 6512
iconst 1
cc_setobject_nonum
LABEL283:
iload 0
iload 8
cc_find
iconst 1
if_icmpeq LABEL289
jump LABEL291
LABEL289:
sconst "Choose an item..."
cc_settext
LABEL291:
iload 0
iload 9
cc_find
iconst 1
if_icmpeq LABEL297
jump LABEL299
LABEL297:
sconst ""
cc_settext
LABEL299:
iload 0
iload 10
cc_find
iconst 1
if_icmpeq LABEL305
jump LABEL307
LABEL305:
sconst ""
cc_settext
LABEL307:
iload 0
iload 11
cc_find
iconst 1
if_icmpeq LABEL313
jump LABEL315
LABEL313:
sconst ""
cc_settext
LABEL315:
iload 0
iload 14
iload 13
invoke 780
LABEL319:
sconst "geBuilt" ;
runelite_callback ;
return
@@ -1 +0,0 @@
FC7F8B54745582D6DD530D5458E129B67D6B3CFF61BACD4BBE7BC8C40E26F3C6
@@ -1,228 +0,0 @@
.id 1354
.int_stack_count 3
.string_stack_count 0
.int_var_count 7
.string_var_count 0
iconst 0
istore 3
iconst 0
istore 4
iconst 0
istore 5
invoke 1340
istore 6
LABEL8:
iload 5
iload 6
if_icmplt LABEL12
jump LABEL64
LABEL12:
iload 0
iload 5
cc_find
iconst 1
if_icmpeq LABEL18
jump LABEL59
LABEL18:
iload 5
invoke 1357
istore 3
iload 5
invoke 3236
iconst 1
if_icmpeq LABEL26
jump LABEL29
LABEL26:
iconst 10461087
istore 4
jump LABEL45
LABEL29:
iload 3
iconst 2
if_icmpeq LABEL33
jump LABEL36
LABEL33:
iconst 901389
istore 4
jump LABEL45
LABEL36:
iload 3
iconst 0
if_icmpeq LABEL40
jump LABEL43
LABEL40:
iconst 16776960
istore 4
jump LABEL45
LABEL43:
iconst 16711680
istore 4
LABEL45:
iload 4
cc_setcolour
iconst 85
iconst -2147483645
iconst -2147483643
iconst 16777215
sconst "Iii"
cc_setonmouseover
iconst 85
iconst -2147483645
iconst -2147483643
iload 4
sconst "Iii"
cc_setonmouseleave
LABEL59:
iload 5
iconst 1
add
istore 5
jump LABEL8
LABEL64:
iconst 0
invoke 2245
istore 6
istore 5
LABEL68:
iload 5
iload 6
if_icmplt LABEL72
jump LABEL124
LABEL72:
iload 1
iload 5
cc_find
iconst 1
if_icmpeq LABEL78
jump LABEL119
LABEL78:
iload 5
invoke 1358
istore 3
iload 5
invoke 3237
iconst 1
if_icmpeq LABEL86
jump LABEL89
LABEL86:
iconst 10461087
istore 4
jump LABEL105
LABEL89:
iload 3
iconst 2
if_icmpeq LABEL93
jump LABEL96
LABEL93:
iconst 901389
istore 4
jump LABEL105
LABEL96:
iload 3
iconst 0
if_icmpeq LABEL100
jump LABEL103
LABEL100:
iconst 16776960
istore 4
jump LABEL105
LABEL103:
iconst 16711680
istore 4
LABEL105:
iload 4
cc_setcolour
iconst 85
iconst -2147483645
iconst -2147483643
iconst 16777215
sconst "Iii"
cc_setonmouseover
iconst 85
iconst -2147483645
iconst -2147483643
iload 4
sconst "Iii"
cc_setonmouseleave
LABEL119:
iload 5
iconst 1
add
istore 5
jump LABEL68
LABEL124:
iconst 0
invoke 2265
istore 6
istore 5
LABEL128:
iload 5
iload 6
if_icmplt LABEL132
jump LABEL184
LABEL132:
iload 2
iload 5
cc_find
iconst 1
if_icmpeq LABEL138
jump LABEL179
LABEL138:
iload 5
invoke 1359
istore 3
iload 5
invoke 3238
iconst 1
if_icmpeq LABEL146
jump LABEL149
LABEL146:
iconst 10461087
istore 4
jump LABEL165
LABEL149:
iload 3
iconst 2
if_icmpeq LABEL153
jump LABEL156
LABEL153:
iconst 901389
istore 4
jump LABEL165
LABEL156:
iload 3
iconst 0
if_icmpeq LABEL160
jump LABEL163
LABEL160:
iconst 16776960
istore 4
jump LABEL165
LABEL163:
iconst 16711680
istore 4
LABEL165:
iload 4
cc_setcolour
iconst 85
iconst -2147483645
iconst -2147483643
iconst 16777215
sconst "Iii"
cc_setonmouseover
iconst 85
iconst -2147483645
iconst -2147483643
iload 4
sconst "Iii"
cc_setonmouseleave
LABEL179:
iload 5
iconst 1
add
istore 5
jump LABEL128
LABEL184:
sconst "questProgressUpdated"
runelite_callback
return
@@ -27,11 +27,14 @@ package net.runelite.client.config;
import com.google.inject.Guice; import com.google.inject.Guice;
import com.google.inject.testing.fieldbinder.Bind; import com.google.inject.testing.fieldbinder.Bind;
import com.google.inject.testing.fieldbinder.BoundFieldModule; import com.google.inject.testing.fieldbinder.BoundFieldModule;
import java.io.File;
import java.time.Instant; import java.time.Instant;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.client.RuneLite;
import net.runelite.client.account.AccountSession; import net.runelite.client.account.AccountSession;
import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.EventBus;
import org.junit.Assert; import org.junit.Assert;
@@ -64,6 +67,10 @@ public class ConfigManagerTest
@Bind @Bind
private OpenOSRSConfig openOSRSConfig; private OpenOSRSConfig openOSRSConfig;
@Bind
@Named("config")
private File config = RuneLite.DEFAULT_CONFIG_FILE;
@Inject @Inject
ConfigManager manager; ConfigManager manager;
@@ -87,7 +87,7 @@ public class PluginManagerTest
public void before() throws IOException public void before() throws IOException
{ {
Injector injector = Guice.createInjector(Modules Injector injector = Guice.createInjector(Modules
.override(new RuneLiteModule(() -> null, true)) .override(new RuneLiteModule(() -> null, RuneLite.DEFAULT_CONFIG_FILE))
.with(BoundFieldModule.of(this))); .with(BoundFieldModule.of(this)));
RuneLite.setInjector(injector); RuneLite.setInjector(injector);
@@ -116,7 +116,7 @@ public class PluginManagerTest
@Test @Test
public void testLoadPlugins() throws Exception public void testLoadPlugins() throws Exception
{ {
PluginManager pluginManager = new PluginManager(false, null, null, null, null); PluginManager pluginManager = new PluginManager(null, null, null, null);
pluginManager.setOutdated(true); pluginManager.setOutdated(true);
pluginManager.loadCorePlugins(); pluginManager.loadCorePlugins();
Collection<Plugin> plugins = pluginManager.getPlugins(); Collection<Plugin> plugins = pluginManager.getPlugins();
@@ -127,14 +127,13 @@ public class PluginManagerTest
.count(); .count();
assertEquals(expected, plugins.size()); assertEquals(expected, plugins.size());
pluginManager = new PluginManager(false, null, null, null, null); pluginManager = new PluginManager(null, null, null, null);
pluginManager.loadCorePlugins(); pluginManager.loadCorePlugins();
plugins = pluginManager.getPlugins(); plugins = pluginManager.getPlugins();
expected = pluginClasses.stream() expected = pluginClasses.stream()
.map(cl -> (PluginDescriptor) cl.getAnnotation(PluginDescriptor.class)) .map(cl -> (PluginDescriptor) cl.getAnnotation(PluginDescriptor.class))
.filter(Objects::nonNull) .filter(Objects::nonNull)
.filter(pd -> !pd.developerPlugin())
.count(); .count();
assertEquals(expected, plugins.size()); assertEquals(expected, plugins.size());
} }
@@ -144,9 +143,9 @@ public class PluginManagerTest
{ {
List<Module> modules = new ArrayList<>(); List<Module> modules = new ArrayList<>();
modules.add(new GraphvizModule()); modules.add(new GraphvizModule());
modules.add(new RuneLiteModule(() -> null, true)); modules.add(new RuneLiteModule(() -> null, RuneLite.DEFAULT_CONFIG_FILE));
PluginManager pluginManager = new PluginManager(true, null, null, null, null); PluginManager pluginManager = new PluginManager(null, null, null, null);
pluginManager.loadCorePlugins(); pluginManager.loadCorePlugins();
modules.addAll(pluginManager.getPlugins()); modules.addAll(pluginManager.getPlugins());
@@ -198,7 +197,7 @@ public class PluginManagerTest
public void testEventbusAnnotations() throws PluginInstantiationException public void testEventbusAnnotations() throws PluginInstantiationException
{ {
EventBus eventbus = new EventBus(); EventBus eventbus = new EventBus();
PluginManager pluginManager = new PluginManager(true, eventbus, null, null, null) PluginManager pluginManager = new PluginManager(eventbus, null, null, null)
{ {
@Override @Override
public boolean isPluginEnabled(Plugin plugin) public boolean isPluginEnabled(Plugin plugin)
@@ -46,7 +46,10 @@ import static net.runelite.api.SkullIcon.SKULL;
import static net.runelite.api.SkullIcon.SKULL_FIGHT_PIT; import static net.runelite.api.SkullIcon.SKULL_FIGHT_PIT;
import net.runelite.api.coords.LocalPoint; import net.runelite.api.coords.LocalPoint;
import net.runelite.api.events.PlayerAppearanceChanged; import net.runelite.api.events.PlayerAppearanceChanged;
import net.runelite.api.events.player.headicon.OverheadPrayerChanged;
import net.runelite.api.events.player.headicon.PlayerSkullChanged;
import net.runelite.api.mixins.Copy; import net.runelite.api.mixins.Copy;
import net.runelite.api.mixins.FieldHook;
import net.runelite.api.mixins.Inject; import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.MethodHook; import net.runelite.api.mixins.MethodHook;
import net.runelite.api.mixins.Mixin; import net.runelite.api.mixins.Mixin;
@@ -67,6 +70,12 @@ public abstract class RSPlayerMixin implements RSPlayer
@Inject @Inject
private boolean friended; private boolean friended;
@Inject
private int oldHeadIcon = -1;
@Inject
private int oldSkullIcon = -1;
@Inject @Inject
@Override @Override
public String getName() public String getName()
@@ -88,11 +97,53 @@ public abstract class RSPlayerMixin implements RSPlayer
return name.replace('\u00A0', ' '); return name.replace('\u00A0', ' ');
} }
@Inject
@FieldHook("headIconPrayer")
public void prayerChanged(int idx)
{
if (!(getRsOverheadIcon() == -1 && oldHeadIcon == -1))
{
final HeadIcon headIcon = getHeadIcon(getRsOverheadIcon());
if (getRsOverheadIcon() != oldHeadIcon)
{
client.getCallbacks().post(OverheadPrayerChanged.class,
new OverheadPrayerChanged(this, getHeadIcon(oldHeadIcon), headIcon));
}
}
oldHeadIcon = getRsOverheadIcon();
}
@Inject @Inject
@Override @Override
public HeadIcon getOverheadIcon() public HeadIcon getOverheadIcon()
{ {
switch (getRsOverheadIcon()) return getHeadIcon(getRsOverheadIcon());
}
@Inject
@FieldHook("headIconPk")
public void skullChanged(int idx)
{
final SkullIcon skullIcon = skullFromInt(getRsSkullIcon());
if (getRsSkullIcon() != oldSkullIcon)
{
client.getCallbacks().post(PlayerSkullChanged.class,
new PlayerSkullChanged(this, skullFromInt(getRsSkullIcon()), skullIcon));
}
oldSkullIcon = getRsSkullIcon();
}
@Inject
@Override
public SkullIcon getSkullIcon()
{
return skullFromInt(getRsSkullIcon());
}
@Inject
private HeadIcon getHeadIcon(int overheadIcon)
{
switch (overheadIcon)
{ {
case 0: case 0:
return MELEE; return MELEE;
@@ -112,10 +163,9 @@ public abstract class RSPlayerMixin implements RSPlayer
} }
@Inject @Inject
@Override private SkullIcon skullFromInt(int skull)
public SkullIcon getSkullIcon()
{ {
switch (getRsSkullIcon()) switch (skull)
{ {
case 0: case 0:
return SKULL; return SKULL;
@@ -71,4 +71,13 @@ public interface RSItemDefinition extends ItemDefinition
@Import("getModel") @Import("getModel")
RSModel getModel(int quantity); RSModel getModel(int quantity);
@Import("unnotedId")
int getInventoryModel();
@Import("recolorTo")
short[] getColorToReplaceWith();
@Import("retextureTo")
short[] getTextureToReplaceWith();
} }