diff --git a/README.md b/README.md index 8429270de4..76ef9804ad 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Contributions are welcome, but there should be no changes made to runelite-clien - [cache](cache/src/main/java/net/runelite/cache) - Libraries used for reading/writing cache files, as well as the data in it - [deobfuscator](deobfuscator/src/main/java/net/runelite/deob) - Can decompile and cleanup gamepacks as well as map updates to newer revs - [http-api](http-api/src/main/java/net/runelite/http/api) - API for runelite and OpenOSRS -- [injector-plugin](injector-plugin/src/main/java/net/runelite/injector) - Tool for implementing our modifications to the gamepack +- [injector](injector/src/main/java/com/openosrs/injector) - Bytecode weaver that allows us to add code to the obfuscated gamepack - [runelite-api](runelite-api/src/main/java/net/runelite/api) - RuneLite API, interfaces for accessing the client - [runelite-mixins](runelite-mixins/src/main/java/net/runelite) - Classes containing the Objects to be injected using the injector-plugin - [runescape-api](runescape-api/src/main/java/net/runelite) - Mappings correspond to these interfaces, runelite-api is a subset of this diff --git a/buildSrc/src/main/kotlin/BootstrapTask.kt b/buildSrc/src/main/kotlin/BootstrapTask.kt index 3eaf7dcebb..0e141ee23d 100644 --- a/buildSrc/src/main/kotlin/BootstrapTask.kt +++ b/buildSrc/src/main/kotlin/BootstrapTask.kt @@ -1,3 +1,4 @@ +import groovy.json.JsonOutput import org.gradle.api.DefaultTask import org.gradle.api.file.RegularFileProperty import org.gradle.api.tasks.* @@ -117,11 +118,13 @@ open class BootstrapTask @Inject constructor(@Input val type: String) : DefaultT "artifacts" to getArtifacts() ).toString() + val prettyJson = JsonOutput.prettyPrint(json) + val bootstrapDir = File("${project.buildDir}/bootstrap") bootstrapDir.mkdirs() File(bootstrapDir, "bootstrap-${type}.json").printWriter().use { out -> - out.println(json) + out.println(prettyJson) } } } diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 7f661d29d5..a230b4272c 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -25,9 +25,9 @@ object ProjectVersions { const val launcherVersion = "2.2.0" - const val rlVersion = "1.6.36" + const val rlVersion = "1.6.38" - const val openosrsVersion = "3.5.4" + const val openosrsVersion = "4.0.0" const val rsversion = 193 const val cacheversion = 165 diff --git a/cache/src/main/java/net/runelite/cache/fs/flat/FlatStorage.java b/cache/src/main/java/net/runelite/cache/fs/flat/FlatStorage.java index 92a82e26b7..c8d651bcf6 100644 --- a/cache/src/main/java/net/runelite/cache/fs/flat/FlatStorage.java +++ b/cache/src/main/java/net/runelite/cache/fs/flat/FlatStorage.java @@ -220,7 +220,7 @@ public class FlatStorage implements Storage br.printf("revision=%d\n", idx.getRevision()); br.printf("compression=%d\n", idx.getCompression()); br.printf("crc=%d\n", idx.getCrc()); - br.printf("named=%b\n", idx.getCompression()); + br.printf("named=%b\n", idx.isNamed()); idx.getArchives().sort(Comparator.comparing(Archive::getArchiveId)); for (Archive archive : idx.getArchives()) diff --git a/cache/src/main/java/net/runelite/cache/fs/jagex/DataFile.java b/cache/src/main/java/net/runelite/cache/fs/jagex/DataFile.java index 89eb607eee..7b79f8b4f7 100644 --- a/cache/src/main/java/net/runelite/cache/fs/jagex/DataFile.java +++ b/cache/src/main/java/net/runelite/cache/fs/jagex/DataFile.java @@ -66,7 +66,7 @@ public class DataFile implements Closeable * @return * @throws IOException */ - public byte[] read(int indexId, int archiveId, int sector, int size) throws IOException + public synchronized byte[] read(int indexId, int archiveId, int sector, int size) throws IOException { if (sector <= 0L || dat.length() / SECTOR_SIZE < (long) sector) { @@ -169,7 +169,7 @@ public class DataFile implements Closeable return buffer.array(); } - public DataFileWriteResult write(int indexId, int archiveId, byte[] compressedData) throws IOException + public synchronized DataFileWriteResult write(int indexId, int archiveId, byte[] compressedData) throws IOException { int sector; int startSector; diff --git a/cache/src/main/java/net/runelite/cache/fs/jagex/DiskStorage.java b/cache/src/main/java/net/runelite/cache/fs/jagex/DiskStorage.java index 42fd8d9b0c..0e13537061 100644 --- a/cache/src/main/java/net/runelite/cache/fs/jagex/DiskStorage.java +++ b/cache/src/main/java/net/runelite/cache/fs/jagex/DiskStorage.java @@ -112,13 +112,13 @@ public class DiskStorage implements Storage public byte[] readIndex(int indexId) throws IOException { IndexEntry entry = index255.read(indexId); - if (entry != null) + if (entry == null) { - byte[] indexData = data.read(index255.getIndexFileId(), entry.getId(), entry.getSector(), entry.getLength()); - return indexData; + return null; } - return null; + byte[] indexData = data.read(index255.getIndexFileId(), entry.getId(), entry.getSector(), entry.getLength()); + return indexData; } private void loadIndex(Index index) throws IOException @@ -126,7 +126,6 @@ public class DiskStorage implements Storage logger.trace("Loading index {}", index.getId()); byte[] indexData = readIndex(index.getId()); - if (indexData == null) { return; diff --git a/cache/src/main/java/net/runelite/cache/models/JagexColor.java b/cache/src/main/java/net/runelite/cache/models/JagexColor.java new file mode 100644 index 0000000000..993073bf90 --- /dev/null +++ b/cache/src/main/java/net/runelite/cache/models/JagexColor.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2020 Abex + * 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.cache.models; + +public final class JagexColor +{ + public static final double BRIGHTNESS_MAX = .6; + public static final double BRIGHTNESS_HIGH = .7; + public static final double BRIGHTNESS_LOW = .8; + public static final double BRIGTHNESS_MIN = .9; + + private static final double HUE_OFFSET = (.5 / 64.D); + private static final double SATURATION_OFFSET = (.5 / 8.D); + + private JagexColor() + { + } + + public static short packHSL(int hue, int saturation, int luminance) + { + return (short) ((short) (hue & 63) << 10 + | (short) (saturation & 7) << 7 + | (short) (luminance & 127)); + } + + public static int unpackHue(short hsl) + { + return hsl >> 10 & 63; + } + + public static int unpackSaturation(short hsl) + { + return hsl >> 7 & 7; + } + + public static int unpackLuminance(short hsl) + { + return hsl & 127; + } + + public static String formatHSL(short hsl) + { + return String.format("%02Xh%Xs%02Xl", unpackHue(hsl), unpackSaturation(hsl), unpackLuminance(hsl)); + } + + public static int HSLtoRGB(short hsl, double brightness) + { + double hue = (double) unpackHue(hsl) / 64.D + HUE_OFFSET; + double saturation = (double) unpackSaturation(hsl) / 8.D + SATURATION_OFFSET; + double luminance = (double) unpackLuminance(hsl) / 128.D; + + // This is just a standard hsl to rgb transform + // the only difference is the offsets above and the brightness transform below + double chroma = (1.D - Math.abs((2.D * luminance) - 1.D)) * saturation; + double x = chroma * (1 - Math.abs(((hue * 6.D) % 2.D) - 1.D)); + double lightness = luminance - (chroma / 2); + + double r = lightness, g = lightness, b = lightness; + switch ((int) (hue * 6.D)) + { + case 0: + r += chroma; + g += x; + break; + case 1: + g += chroma; + r += x; + break; + case 2: + g += chroma; + b += x; + break; + case 3: + b += chroma; + g += x; + break; + case 4: + b += chroma; + r += x; + break; + default: + r += chroma; + b += x; + break; + } + + int rgb = ((int) (r * 256.0D) << 16) + | ((int) (g * 256.0D) << 8) + | (int) (b * 256.0D); + + rgb = adjustForBrightness(rgb, brightness); + + if (rgb == 0) + { + rgb = 1; + } + return rgb; + } + + public static int adjustForBrightness(int rgb, double brightness) + { + double r = (double) (rgb >> 16) / 256.0D; + double g = (double) (rgb >> 8 & 255) / 256.0D; + double b = (double) (rgb & 255) / 256.0D; + + r = Math.pow(r, brightness); + g = Math.pow(g, brightness); + b = Math.pow(b, brightness); + + return ((int) (r * 256.0D) << 16) + | ((int) (g * 256.0D) << 8) + | (int) (b * 256.0D); + } +} \ No newline at end of file diff --git a/cache/src/main/java/net/runelite/cache/models/ObjExporter.java b/cache/src/main/java/net/runelite/cache/models/ObjExporter.java index 8913610177..fb65f99972 100644 --- a/cache/src/main/java/net/runelite/cache/models/ObjExporter.java +++ b/cache/src/main/java/net/runelite/cache/models/ObjExporter.java @@ -24,7 +24,6 @@ */ package net.runelite.cache.models; -import java.awt.Color; import java.io.PrintWriter; import net.runelite.cache.TextureManager; import net.runelite.cache.definitions.ModelDefinition; @@ -32,6 +31,8 @@ import net.runelite.cache.definitions.TextureDefinition; public class ObjExporter { + private static final double BRIGHTNESS = JagexColor.BRIGTHNESS_MIN; + private final TextureManager textureManager; private final ModelDefinition model; @@ -111,11 +112,10 @@ public class ObjExporter if (textureId == -1) { - Color color = rs2hsbToColor(model.faceColors[i]); - - double r = color.getRed() / 255.0; - double g = color.getGreen() / 255.0; - double b = color.getBlue() / 255.0; + int rgb = JagexColor.HSLtoRGB( model.faceColors[i], BRIGHTNESS); + double r = ((rgb >> 16) & 0xff) / 255.0; + double g = ((rgb >> 8) & 0xff) / 255.0; + double b = (rgb & 0xff) / 255.0; mtlWriter.println("Kd " + r + " " + g + " " + b); } @@ -140,12 +140,4 @@ public class ObjExporter } } } - - private static Color rs2hsbToColor(int hsb) - { - int decode_hue = (hsb >> 10) & 0x3f; - int decode_saturation = (hsb >> 7) & 0x07; - int decode_brightness = (hsb & 0x7f); - return Color.getHSBColor((float) decode_hue / 63, (float) decode_saturation / 7, (float) decode_brightness / 127); - } } diff --git a/cache/src/test/java/net/runelite/cache/models/JagexColorTest.java b/cache/src/test/java/net/runelite/cache/models/JagexColorTest.java new file mode 100644 index 0000000000..25291d4528 --- /dev/null +++ b/cache/src/test/java/net/runelite/cache/models/JagexColorTest.java @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2020 Abex + * 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.cache.models; + +import static org.junit.Assert.assertEquals; +import org.junit.Test; + +public class JagexColorTest +{ + private static final double[] BRIGHTNESS_LEVELS = { + JagexColor.BRIGTHNESS_MIN, + JagexColor.BRIGHTNESS_LOW, + JagexColor.BRIGHTNESS_HIGH, + JagexColor.BRIGHTNESS_MAX, + }; + + // copy/pasted from the client, the reference colors + private static int[] computeColorTable(double brightness, int min, int max) + { + int[] colorPalette = new int[65536]; + int var4 = min * 128; + + for (int var5 = min; var5 < max; ++var5) + { + double var6 = (double) (var5 >> 3) / 64.0D + 0.0078125D; + double var8 = (double) (var5 & 7) / 8.0D + 0.0625D; + + for (int var10 = 0; var10 < 128; ++var10) + { + double var11 = (double) var10 / 128.0D; + double var13 = var11; + double var15 = var11; + double var17 = var11; + if (var8 != 0.0D) + { + double var19; + if (var11 < 0.5D) + { + var19 = var11 * (1.0D + var8); + } + else + { + var19 = var11 + var8 - var11 * var8; + } + + double var21 = 2.0D * var11 - var19; + double var23 = var6 + 0.3333333333333333D; + if (var23 > 1.0D) + { + --var23; + } + + double var27 = var6 - 0.3333333333333333D; + if (var27 < 0.0D) + { + ++var27; + } + + if (6.0D * var23 < 1.0D) + { + var13 = var21 + (var19 - var21) * 6.0D * var23; + } + else if (2.0D * var23 < 1.0D) + { + var13 = var19; + } + else if (3.0D * var23 < 2.0D) + { + var13 = var21 + (var19 - var21) * (0.6666666666666666D - var23) * 6.0D; + } + else + { + var13 = var21; + } + + if (6.0D * var6 < 1.0D) + { + var15 = var21 + (var19 - var21) * 6.0D * var6; + } + else if (2.0D * var6 < 1.0D) + { + var15 = var19; + } + else if (3.0D * var6 < 2.0D) + { + var15 = var21 + (var19 - var21) * (0.6666666666666666D - var6) * 6.0D; + } + else + { + var15 = var21; + } + + if (6.0D * var27 < 1.0D) + { + var17 = var21 + (var19 - var21) * 6.0D * var27; + } + else if (2.0D * var27 < 1.0D) + { + var17 = var19; + } + else if (3.0D * var27 < 2.0D) + { + var17 = var21 + (var19 - var21) * (0.6666666666666666D - var27) * 6.0D; + } + else + { + var17 = var21; + } + } + + int var29 = (int) (var13 * 256.0D); + int var20 = (int) (var15 * 256.0D); + int var30 = (int) (var17 * 256.0D); + int var22 = var30 + (var20 << 8) + (var29 << 16); + var22 = adjustForBrightness(var22, brightness); + if (var22 == 0) + { + var22 = 1; + } + + colorPalette[var4++] = var22; + } + } + + return colorPalette; + } + + private static int adjustForBrightness(int rgb, double brightness) + { + double var3 = (double) (rgb >> 16) / 256.0D; + double var5 = (double) (rgb >> 8 & 255) / 256.0D; + double var7 = (double) (rgb & 255) / 256.0D; + var3 = Math.pow(var3, brightness); + var5 = Math.pow(var5, brightness); + var7 = Math.pow(var7, brightness); + int var9 = (int) (var3 * 256.0D); + int var10 = (int) (var5 * 256.0D); + int var11 = (int) (var7 * 256.0D); + return var11 + (var10 << 8) + (var9 << 16); + } + + @Test + public void testHslToRgb() + { + for (double brightness : BRIGHTNESS_LEVELS) + { + int[] colorPalette = computeColorTable(brightness, 0, 512); + for (int i = 0; i < 0xFFFF; i++) + { + int rgb = JagexColor.HSLtoRGB((short) i, brightness); + int crgb = colorPalette[i]; + assertEquals("idx " + i + " brightness " + brightness, crgb, rgb); + } + } + } +} \ No newline at end of file diff --git a/http-api/src/main/java/net/runelite/http/api/RuneLiteAPI.java b/http-api/src/main/java/net/runelite/http/api/RuneLiteAPI.java index 0b017518c8..dc483f35db 100644 --- a/http-api/src/main/java/net/runelite/http/api/RuneLiteAPI.java +++ b/http-api/src/main/java/net/runelite/http/api/RuneLiteAPI.java @@ -25,10 +25,16 @@ package net.runelite.http.api; import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import java.awt.Color; import java.io.IOException; import java.io.InputStream; +import java.time.Instant; import java.util.Properties; import java.util.concurrent.TimeUnit; +import net.runelite.http.api.gson.ColorTypeAdapter; +import net.runelite.http.api.gson.InstantTypeAdapter; +import net.runelite.http.api.gson.IllegalReflectionExclusion; import okhttp3.HttpUrl; import okhttp3.Interceptor; import okhttp3.MediaType; @@ -46,7 +52,7 @@ public class RuneLiteAPI public static final String RUNELITE_MACHINEID = "RUNELITE-MACHINEID"; public static final OkHttpClient CLIENT; - public static final Gson GSON = new Gson(); + public static final Gson GSON; public static final MediaType JSON = MediaType.parse("application/json"); public static String userAgent; @@ -96,6 +102,23 @@ public class RuneLiteAPI } }) .build(); + + GsonBuilder gsonBuilder = new GsonBuilder(); + + gsonBuilder + .registerTypeAdapter(Instant.class, new InstantTypeAdapter()) + .registerTypeAdapter(Color.class, new ColorTypeAdapter()); + + boolean assertionsEnabled = false; + assert assertionsEnabled = true; + if (assertionsEnabled) + { + IllegalReflectionExclusion jbe = new IllegalReflectionExclusion(); + gsonBuilder.addSerializationExclusionStrategy(jbe); + gsonBuilder.addDeserializationExclusionStrategy(jbe); + } + + GSON = gsonBuilder.create(); } public static HttpUrl getSessionBase() diff --git a/http-api/src/main/java/net/runelite/http/api/gson/ColorTypeAdapter.java b/http-api/src/main/java/net/runelite/http/api/gson/ColorTypeAdapter.java new file mode 100644 index 0000000000..6f4b003df0 --- /dev/null +++ b/http-api/src/main/java/net/runelite/http/api/gson/ColorTypeAdapter.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2020 Abex + * 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.http.api.gson; + +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import java.awt.Color; +import java.io.IOException; + +public class ColorTypeAdapter extends TypeAdapter +{ + @Override + public void write(JsonWriter out, Color value) throws IOException + { + if (value == null) + { + out.nullValue(); + return; + } + + int rgba = value.getRGB(); + out.beginObject() + .name("value") + .value(rgba) + .endObject(); + } + + @Override + public Color read(JsonReader in) throws IOException + { + switch (in.peek()) + { + case NULL: + in.nextNull(); + return null; + case BEGIN_OBJECT: + in.beginObject(); + double value = 0; + while (in.peek() != JsonToken.END_OBJECT) + { + switch (in.nextName()) + { + case "value": + value = in.nextDouble(); + break; + default: + in.skipValue(); + break; + } + } + in.endObject(); + return new Color((int) value, true); + } + return null; // throws + } +} diff --git a/http-api/src/main/java/net/runelite/http/api/gson/IllegalReflectionExclusion.java b/http-api/src/main/java/net/runelite/http/api/gson/IllegalReflectionExclusion.java new file mode 100644 index 0000000000..a25ffb79f7 --- /dev/null +++ b/http-api/src/main/java/net/runelite/http/api/gson/IllegalReflectionExclusion.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2020 Abex + * 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.http.api.gson; + +import com.google.gson.ExclusionStrategy; +import com.google.gson.FieldAttributes; +import java.lang.reflect.Modifier; +import java.util.HashSet; +import java.util.Set; + +public class IllegalReflectionExclusion implements ExclusionStrategy +{ + private static final Set PRIVATE_CLASSLOADERS = new HashSet<>(); + + static + { + for (ClassLoader cl = ClassLoader.getSystemClassLoader(); cl != null; ) + { + cl = cl.getParent(); + PRIVATE_CLASSLOADERS.add(cl); + } + } + + @Override + public boolean shouldSkipField(FieldAttributes f) + { + if (!PRIVATE_CLASSLOADERS.contains(f.getDeclaringClass().getClassLoader())) + { + return false; + } + + assert !Modifier.isPrivate(f.getDeclaringClass().getModifiers()) : "gsoning private class " + f.getDeclaringClass().getName(); + try + { + f.getDeclaringClass().getField(f.getName()); + } + catch (NoSuchFieldException e) + { + throw new AssertionError("gsoning private field " + f.getDeclaringClass() + "." + f.getName()); + } + return false; + } + + @Override + public boolean shouldSkipClass(Class clazz) + { + return false; + } +} diff --git a/http-api/src/main/java/net/runelite/http/api/gson/InstantTypeAdapter.java b/http-api/src/main/java/net/runelite/http/api/gson/InstantTypeAdapter.java new file mode 100644 index 0000000000..bf92af94b8 --- /dev/null +++ b/http-api/src/main/java/net/runelite/http/api/gson/InstantTypeAdapter.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2020 Abex + * 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.http.api.gson; + +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.time.Instant; + +// Just add water! +public class InstantTypeAdapter extends TypeAdapter +{ + @Override + public void write(JsonWriter out, Instant value) throws IOException + { + if (value == null) + { + out.nullValue(); + return; + } + + out.beginObject() + .name("seconds") + .value(value.getEpochSecond()) + .name("nanos") + .value(value.getNano()) + .endObject(); + } + + @Override + public Instant read(JsonReader in) throws IOException + { + if (in.peek() == JsonToken.NULL) + { + in.nextNull(); + return null; + } + + long seconds = 0; + int nanos = 0; + in.beginObject(); + while (in.peek() != JsonToken.END_OBJECT) + { + switch (in.nextName()) + { + case "nanos": + nanos = in.nextInt(); + break; + case "seconds": + seconds = in.nextLong(); + break; + } + } + in.endObject(); + + return Instant.ofEpochSecond(seconds, nanos); + } +} diff --git a/http-api/src/main/java/net/runelite/http/api/ws/WebsocketGsonFactory.java b/http-api/src/main/java/net/runelite/http/api/ws/WebsocketGsonFactory.java index 9d4e46e6ea..328d0aa1a7 100644 --- a/http-api/src/main/java/net/runelite/http/api/ws/WebsocketGsonFactory.java +++ b/http-api/src/main/java/net/runelite/http/api/ws/WebsocketGsonFactory.java @@ -25,11 +25,11 @@ package net.runelite.http.api.ws; import com.google.gson.Gson; -import com.google.gson.GsonBuilder; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; +import net.runelite.http.api.RuneLiteAPI; import net.runelite.http.api.ws.messages.Handshake; import net.runelite.http.api.ws.messages.LoginResponse; import net.runelite.http.api.ws.messages.party.Join; @@ -76,7 +76,7 @@ public class WebsocketGsonFactory public static Gson build(final RuntimeTypeAdapterFactory factory) { - return new GsonBuilder() + return RuneLiteAPI.GSON.newBuilder() .registerTypeAdapterFactory(factory) .create(); } diff --git a/http-service/src/main/java/net/runelite/http/service/chat/ChatController.java b/http-service/src/main/java/net/runelite/http/service/chat/ChatController.java new file mode 100644 index 0000000000..8632a8b2f0 --- /dev/null +++ b/http-service/src/main/java/net/runelite/http/service/chat/ChatController.java @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2018, Adam + * 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.http.service.chat; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import net.runelite.http.api.chat.Duels; +import net.runelite.http.api.chat.LayoutRoom; +import net.runelite.http.api.chat.Task; +import net.runelite.http.service.util.exception.NotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.CacheControl; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/chat") +public class ChatController +{ + private static final Pattern STRING_VALIDATION = Pattern.compile("[^a-zA-Z0-9' -]"); + private static final int STRING_MAX_LENGTH = 50; + private static final int MAX_LAYOUT_ROOMS = 16; + + private final Cache killCountCache = CacheBuilder.newBuilder() + .expireAfterWrite(2, TimeUnit.MINUTES) + .maximumSize(128L) + .build(); + + @Autowired + private ChatService chatService; + + @PostMapping("/kc") + public void submitKc(@RequestParam String name, @RequestParam String boss, @RequestParam int kc) + { + if (kc <= 0) + { + return; + } + + chatService.setKc(name, boss, kc); + killCountCache.put(new KillCountKey(name, boss), kc); + } + + @GetMapping("/kc") + public int getKc(@RequestParam String name, @RequestParam String boss) + { + Integer kc = killCountCache.getIfPresent(new KillCountKey(name, boss)); + if (kc == null) + { + kc = chatService.getKc(name, boss); + if (kc != null) + { + killCountCache.put(new KillCountKey(name, boss), kc); + } + } + + if (kc == null) + { + throw new NotFoundException(); + } + return kc; + } + + @PostMapping("/qp") + public void submitQp(@RequestParam String name, @RequestParam int qp) + { + if (qp < 0) + { + return; + } + + chatService.setQp(name, qp); + } + + @GetMapping("/qp") + public int getQp(@RequestParam String name) + { + Integer kc = chatService.getQp(name); + if (kc == null) + { + throw new NotFoundException(); + } + return kc; + } + + @PostMapping("/gc") + public void submitGc(@RequestParam String name, @RequestParam int gc) + { + if (gc < 0) + { + return; + } + + chatService.setGc(name, gc); + } + + @GetMapping("/gc") + public int getKc(@RequestParam String name) + { + Integer gc = chatService.getGc(name); + if (gc == null) + { + throw new NotFoundException(); + } + return gc; + } + + @PostMapping("/task") + public void submitTask(@RequestParam String name, @RequestParam("task") String taskName, @RequestParam int amount, + @RequestParam int initialAmount, @RequestParam String location) + { + Matcher mTask = STRING_VALIDATION.matcher(taskName); + Matcher mLocation = STRING_VALIDATION.matcher(location); + if (mTask.find() || taskName.length() > STRING_MAX_LENGTH || + mLocation.find() || location.length() > STRING_MAX_LENGTH) + { + return; + } + + Task task = new Task(); + task.setTask(taskName); + task.setAmount(amount); + task.setInitialAmount(initialAmount); + task.setLocation(location); + + chatService.setTask(name, task); + } + + @GetMapping("/task") + public ResponseEntity getTask(@RequestParam String name) + { + Task task = chatService.getTask(name); + if (task == null) + { + return ResponseEntity.status(HttpStatus.NOT_FOUND) + .build(); + } + + return ResponseEntity.ok() + .cacheControl(CacheControl.maxAge(2, TimeUnit.MINUTES).cachePublic()) + .body(task); + } + + @PostMapping("/pb") + public void submitPb(@RequestParam String name, @RequestParam String boss, @RequestParam int pb) + { + if (pb < 0) + { + return; + } + + chatService.setPb(name, boss, pb); + } + + @GetMapping("/pb") + public int getPb(@RequestParam String name, @RequestParam String boss) + { + Integer pb = chatService.getPb(name, boss); + if (pb == null) + { + throw new NotFoundException(); + } + return pb; + } + + @PostMapping("/duels") + public void submitDuels(@RequestParam String name, @RequestParam int wins, + @RequestParam int losses, + @RequestParam int winningStreak, @RequestParam int losingStreak) + { + if (wins < 0 || losses < 0 || winningStreak < 0 || losingStreak < 0) + { + return; + } + + Duels duels = new Duels(); + duels.setWins(wins); + duels.setLosses(losses); + duels.setWinningStreak(winningStreak); + duels.setLosingStreak(losingStreak); + + chatService.setDuels(name, duels); + } + + @GetMapping("/duels") + public Duels getDuels(@RequestParam String name) + { + Duels duels = chatService.getDuels(name); + if (duels == null) + { + throw new NotFoundException(); + } + return duels; + } + + @PostMapping("/layout") + public void submitLayout(@RequestParam String name, @RequestBody LayoutRoom[] rooms) + { + if (rooms.length > MAX_LAYOUT_ROOMS) + { + return; + } + + chatService.setLayout(name, rooms); + } + + @GetMapping("/layout") + public LayoutRoom[] getLayout(@RequestParam String name) + { + LayoutRoom[] layout = chatService.getLayout(name); + + if (layout == null) + { + throw new NotFoundException(); + } + + return layout; + } +} diff --git a/http-service/src/main/java/net/runelite/http/service/config/ConfigController.java b/http-service/src/main/java/net/runelite/http/service/config/ConfigController.java new file mode 100644 index 0000000000..cebeb926ae --- /dev/null +++ b/http-service/src/main/java/net/runelite/http/service/config/ConfigController.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2019, Adam + * 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.http.service.config; + +import java.io.IOException; +import java.util.List; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import net.runelite.http.api.config.Configuration; +import net.runelite.http.service.account.AuthFilter; +import net.runelite.http.service.account.beans.SessionEntry; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import static org.springframework.web.bind.annotation.RequestMethod.DELETE; +import static org.springframework.web.bind.annotation.RequestMethod.PUT; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/config") +public class ConfigController +{ + private final ConfigService configService; + private final AuthFilter authFilter; + + @Autowired + public ConfigController(ConfigService configService, AuthFilter authFilter) + { + this.configService = configService; + this.authFilter = authFilter; + } + + @GetMapping + public Configuration get(HttpServletRequest request, HttpServletResponse response) throws IOException + { + SessionEntry session = authFilter.handle(request, response); + + if (session == null) + { + return null; + } + + return configService.get(session.getUser()); + } + + @PatchMapping + public List patch( + HttpServletRequest request, + HttpServletResponse response, + @RequestBody Configuration changes + ) throws IOException + { + SessionEntry session = authFilter.handle(request, response); + if (session == null) + { + return null; + } + + List failures = configService.patch(session.getUser(), changes); + if (failures.size() != 0) + { + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + return failures; + } + + return null; + } + + @RequestMapping(path = "/{key:.+}", method = PUT) + public void setKey( + HttpServletRequest request, + HttpServletResponse response, + @PathVariable String key, + @RequestBody(required = false) String value + ) throws IOException + { + SessionEntry session = authFilter.handle(request, response); + + if (session == null) + { + return; + } + + if (!configService.setKey(session.getUser(), key, value)) + { + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } + + @RequestMapping(path = "/{key:.+}", method = DELETE) + public void unsetKey( + HttpServletRequest request, + HttpServletResponse response, + @PathVariable String key + ) throws IOException + { + SessionEntry session = authFilter.handle(request, response); + + if (session == null) + { + return; + } + + if (!configService.unsetKey(session.getUser(), key)) + { + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } +} diff --git a/http-service/src/main/java/net/runelite/http/service/config/ConfigService.java b/http-service/src/main/java/net/runelite/http/service/config/ConfigService.java new file mode 100644 index 0000000000..6c48a60277 --- /dev/null +++ b/http-service/src/main/java/net/runelite/http/service/config/ConfigService.java @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2017-2019, Adam + * 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.http.service.config; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Strings; +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSyntaxException; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; +import static com.mongodb.client.model.Filters.eq; +import com.mongodb.client.model.IndexOptions; +import com.mongodb.client.model.Indexes; +import com.mongodb.client.model.UpdateOptions; +import static com.mongodb.client.model.Updates.combine; +import static com.mongodb.client.model.Updates.set; +import static com.mongodb.client.model.Updates.unset; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import javax.annotation.Nullable; +import net.runelite.http.api.RuneLiteAPI; +import net.runelite.http.api.config.ConfigEntry; +import net.runelite.http.api.config.Configuration; +import org.bson.Document; +import org.bson.conversions.Bson; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +@Service +public class ConfigService +{ + private static final int MAX_DEPTH = 8; + private static final int MAX_VALUE_LENGTH = 262144; + + private final Gson GSON = RuneLiteAPI.GSON; + private final UpdateOptions upsertUpdateOptions = new UpdateOptions().upsert(true); + + private final MongoCollection mongoCollection; + + @Autowired + public ConfigService( + MongoClient mongoClient, + @Value("${mongo.database}") String databaseName + ) + { + + MongoDatabase database = mongoClient.getDatabase(databaseName); + MongoCollection collection = database.getCollection("config"); + this.mongoCollection = collection; + + // Create unique index on _userId + IndexOptions indexOptions = new IndexOptions().unique(true); + collection.createIndex(Indexes.ascending("_userId"), indexOptions); + } + + private Document getConfig(int userId) + { + return mongoCollection.find(eq("_userId", userId)).first(); + } + + public Configuration get(int userId) + { + Map configMap = getConfig(userId); + + if (configMap == null || configMap.isEmpty()) + { + return new Configuration(Collections.emptyList()); + } + + List config = new ArrayList<>(); + + for (String group : configMap.keySet()) + { + // Reserved keys + if (group.startsWith("_") || group.startsWith("$")) + { + continue; + } + + Map groupMap = (Map) configMap.get(group); + + for (Map.Entry entry : groupMap.entrySet()) + { + String key = entry.getKey(); + Object value = entry.getValue(); + + if (value instanceof Map || value instanceof Collection) + { + value = GSON.toJson(entry.getValue()); + } + else if (value == null) + { + continue; + } + + ConfigEntry configEntry = new ConfigEntry(); + configEntry.setKey(group + "." + key.replace(':', '.')); + configEntry.setValue(value.toString()); + config.add(configEntry); + } + } + + return new Configuration(config); + } + + public List patch(int userID, Configuration config) + { + List failures = new ArrayList<>(); + List sets = new ArrayList<>(config.getConfig().size()); + for (ConfigEntry entry : config.getConfig()) + { + Bson s = setForKV(entry.getKey(), entry.getValue()); + if (s == null) + { + failures.add(entry.getKey()); + } + else + { + sets.add(s); + } + } + + if (sets.size() > 0) + { + mongoCollection.updateOne( + eq("_userId", userID), + combine(sets), + upsertUpdateOptions + ); + } + + return failures; + } + + @Nullable + private Bson setForKV(String key, @Nullable String value) + { + if (key.startsWith("$") || key.startsWith("_")) + { + return null; + } + + String[] split = key.split("\\.", 2); + if (split.length != 2) + { + return null; + } + + String dbKey = split[0] + "." + split[1].replace('.', ':'); + + if (Strings.isNullOrEmpty(value)) + { + return unset(dbKey); + } + + if (!validateJson(value)) + { + return null; + } + + Object jsonValue = parseJsonString(value); + return set(dbKey, jsonValue); + } + + public boolean setKey( + int userId, + String key, + @Nullable String value + ) + { + Bson set = setForKV(key, value); + if (set == null) + { + return false; + } + + mongoCollection.updateOne(eq("_userId", userId), + set, + upsertUpdateOptions); + return true; + } + + public boolean unsetKey( + int userId, + String key + ) + { + Bson set = setForKV(key, null); + if (set == null) + { + return false; + } + + mongoCollection.updateOne(eq("_userId", userId), set); + return true; + } + + @VisibleForTesting + static Object parseJsonString(String value) + { + Object jsonValue; + try + { + jsonValue = RuneLiteAPI.GSON.fromJson(value, Object.class); + if (jsonValue == null) + { + return value; + } + else if (jsonValue instanceof Double || jsonValue instanceof Float) + { + Number number = (Number) jsonValue; + if (Math.floor(number.doubleValue()) == number.doubleValue() && !Double.isInfinite(number.doubleValue())) + { + // value is an int or long. 'number' might be truncated so parse it from 'value' + try + { + jsonValue = Integer.parseInt(value); + } + catch (NumberFormatException ex) + { + try + { + jsonValue = Long.parseLong(value); + } + catch (NumberFormatException ex2) + { + + } + } + } + } + } + catch (JsonSyntaxException ex) + { + jsonValue = value; + } + return jsonValue; + } + + @VisibleForTesting + static boolean validateJson(String value) + { + try + { + // I couldn't figure out a better way to do this than a second json parse + JsonElement jsonElement = RuneLiteAPI.GSON.fromJson(value, JsonElement.class); + if (jsonElement == null) + { + return value.length() < MAX_VALUE_LENGTH; + } + return validateObject(jsonElement, 1); + } + catch (JsonSyntaxException ex) + { + // the client submits the string representation of objects which is not always valid json, + // eg. a value with a ':' in it. We just ignore it now. We can't json encode the values client + // side due to them already being strings, which prevents gson from being able to convert them + // to ints/floats/maps etc. + return value.length() < MAX_VALUE_LENGTH; + } + } + + private static boolean validateObject(JsonElement jsonElement, int depth) + { + if (depth >= MAX_DEPTH) + { + return false; + } + + if (jsonElement.isJsonObject()) + { + JsonObject jsonObject = jsonElement.getAsJsonObject(); + + for (Map.Entry entry : jsonObject.entrySet()) + { + JsonElement element = entry.getValue(); + + if (!validateObject(element, depth + 1)) + { + return false; + } + } + } + else if (jsonElement.isJsonArray()) + { + JsonArray jsonArray = jsonElement.getAsJsonArray(); + + for (int i = 0; i < jsonArray.size(); ++i) + { + JsonElement element = jsonArray.get(i); + + if (!validateObject(element, depth + 1)) + { + return false; + } + } + } + else if (jsonElement.isJsonPrimitive()) + { + JsonPrimitive jsonPrimitive = jsonElement.getAsJsonPrimitive(); + String value = jsonPrimitive.getAsString(); + if (value.length() >= MAX_VALUE_LENGTH) + { + return false; + } + } + + return true; + } +} diff --git a/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeController.java b/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeController.java new file mode 100644 index 0000000000..509f2bdb70 --- /dev/null +++ b/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeController.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2019, Adam + * 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.http.service.ge; + +import com.google.gson.Gson; +import java.io.IOException; +import java.time.Instant; +import java.util.Collection; +import java.util.stream.Collectors; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import net.runelite.http.api.RuneLiteAPI; +import net.runelite.http.api.ge.GrandExchangeTrade; +import net.runelite.http.service.account.AuthFilter; +import net.runelite.http.service.account.beans.SessionEntry; +import net.runelite.http.service.util.redis.RedisPool; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import redis.clients.jedis.Jedis; + +@RestController +@RequestMapping("/ge") +public class GrandExchangeController +{ + private static final Gson GSON = RuneLiteAPI.GSON; + + private final GrandExchangeService grandExchangeService; + private final AuthFilter authFilter; + private final RedisPool redisPool; + + @Autowired + public GrandExchangeController(GrandExchangeService grandExchangeService, AuthFilter authFilter, RedisPool redisPool) + { + this.grandExchangeService = grandExchangeService; + this.authFilter = authFilter; + this.redisPool = redisPool; + } + + @PostMapping + public void submit(HttpServletRequest request, HttpServletResponse response, @RequestBody GrandExchangeTrade grandExchangeTrade) throws IOException + { + SessionEntry session = null; + if (request.getHeader(RuneLiteAPI.RUNELITE_AUTH) != null) + { + session = authFilter.handle(request, response); + if (session == null) + { + // error is set here on the response, so we shouldn't continue + return; + } + } + Integer userId = session == null ? null : session.getUser(); + + // We don't keep track of pending trades in the web UI, so only add cancelled or completed trades + if (userId != null && + grandExchangeTrade.getQty() > 0 && + (grandExchangeTrade.isCancel() || grandExchangeTrade.getQty() == grandExchangeTrade.getTotal())) + { + grandExchangeService.add(userId, grandExchangeTrade); + } + + Trade trade = new Trade(); + trade.setBuy(grandExchangeTrade.isBuy()); + trade.setCancel(grandExchangeTrade.isCancel()); + trade.setLogin(grandExchangeTrade.isLogin()); + trade.setItemId(grandExchangeTrade.getItemId()); + trade.setQty(grandExchangeTrade.getQty()); + trade.setDqty(grandExchangeTrade.getDqty()); + trade.setTotal(grandExchangeTrade.getTotal()); + trade.setSpent(grandExchangeTrade.getDspent()); + trade.setOffer(grandExchangeTrade.getOffer()); + trade.setSlot(grandExchangeTrade.getSlot()); + trade.setTime((int) (System.currentTimeMillis() / 1000L)); + trade.setMachineId(request.getHeader(RuneLiteAPI.RUNELITE_MACHINEID)); + trade.setUserId(userId); + trade.setIp(request.getHeader("X-Forwarded-For")); + trade.setUa(request.getHeader("User-Agent")); + trade.setWorldType(grandExchangeTrade.getWorldType()); + trade.setSeq(grandExchangeTrade.getSeq()); + Instant resetTime = grandExchangeTrade.getResetTime(); + trade.setResetTime(resetTime == null ? 0L : resetTime.getEpochSecond()); + + String json = GSON.toJson(trade); + try (Jedis jedis = redisPool.getResource()) + { + jedis.publish("ge", json); + } + } + + @GetMapping + public Collection get(HttpServletRequest request, HttpServletResponse response, + @RequestParam(required = false, defaultValue = "1024") int limit, + @RequestParam(required = false, defaultValue = "0") int offset) throws IOException + { + SessionEntry session = authFilter.handle(request, response); + + if (session == null) + { + return null; + } + + return grandExchangeService.get(session.getUser(), limit, offset).stream() + .map(GrandExchangeController::convert) + .collect(Collectors.toList()); + } + + private static GrandExchangeTradeHistory convert(TradeEntry tradeEntry) + { + GrandExchangeTradeHistory grandExchangeTrade = new GrandExchangeTradeHistory(); + grandExchangeTrade.setBuy(tradeEntry.getAction() == TradeAction.BUY); + grandExchangeTrade.setItemId(tradeEntry.getItem()); + grandExchangeTrade.setQuantity(tradeEntry.getQuantity()); + grandExchangeTrade.setPrice(tradeEntry.getPrice()); + grandExchangeTrade.setTime(tradeEntry.getTime()); + return grandExchangeTrade; + } + + @DeleteMapping + public void delete(HttpServletRequest request, HttpServletResponse response) throws IOException + { + SessionEntry session = authFilter.handle(request, response); + + if (session == null) + { + return; + } + + grandExchangeService.delete(session.getUser()); + } +} diff --git a/http-service/src/test/java/net/runelite/http/service/config/ConfigServiceTest.java b/http-service/src/test/java/net/runelite/http/service/config/ConfigServiceTest.java new file mode 100644 index 0000000000..e74eb4d4fa --- /dev/null +++ b/http-service/src/test/java/net/runelite/http/service/config/ConfigServiceTest.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2019, Adam + * 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.http.service.config; + +import com.google.common.collect.ImmutableMap; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import org.junit.Test; + +public class ConfigServiceTest +{ + @Test + public void testParseJsonString() + { + assertEquals(1, ConfigService.parseJsonString("1")); + assertEquals(3.14, ConfigService.parseJsonString("3.14")); + assertEquals(1L << 32, ConfigService.parseJsonString("4294967296")); + assertEquals("test", ConfigService.parseJsonString("test")); + assertEquals("test", ConfigService.parseJsonString("\"test\"")); + assertEquals(ImmutableMap.of("key", "value"), ConfigService.parseJsonString("{\"key\": \"value\"}")); + } + + @Test + public void testValidateJson() + { + assertTrue(ConfigService.validateJson("1")); + assertTrue(ConfigService.validateJson("3.14")); + assertTrue(ConfigService.validateJson("test")); + assertTrue(ConfigService.validateJson("\"test\"")); + assertTrue(ConfigService.validateJson("key:value")); + assertTrue(ConfigService.validateJson("{\"key\": \"value\"}")); + assertTrue(ConfigService.validateJson("\n")); + } +} \ No newline at end of file diff --git a/http-service/src/test/java/net/runelite/http/service/hiscore/HiscoreServiceTest.java b/http-service/src/test/java/net/runelite/http/service/hiscore/HiscoreServiceTest.java new file mode 100644 index 0000000000..7cb2ac5e45 --- /dev/null +++ b/http-service/src/test/java/net/runelite/http/service/hiscore/HiscoreServiceTest.java @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2017, Adam + * 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.http.service.hiscore; + +import java.io.IOException; +import net.runelite.http.api.hiscore.HiscoreEndpoint; +import net.runelite.http.api.hiscore.HiscoreResult; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class HiscoreServiceTest +{ + private static final String RESPONSE = "654683,705,1304518\n" + + "679419,50,107181\n" + + "550667,48,85764\n" + + "861497,50,101366\n" + + "891591,48,87843\n" + + "-1,1,4\n" + + "840255,27,10073\n" + + "1371912,10,1310\n" + + "432193,56,199795\n" + + "495638,56,198304\n" + + "514466,37,27502\n" + + "456981,54,159727\n" + + "459159,49,93010\n" + + "1028855,8,823\n" + + "862906,29,12749\n" + + "795020,31,16097\n" + + "673591,5,495\n" + + "352676,51,112259\n" + + "428419,40,37235\n" + + "461887,43,51971\n" + + "598582,1,10\n" + + "638177,1,0\n" + + "516239,9,1000\n" + + "492790,1,0\n" + + "2,2460\n" // leagues + + "-1,-1\n" + + "73,1738\n" + + "531,1432\n" + + "324,212\n" + + "8008,131\n" + + "1337,911\n" + + "42,14113\n" + + "1,777\n" + + "254,92\n" + + "-1,-1\n" // lms + + "1,241\n" // soul wars + + "24870,37\n" + + "15020,388\n" + + "50463,147\n" + + "-1,-1\n" + + "92357,1\n" + + "22758,637\n" + + "22744,107\n" + + "-1,-1\n" + + "20150,17\n" + + "29400,18\n" + + "13465,172\n" + + "1889,581\n" + + "42891,11\n" + + "1624,1957\n" + + "1243,2465\n" + + "1548,2020\n" + + "-1,-1\n" + + "16781,327\n" + + "19004,149\n" + + "-1,-1\n" + + "72046,5\n" + + "5158,374\n" + + "20902,279\n" + + "702,6495\n" + + "10170,184\n" + + "8064,202\n" + + "6936,2\n" + + "2335,9\n" + + "-1,-1\n" + + "-1,-1\n" + + "19779,22\n" + + "58283,10\n" + + "-1,-1\n" + + "-1,-1\n" + + "-1,-1\n" + + "29347,130\n" + + "723,4\n" + + "1264,38\n" + + "44595,4\n" + + "24820,4\n" + + "12116,782\n" + + "2299,724\n" + + "19301,62\n" + + "1498,5847\n"; + + private final MockWebServer server = new MockWebServer(); + + @Before + public void before() throws IOException + { + server.enqueue(new MockResponse().setBody(RESPONSE)); + + server.start(); + } + + @After + public void after() throws IOException + { + server.shutdown(); + } + + @Test + public void testNormalLookup() throws Exception + { + HiscoreTestService hiscores = new HiscoreTestService(server.url("/")); + + HiscoreResult result = hiscores.lookupUsername("zezima", HiscoreEndpoint.NORMAL.getHiscoreURL()); + + Assert.assertEquals(50, result.getAttack().getLevel()); + Assert.assertEquals(159727L, result.getFishing().getExperience()); + Assert.assertEquals(492790, result.getConstruction().getRank()); + Assert.assertEquals(1432, result.getClueScrollAll().getLevel()); + Assert.assertEquals(324, result.getClueScrollBeginner().getRank()); + Assert.assertEquals(8008, result.getClueScrollEasy().getRank()); + Assert.assertEquals(911, result.getClueScrollMedium().getLevel()); + Assert.assertEquals(42, result.getClueScrollHard().getRank()); + Assert.assertEquals(777, result.getClueScrollElite().getLevel()); + Assert.assertEquals(254, result.getClueScrollMaster().getRank()); + Assert.assertEquals(-1, result.getLastManStanding().getLevel()); + Assert.assertEquals(241, result.getSoulWarsZeal().getLevel()); + Assert.assertEquals(2460, result.getLeaguePoints().getLevel()); + Assert.assertEquals(37, result.getAbyssalSire().getLevel()); + Assert.assertEquals(92357, result.getCallisto().getRank()); + Assert.assertEquals(5847, result.getZulrah().getLevel()); + } + +} diff --git a/injector/src/main/java/com/openosrs/injector/injectors/MixinInjector.java b/injector/src/main/java/com/openosrs/injector/injectors/MixinInjector.java index 8202be72a7..f9d0b8e472 100644 --- a/injector/src/main/java/com/openosrs/injector/injectors/MixinInjector.java +++ b/injector/src/main/java/com/openosrs/injector/injectors/MixinInjector.java @@ -438,7 +438,7 @@ public class MixinInjector extends AbstractInjector else if (hasInject) { // Make sure the method doesn't invoke copied methods - for (Instruction i : mixinMethod.getCode().getInstructions()) + /*for (Instruction i : mixinMethod.getCode().getInstructions()) { if (i instanceof InvokeInstruction) { @@ -446,10 +446,10 @@ public class MixinInjector extends AbstractInjector if (copiedMethods.containsKey(ii.getMethod())) { - throw new InjectException("Injected methods cannot invoke copied methods"); + throw new InjectException("Injected methods cannot invoke copied methods " + ii.toString()); } } - } + }*/ Method copy = new Method(targetClass, mixinMethod.getName(), mixinMethod.getDescriptor()); moveCode(copy, mixinMethod.getCode()); diff --git a/runelite-api/src/main/java/net/runelite/api/AbstractArchive.java b/runelite-api/src/main/java/net/runelite/api/AbstractArchive.java new file mode 100644 index 0000000000..0be27dfa46 --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/AbstractArchive.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2020, Noodleeater + * 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.api; + +/** + * Represents an archive of data, which is ordered into "groups" of "files". + */ +public interface AbstractArchive extends IndexDataBase +{ + /** + * the methods bellow are usefull for reading byte data from the cache + */ + int getGroupCount(); + + byte[] getConfigData(int archiveId, int fileId); + + int[] getFileIds(int groupId); + + int[][] getFileIds(); + + byte[] getFile(int groupId, int fileId); + + int getGroupFileCount(int groupId); + + int[] getFileCounts(); +} diff --git a/runelite-api/src/main/java/net/runelite/api/AnimationID.java b/runelite-api/src/main/java/net/runelite/api/AnimationID.java index 792530eed6..7c4d40e61c 100644 --- a/runelite-api/src/main/java/net/runelite/api/AnimationID.java +++ b/runelite-api/src/main/java/net/runelite/api/AnimationID.java @@ -43,10 +43,11 @@ public final class AnimationID public static final int WOODCUTTING_RUNE = 867; public static final int WOODCUTTING_GILDED = 8303; public static final int WOODCUTTING_DRAGON = 2846; + public static final int WOODCUTTING_DRAGON_OR = 24; public static final int WOODCUTTING_INFERNAL = 2117; public static final int WOODCUTTING_3A_AXE = 7264; public static final int WOODCUTTING_CRYSTAL = 8324; - public static final int WOODCUTTING_TRAILBLAZER = 8778; + public static final int WOODCUTTING_TRAILBLAZER = 8778; // Same animation as Infernal axe (or) public static final int CONSUMING = 829; // consuming consumables public static final int FIREMAKING = 733; public static final int DEATH = 836; @@ -96,6 +97,7 @@ public final class AnimationID public static final int CRAFTING_SPINNING = 894; public static final int CRAFTING_POTTERS_WHEEL = 883; public static final int CRAFTING_POTTERY_OVEN = 24975; + public static final int CRAFTING_LOOM = 2270; public static final int SMITHING_SMELTING = 899; public static final int SMITHING_CANNONBALL = 827; //cball smithing uses this and SMITHING_SMELTING public static final int SMITHING_ANVIL = 898; @@ -106,19 +108,10 @@ public final class AnimationID public static final int FISHING_HARPOON = 618; public static final int FISHING_BARBTAIL_HARPOON = 5108; public static final int FISHING_DRAGON_HARPOON = 7401; + public static final int FISHING_DRAGON_HARPOON_OR = 88; public static final int FISHING_INFERNAL_HARPOON = 7402; public static final int FISHING_CRYSTAL_HARPOON = 8336; - public static final int CRYSTALLINE_RAT_DEATH = 8334; - public static final int CRYSTALLINE_BAT_DEATH = 4917; - public static final int CRYSTALLINE_WOLF_DEATH = 8335; - public static final int CRYSTALLINE_SPIDER_DEATH = 8338; - public static final int CRYSTALLINE_UNICORN_DEATH = 6377; - public static final int CRYSTALLINE_DRAGON_DEATH = 92; - public static final int CRYSTALLINE_BEAR_DEATH = 4929; - public static final int CRYSTALLINE_DARK_BEAST_DEATH = 2733; - public static final int CORRUPTED_SCORPION_DEATH = 6256; - public static final int FISHING_TRAILBLAZER_HARPOON = 8784; - public static final int FISHING_TRAILBLAZER_HARPOON_2 = 8785; + public static final int FISHING_TRAILBLAZER_HARPOON = 8784; // Same animation as Infernal harpoon (or) public static final int FISHING_OILY_ROD = 622; public static final int FISHING_KARAMBWAN = 1193; public static final int FISHING_CRUSHING_INFERNAL_EELS = 7553; @@ -150,10 +143,11 @@ public final class AnimationID public static final int MINING_DRAGON_PICKAXE = 7139; public static final int MINING_DRAGON_PICKAXE_UPGRADED = 642; public static final int MINING_DRAGON_PICKAXE_OR = 8346; + public static final int MINING_DRAGON_PICKAXE_OR_TRAILBLAZER = 8887; public static final int MINING_INFERNAL_PICKAXE = 4482; public static final int MINING_3A_PICKAXE = 7283; public static final int MINING_CRYSTAL_PICKAXE = 8347; - public static final int MINING_TRAILBLAZER_PICKAXE = 8787; + public static final int MINING_TRAILBLAZER_PICKAXE = 8787; // Same animation as Infernal pickaxe (or) public static final int MINING_TRAILBLAZER_PICKAXE_2 = 8788; public static final int MINING_TRAILBLAZER_PICKAXE_3 = 8789; public static final int MINING_MOTHERLODE_BRONZE = 6753; @@ -167,16 +161,16 @@ public final class AnimationID public static final int MINING_MOTHERLODE_DRAGON = 6758; public static final int MINING_MOTHERLODE_DRAGON_UPGRADED = 335; public static final int MINING_MOTHERLODE_DRAGON_OR = 8344; + public static final int MINING_MOTHERLODE_DRAGON_OR_TRAILBLAZER = 8886; public static final int MINING_MOTHERLODE_INFERNAL = 4481; public static final int MINING_MOTHERLODE_3A = 7282; public static final int MINING_MOTHERLODE_CRYSTAL = 8345; - public static final int MINING_MOTHERLODE_TRAILBLAZER = 8786; + public static final int MINING_MOTHERLODE_TRAILBLAZER = 8786; // Same animation as Infernal pickaxe (or) public static final int DENSE_ESSENCE_CHIPPING = 7201; public static final int DENSE_ESSENCE_CHISELING = 7202; public static final int HERBLORE_POTIONMAKING = 363; //used for both herb and secondary public static final int MAGIC_CHARGING_ORBS = 726; public static final int MAGIC_MAKE_TABLET = 4068; - public static final int TABLET_TELEPORT = 4069; public static final int MAGIC_ENCHANTING_JEWELRY = 931; public static final int MAGIC_ENCHANTING_AMULET_1 = 719; // sapphire, opal, diamond public static final int MAGIC_ENCHANTING_AMULET_2 = 720; // emerald, jade, dragonstone @@ -209,81 +203,23 @@ public final class AnimationID public static final int LEAGUE_HOME_TELEPORT_4 = 8803; public static final int LEAGUE_HOME_TELEPORT_5 = 8805; public static final int LEAGUE_HOME_TELEPORT_6 = 8807; + public static final int CONSTRUCTION = 3676; public static final int SAND_COLLECTION = 895; public static final int PISCARILIUS_CRANE_REPAIR = 7199; public static final int HOME_MAKE_TABLET = 4067; - public static final int THIEVING_STALL = 832; - public static final int PICKPOCKET_SUCCESS = 881; - public static final int PULL_LEVER = 2140; - public static final int STANDARD_PURPLE_TELEPORT = 714; - public static final int ECTOPHIAL_TELEPORT = 878; - public static final int FAIRY_RING_TELEPORT = 3265; - public static final int SCROLL_TELEPORT = 3864; - public static final int XERICS_TALISMAN_TELEPORT = 3865; - public static final int WILDERNESS_OBELISK_TELEPORT = 3945; - public static final int SEED_POD_TELEPORT = 4544; - - //block animations for players and perhaps npcs as well? - public static final int BLOCK_DEFENDER = 4177; - public static final int BLOCK_NO_SHIELD = 420; - public static final int BLOCK_SHIELD = 1156; - public static final int BLOCK_SWORD = 388; - public static final int BLOCK_UNARMED = 424; // Same Animation as failed pickpocked public static final int DRAGONFIRE_SHIELD_SPECIAL = 6696; - //Player Emotes - public static final int YES = 855; - public static final int NO = 856; - public static final int BOW = 858; - public static final int ANGRY = 859; - public static final int THINK = 857; - public static final int WAVE = 863; - public static final int SHRUG = 2113; - public static final int CHEER = 862; - public static final int BECKON = 864; - public static final int LAUGH = 861; - public static final int JUMP_FOR_JOY = 2109; - public static final int YAWN = 2111; - public static final int DANCE = 866; - public static final int JIG = 2106; - public static final int SPIN = 2107; - public static final int HEAD_BANG = 2108; - public static final int CRY = 860; - public static final int BLOW_KISS = 1374; - public static final int PANIC = 2105; - public static final int RASPBERRY = 2110; - public static final int CLAP = 865; - public static final int SALUTE = 2112; - public static final int GOBLIN_BOW = 2127; - public static final int GOBLIN_SALUTE = 2128; + // Ectofuntus animations + public static final int ECTOFUNTUS_FILL_SLIME_BUCKET = 4471; + public static final int ECTOFUNTUS_GRIND_BONES = 1648; + public static final int ECTOFUNTUS_INSERT_BONES = 1649; + public static final int ECTOFUNTUS_EMPTY_BIN = 1650; - // Combat counter - public static final int BARRAGE_ANIMATION = 1979; - public static final int BLITZ_ANIMATION = 1978; - public static final int CHIN_ANIMATION = 7618; - - //Supplies Tracker - public static final int ONEHAND_SLASH_SWORD_ANIMATION = 390; - public static final int ONEHAND_STAB_SWORD_ANIMATION = 386; - public static final int SCYTHE_OF_VITUR_ANIMATION = 8056; - public static final int LOW_LEVEL_STANDARD_SPELLS = 711; - public static final int WAVE_SPELL_ANIMATION = 727; - public static final int SURGE_SPELL_ANIMATION = 7855; - public static final int HIGH_ALCH_ANIMATION = 713; - public static final int LUNAR_HUMIDIFY = 6294; - public static final int PRAY_AT_ALTAR = 645; - public static final int ENSOULED_HEADS_ANIMATION = 7198; - - // Weapon attack animations - public static final int ONEHAND_SLASH_AXE_ANIMATION = 395; - public static final int ONEHAND_CRUSH_PICKAXE_ANIMATION = 400; - public static final int ONEHAND_CRUSH_AXE_ANIMATION = 401; - public static final int UNARMED_PUNCH_ANIMATION = 422; - public static final int UNARMED_KICK_ANIMATION = 423; - public static final int BOW_ATTACK_ANIMATION = 426; - public static final int ONEHAND_STAB_HALBERD_ANIMATION = 428; - public static final int ONEHAND_SLASH_HALBERD_ANIMATION = 440; + // NPC animations + public static final int TZTOK_JAD_MAGIC_ATTACK = 2656; + public static final int TZTOK_JAD_RANGE_ATTACK = 2652; + public static final int HELLHOUND_DEFENCE = 6566; // Farming public static final int FARMING_HARVEST_FRUIT_TREE = 2280; @@ -319,205 +255,7 @@ public final class AnimationID public static final int ROCKSLUG_DEATH = 1568; public static final int ZYGOMITE_DEATH = 3327; public static final int IMP_DEATH = 172; - public static final int NIGHTMARE_DEATH = 8612; // POH Animations public static final int INCENSE_BURNER = 3687; - public static final int LOW_LEVEL_MAGIC_ATTACK = 1162; - public static final int HIGH_LEVEL_MAGIC_ATTACK = 1167; - public static final int BLOWPIPE_ATTACK = 5061; - - // NPC animations - public static final int HELLHOUND_DEFENCE = 6566; - public static final int BLACKJACK_KO = 838; - - // Fight Caves - public static final int TZTOK_JAD_RANGE_ATTACK = 2652; - public static final int TZTOK_JAD_MELEE_ATTACK = 2655; - public static final int TZTOK_JAD_MAGIC_ATTACK = 2656; - public static final int TOK_XIL_RANGE_ATTACK = 2633; - public static final int TOK_XIL_MELEE_ATTACK = 2628; - public static final int KET_ZEK_MELEE_ATTACK = 2644; - public static final int KET_ZEK_MAGE_ATTACK = 2647; - public static final int MEJ_KOT_MELEE_ATTACK = 2637; - public static final int MEJ_KOT_HEAL_ATTACK = 2639; - - // Vorkath - public static final int VORKATH_WAKE_UP = 7950; - public static final int VORKATH_DEATH = 7949; - public static final int VORKATH_SLASH_ATTACK = 7951; - public static final int VORKATH_ATTACK = 7952; - public static final int VORKATH_FIRE_BOMB_OR_SPAWN_ATTACK = 7960; - public static final int VORKATH_ACID_ATTACK = 7957; - - // Tekton - public static final int TEKTON_ANVIL = 7475; - public static final int TEKTON_AUTO1 = 7482; - public static final int TEKTON_AUTO2 = 7483; - public static final int TEKTON_AUTO3 = 7484; - public static final int TEKTON_FAST_AUTO1 = 7478; - public static final int TEKTON_FAST_AUTO2 = 7488; - public static final int TEKTON_ENRAGE_AUTO1 = 7492; - public static final int TEKTON_ENRAGE_AUTO2 = 7493; - public static final int TEKTON_ENRAGE_AUTO3 = 7494; - - // Hydra - public static final int HYDRA_WALKING = 8232; - public static final int HYDRA_IDLE = 8233; - public static final int HYDRA_POISON_1 = 8234; - public static final int HYDRA_RANGED_1 = 8235; - public static final int HYDRA_MAGIC_1 = 8236; - public static final int HYDRA_1_1 = 8237; - public static final int HYDRA_1_2 = 8238; - public static final int HYDRA_LIGHTNING = 8241; - public static final int HYDRA_RANGED_2 = 8242; - public static final int HYDRA_MAGIC_2 = 8243; - public static final int HYDRA_2_1 = 8244; - public static final int HYDRA_2_2 = 8245; - public static final int HYDRA_FIRE = 8248; - public static final int HYDRA_RANGED_3 = 8249; - public static final int HYDRA_MAGIC_3 = 8250; - public static final int HYDRA_3_1 = 8251; - public static final int HYDRA_3_2 = 8252; - public static final int HYDRA_MAGIC_4 = 8254; - public static final int HYDRA_POISON_4 = 8254; - public static final int HYDRA_RANGED_4 = 8255; - public static final int HYDRA_RANGED_OR_POISON_ATTACK = 8256; - public static final int HYDRA_4_1 = 8257; - public static final int HYDRA_4_2 = 8258; - - // Inferno animations - public static final int JAL_NIB = 7574; - public static final int JAL_MEJRAH = 7578; - public static final int JAL_MEJRAH_STAND = 7577; - public static final int JAL_AK_RANGE_ATTACK = 7581; - public static final int JAL_AK_MELEE_ATTACK = 7582; - public static final int JAL_AK_MAGIC_ATTACK = 7583; - public static final int JAL_IMKOT = 7597; - public static final int JAL_XIL_MELEE_ATTACK = 7604; - public static final int JAL_XIL_RANGE_ATTACK = 7605; - public static final int JAL_ZEK_MAGE_ATTACK = 7610; - public static final int JAL_ZEK_MELEE_ATTACK = 7612; - public static final int JALTOK_JAD_MELEE_ATTACK = 7590; - public static final int JALTOK_JAD_MAGE_ATTACK = 7592; - public static final int JALTOK_JAD_RANGE_ATTACK = 7593; - public static final int TZKAL_ZUK = 7566; - public static final int JAL_MEJJAK = 2858; - - // General Graardor - public static final int MINION_AUTO1 = 6154; - public static final int MINION_AUTO2 = 6156; - public static final int MINION_AUTO3 = 7071; - public static final int MINION_AUTO4 = 7073; - public static final int GENERAL_AUTO1 = 7018; - public static final int GENERAL_AUTO2 = 7020; - public static final int GENERAL_AUTO3 = 7021; - - // Kr'il Tsutsaroth - public static final int ZAMMY_GENERIC_AUTO = 64; - public static final int KRIL_AUTO = 6948; - public static final int KRIL_SPEC = 6950; - public static final int ZAKL_AUTO = 7077; - public static final int BALFRUG_AUTO = 4630; - - // Commander Zilyana - public static final int ZILYANA_MELEE_AUTO = 6964; - public static final int ZILYANA_AUTO = 6967; - public static final int ZILYANA_SPEC = 6970; - public static final int STARLIGHT_AUTO = 6376; - public static final int BREE_AUTO = 7026; - public static final int GROWLER_AUTO = 7037; - - // Kree'arra - public static final int KREE_RANGED = 6978; - public static final int SKREE_AUTO = 6955; - public static final int GEERIN_AUTO = 6956; - public static final int GEERIN_FLINCH = 6958; - public static final int KILISA_AUTO = 6957; - - // Vetion - public static final int VETION_EARTHQUAKE = 5507; - - // Zulrah - public static final int ZULRAH_DEATH = 5804; - public static final int ZULRAH_PHASE = 5072; - - //Dagannoth Kings - public static final int DAG_REX = 2853; - public static final int DAG_PRIME = 2854; - public static final int DAG_SUPREME = 2855; - - // Lizardman shaman - public static final int LIZARDMAN_SHAMAN_SPAWN = 7157; - public static final int LIZARDMAN_SHAMAN_SPAWN_EXPLOSION = 7159; - - // Cerberus - public static final int CERBERUS_MAGIC_ATTACK = 4489; - public static final int CERBERUS_RANGED_ATTACK = 4490; - public static final int CERBERUS_MELEE_ATTACK = 4491; - public static final int CERBERUS_LAVA_ATTACK = 4493; - public static final int CERBERUS_SUMMON_GHOSTS = 4494; - - // Gauntlet Hunleff - public static final int HUNLEFF_TRAMPLE = 8420; - public static final int HUNLEFF_ATTACK = 8419; - public static final int HUNLEFF_TORNADO = 8418; - public static final int HUNLLEF_SWITCH_TO_MAGIC = 8754; - public static final int HUNLLEF_SWITCH_TO_RANGED = 8755; - - //Zalcano - public static final int ZALCANO_KNOCKED_DOWN = 8437; - public static final int ZALCANO_WAKEUP = 8439; - public static final int ZALCANO_ROCK_GLOWING = 8448; - - // Theatre of Blood - Sugadinti Maiden - public static final int SUGADINTI_MAIDEN_BLOOD_SPLAT_ATTACK = 8091; - public static final int SUGADINTI_MAIDEN_MAGIC_ATTACK = 8092; - public static final int SUGADINTI_MAIDEN_DEATH = 8094; - - // Theatre of Blood - Pestilent Bloat - public static final int BLOAT_SLEEP = 8082; - - // Theatre of Blood - Sotetseg - public static final int SOTETSEG_MELEE_ATTACK = 8138; - public static final int SOTETSEG_REGULAR_PROJECTILE_ATTACK = 8139; - - // Theatre of Blood - Verzik Vitur - public static final int VERZIK_PHASE_1_MAGIC_ATTACK = 8109; - public static final int VERZIK_PHASE_1_MAGIC_ATTACK_CHANNEL = 8110; - public static final int VERZIK_CHANGE_TO_PHASE_2 = 8111; - public static final int VERZIK_PHASE_2_MAGIC_ATTACK = 8114; - public static final int VERZIK_PHASE_2_BELLY_FLOP_ATTACK_1 = 8116; - public static final int VERZIK_PHASE_2_HEALING_CHANNEL = 8117; - public static final int VERZIK_PHASE_2_BELLY_FLOP_ATTACK_2 = 8118; - public static final int VERZIK_CHANGE_TO_PHASE_3 = 8119; - public static final int VERZIK_PHASE_3_MELEE_ATTACK = 8123; - public static final int VERZIK_PHASE_3_MAGIC_ATTACK = 8124; - public static final int VERZIK_PHASE_3_RANGED_ATTACK = 8125; - public static final int VERZIK_PHASE_3_GREEN_POOL_ATTACK = 8126; - public static final int VERZIK_PHASE_3_WEB_ATTACK = 8127; - public static final int VERZIK_DEATH_1 = 8128; - public static final int VERZIK_DEATH_2 = 8129; - - // The Nightmare of Ashihama - public static final int NIGHTMARE_SPAWN_SLEEPWALKERS = 8572; - public static final int NIGHTMARE_FLOATY = 8592; - public static final int NIGHTMARE_WALKING = 8592; - public static final int NIGHTMARE_IDLE = 8593; - public static final int NIGHTMARE_MELEE_ATTACK = 8594; - public static final int NIGHTMARE_MAGIC_ATTACK = 8595; - public static final int NIGHTMARE_RANGED_ATTACK = 8596; - public static final int NIGHTMARE_SURGE_ATTACK = 8597; - public static final int NIGHTMARE_GHOST_AOE_ATTACK = 8598; - public static final int NIGHTMARE_CURSE_PRAYERS_ATTACK = 8599; - public static final int NIGHTMARE_SPAWN_INFECTIOUS_SPORES = 8600; - public static final int NIGHTMARE_SPAWN_ROOM_SECTION_FLOWERS = 8601; - public static final int NIGHTMARE_CHANNEL_DEVASTATING_ATTACK = 8604; - public static final int NIGHTMARE_SWITCH_TO_DEVIL_PHASE = 8605; - public static final int NIGHTMARE_PARASITE_ATTACK = 8606; - public static final int NIGHTMARE_JUMP_DOWN = 8607; - public static final int NIGHTMARE_SINK_DOWN = 8608; - public static final int NIGHTMARE_JUMP_UP = 8609; - public static final int NIGHTMARE_JUMP_UP_2 = 8610; - public static final int NIGHTMARE_WAKE_UP = 8611; } diff --git a/runelite-api/src/main/java/net/runelite/api/Buffer.java b/runelite-api/src/main/java/net/runelite/api/Buffer.java new file mode 100644 index 0000000000..384b3cacc8 --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/Buffer.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2020, Noodleeater + * 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.api; + +/** + * Represents a byte buffer + */ +public interface Buffer extends Node +{ + byte[] getPayload(); + + int getOffset(); + + /** + * Use this api to write to byte buffers + */ + void writeByte(int var1); + + void writeShort(int var1); + + void writeMedium(int var1); + + void writeInt(int var1); + + void writeLong(long var1); + + void writeStringCp1252NullTerminated(String string); +} diff --git a/runelite-api/src/main/java/net/runelite/api/ChatMessageType.java b/runelite-api/src/main/java/net/runelite/api/ChatMessageType.java index f96d7fba63..d453bfbb35 100644 --- a/runelite-api/src/main/java/net/runelite/api/ChatMessageType.java +++ b/runelite-api/src/main/java/net/runelite/api/ChatMessageType.java @@ -117,7 +117,7 @@ public enum ChatMessageType */ MODAUTOTYPER(91), /** - * A game message (ie. when a setting is changed). + * A game message. (ie. when a setting is changed) */ CONSOLE(99), /** diff --git a/runelite-api/src/main/java/net/runelite/api/Client.java b/runelite-api/src/main/java/net/runelite/api/Client.java index 3ea377157c..1a1ec1a921 100644 --- a/runelite-api/src/main/java/net/runelite/api/Client.java +++ b/runelite-api/src/main/java/net/runelite/api/Client.java @@ -47,7 +47,7 @@ import org.slf4j.Logger; /** * Represents the RuneScape client. */ -public interface Client extends GameShell +public interface Client extends GameEngine { /** * The injected client invokes these callbacks to send events to us @@ -68,6 +68,8 @@ public interface Client extends GameShell */ Logger getLogger(); + String getBuildID(); + /** * Gets a list of all valid players from the player cache. * @@ -122,12 +124,25 @@ public interface Client extends GameShell /** * Adds a new chat message to the chatbox. * - * @param type the type of message - * @param name the name of the player that sent the message + * @param type the type of message + * @param name the name of the player that sent the message * @param message the message contents - * @param sender the sender/channel name + * @param sender the sender/channel name + * @return the message node for the message */ - void addChatMessage(ChatMessageType type, String name, String message, String sender); + MessageNode addChatMessage(ChatMessageType type, String name, String message, String sender); + + /** + * Adds a new chat message to the chatbox. + * + * @param type the type of message + * @param name the name of the player that sent the message + * @param message the message contents + * @param sender the sender/channel name + * @param postEvent whether to post the chat message event + * @return the message node for the message + */ + MessageNode addChatMessage(ChatMessageType type, String name, String message, String sender, boolean postEvent); /** * Gets the current game state. @@ -457,7 +472,7 @@ public interface Client extends GameShell int getMouseCurrentButton(); /** - * Gets the currently selected tile (ie. last right clicked tile). + * Gets the currently selected tile. (ie. last right clicked tile) * * @return the selected tile */ @@ -819,7 +834,7 @@ public interface Client extends GameShell * @param varps passed varps * @param varpId the VarpPlayer id * @return the value - * @see VarPlayer#id + * @see VarPlayer#getId() */ int getVarpValue(int[] varps, int varpId); @@ -1540,15 +1555,15 @@ public interface Client extends GameShell * * @param state the new player hidden state */ - void setPlayersHidden(boolean state); + void setOthersHidden(boolean state); /** - * Sets whether 2D sprites (ie. overhead prayers, PK skull) related to - * the other players are hidden. + * Sets whether 2D sprites related to the other players are hidden. + * (ie. overhead prayers, PK skull) * * @param state the new player 2D hidden state */ - void setPlayersHidden2D(boolean state); + void setOthersHidden2D(boolean state); /** * Sets whether or not friends are hidden. @@ -1564,6 +1579,13 @@ public interface Client extends GameShell */ void setFriendsChatMembersHidden(boolean state); + /** + * Sets whether or not ignored players are hidden. + * + * @param state the new ignored player hidden state + */ + void setIgnoresHidden(boolean state); + /** * Sets whether the local player is hidden. * @@ -1572,8 +1594,8 @@ public interface Client extends GameShell void setLocalPlayerHidden(boolean state); /** - * Sets whether 2D sprites (ie. overhead prayers, PK skull) related to - * the local player are hidden. + * Sets whether 2D sprites related to the local player are hidden. + * (ie. overhead prayers, PK skull) * * @param state new local player 2D hidden state */ @@ -1586,48 +1608,6 @@ public interface Client extends GameShell */ void setNPCsHidden(boolean state); - /** - * Increments the counter for how many times this npc has been selected to be hidden - * - * @param name npc name - */ - void addHiddenNpcName(String name); - - /** - * Decrements the counter for how many times this npc has been selected to be hidden - * - * @param name npc name - */ - void removeHiddenNpcName(String name); - - /** - * Forcibly unhides an npc by setting its counter to zero - * - * @param name npc name - */ - void forciblyUnhideNpcName(String name); - - /** - * Increments the counter for how many times this npc has been selected to be hidden on death - * - * @param name npc name - */ - void addHiddenNpcDeath(String name); - - /** - * Decrements the counter for how many times this npc has been selected to be hidden on death - * - * @param name npc name - */ - void removeHiddenNpcDeath(String name); - - /** - * Forcibly unhides a hidden-while-dead npc by setting its counter to zero - * - * @param name npc name - */ - void forciblyUnhideNpcDeath(String name); - /** * Sets whether 2D sprites (ie. overhead prayers) related to * the NPCs are hidden. @@ -2121,4 +2101,34 @@ public interface Client extends GameShell void setOutdatedScript(String outdatedScript); List getOutdatedScripts(); + + /** + * various archives you might want to use for reading data from cache + */ + AbstractArchive getSequenceDefinition_skeletonsArchive(); + + AbstractArchive getSequenceDefinition_archive(); + + AbstractArchive getSequenceDefinition_animationsArchive(); + + AbstractArchive getNpcDefinition_archive(); + + AbstractArchive getObjectDefinition_modelsArchive(); + + AbstractArchive getObjectDefinition_archive(); + + AbstractArchive getItemDefinition_archive(); + + AbstractArchive getKitDefinition_archive(); + + AbstractArchive getKitDefinition_modelsArchive(); + + AbstractArchive getSpotAnimationDefinition_archive(); + + AbstractArchive getSpotAnimationDefinition_modelArchive(); + + /** + * use createBuffer to create a new byte buffer + */ + Buffer createBuffer(byte[] initialBytes); } diff --git a/runelite-api/src/main/java/net/runelite/api/Constants.java b/runelite-api/src/main/java/net/runelite/api/Constants.java index b988d21fb0..bb5c789751 100644 --- a/runelite-api/src/main/java/net/runelite/api/Constants.java +++ b/runelite-api/src/main/java/net/runelite/api/Constants.java @@ -82,6 +82,11 @@ public class Constants public static final int TILE_FLAG_BRIDGE = 2; + /** + * The height of the overworld, in tiles. Coordinates above this are in caves and other such zones. + */ + public static final int OVERWORLD_MAX_Y = 4160; + /** * The number of milliseconds in a client tick. *

@@ -114,9 +119,4 @@ public class Constants * Height of a standard item sprite */ public static final int ITEM_SPRITE_HEIGHT = 32; - - /** - * The height of the overworld, in tiles. Coordinates above this are in caves and other such zones. - */ - public static final int OVERWORLD_MAX_Y = 4160; } diff --git a/runelite-api/src/main/java/net/runelite/api/DialogOption.java b/runelite-api/src/main/java/net/runelite/api/DialogOption.java new file mode 100644 index 0000000000..832492cf2d --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/DialogOption.java @@ -0,0 +1,48 @@ +package net.runelite.api; + +import javax.annotation.Nullable; +import java.util.Arrays; + +public enum DialogOption +{ + NPC_CONTINUE(15138819, -1), + PLAYER_CONTINUE(14221315, -1), + QUEST(12648448, 0), + ITEM_ONE(12648448, -1), + ITEM_TWO(12648448, 0), + CHAT_OPTION_ONE(14352385, 1), + CHAT_OPTION_TWO(14352385, 2), + CHAT_OPTION_THREE(14352385, 3), + CHAT_OPTION_FOUR(14352385, 4), + CHAT_OPTION_FIVE(14352385, 5), + PLAIN_CONTINUE(15007746, -1), + PLAIN_CONTINUE_TWO(720900, -1); + + private final int widgetUid; + private final int menuIndex; + + DialogOption(int widgetUid, int menuIndex) + { + this.widgetUid = widgetUid; + this.menuIndex = menuIndex; + } + + public int getWidgetUid() + { + return widgetUid; + } + + public int getMenuIndex() + { + return menuIndex; + } + + @Nullable + public static DialogOption of(int widgetUid, int menuIndex) + { + return Arrays.stream(values()) + .filter(option -> option.getWidgetUid() == widgetUid && option.getMenuIndex() == menuIndex) + .findFirst() + .orElse(null); + } +} \ No newline at end of file diff --git a/runelite-api/src/main/java/net/runelite/api/GameShell.java b/runelite-api/src/main/java/net/runelite/api/GameEngine.java similarity index 98% rename from runelite-api/src/main/java/net/runelite/api/GameShell.java rename to runelite-api/src/main/java/net/runelite/api/GameEngine.java index aa69462bfd..01b85ba512 100644 --- a/runelite-api/src/main/java/net/runelite/api/GameShell.java +++ b/runelite-api/src/main/java/net/runelite/api/GameEngine.java @@ -30,7 +30,7 @@ import java.awt.Canvas; /** * Represents the client game engine. */ -public interface GameShell +public interface GameEngine { /** * Gets the canvas that contains everything. diff --git a/runelite-api/src/main/java/net/runelite/api/HeadIcon.java b/runelite-api/src/main/java/net/runelite/api/HeadIcon.java index 6f70220ba9..ad8f00cc08 100644 --- a/runelite-api/src/main/java/net/runelite/api/HeadIcon.java +++ b/runelite-api/src/main/java/net/runelite/api/HeadIcon.java @@ -54,7 +54,7 @@ public enum HeadIcon */ REDEMPTION, /** - * Protect from range and mage (ie. used by Kalphite Queen). + * Protect from range and mage. (ie. used by Kalphite Queen) */ RANGE_MAGE } diff --git a/runelite-api/src/main/java/net/runelite/api/ItemID.java b/runelite-api/src/main/java/net/runelite/api/ItemID.java index ed667b6b68..d82361802d 100644 --- a/runelite-api/src/main/java/net/runelite/api/ItemID.java +++ b/runelite-api/src/main/java/net/runelite/api/ItemID.java @@ -11656,8 +11656,6 @@ public final class ItemID public static final int GIANT_BOULDER = 25314; public static final int GOBLIN_DECORATIONS = 25316; public static final int GNOME_CHILD_ICON = 25319; - public static final int GNOME_CHILD = 25320; - public static final int GNOME_CHILD_25321 = 25321; public static final int _20TH_ANNIVERSARY_HAT = 25322; public static final int _20TH_ANNIVERSARY_TOP = 25324; public static final int _20TH_ANNIVERSARY_BOTTOM = 25326; @@ -11698,5 +11696,60 @@ public final class ItemID public static final int TRAILBLAZER_RELIC_HUNTER_T1_ARMOUR_SET = 25380; public static final int TRAILBLAZER_RELIC_HUNTER_T2_ARMOUR_SET = 25383; public static final int TRAILBLAZER_RELIC_HUNTER_T3_ARMOUR_SET = 25386; + public static final int SWAMPBARK_BODY = 25389; + public static final int SWAMPBARK_GAUNTLETS = 25392; + public static final int SWAMPBARK_BOOTS = 25395; + public static final int SWAMPBARK_HELM = 25398; + public static final int SWAMPBARK_LEGS = 25401; + public static final int BLOODBARK_BODY = 25404; + public static final int BLOODBARK_GAUNTLETS = 25407; + public static final int BLOODBARK_BOOTS = 25410; + public static final int BLOODBARK_HELM = 25413; + public static final int BLOODBARK_LEGS = 25416; + public static final int URIUM_REMAINS = 25419; + public static final int BLEACHED_BONES = 25422; + public static final int GOLD_KEY_RED = 25424; + public static final int GOLD_KEY_BROWN = 25426; + public static final int GOLD_KEY_CRIMSON = 25428; + public static final int GOLD_KEY_BLACK = 25430; + public static final int GOLD_KEY_PURPLE = 25432; + public static final int ZEALOTS_ROBE_TOP = 25434; + public static final int ZEALOTS_ROBE_BOTTOM = 25436; + public static final int ZEALOTS_HELM = 25438; + public static final int ZEALOTS_BOOTS = 25440; + public static final int BRONZE_LOCKS = 25442; + public static final int STEEL_LOCKS = 25445; + public static final int BLACK_LOCKS = 25448; + public static final int SILVER_LOCKS = 25451; + public static final int GOLD_LOCKS = 25454; + public static final int BROKEN_COFFIN = 25457; + public static final int BRONZE_COFFIN = 25459; + public static final int STEEL_COFFIN = 25461; + public static final int BLACK_COFFIN = 25463; + public static final int SILVER_COFFIN = 25465; + public static final int GOLD_COFFIN = 25467; + public static final int OPEN_BRONZE_COFFIN = 25469; + public static final int OPEN_STEEL_COFFIN = 25470; + public static final int OPEN_BLACK_COFFIN = 25471; + public static final int OPEN_SILVER_COFFIN = 25472; + public static final int OPEN_GOLD_COFFIN = 25473; + public static final int TREE_WIZARDS_JOURNAL = 25474; + public static final int BLOODY_NOTES = 25476; + public static final int RUNESCROLL_OF_SWAMPBARK = 25478; + public static final int RUNESCROLL_OF_BLOODBARK = 25481; + public static final int TOXIC_BLOWPIPE_BETA__BRONZE = 25484; + public static final int TOXIC_BLOWPIPE_BETA__IRON = 25485; + public static final int TOXIC_BLOWPIPE_BETA__STEEL = 25486; + public static final int TOXIC_BLOWPIPE_BETA__BLACK = 25487; + public static final int TOXIC_BLOWPIPE_BETA__MITHRIL = 25488; + public static final int TOXIC_BLOWPIPE_BETA__ADAMANT = 25489; + public static final int TOXIC_BLOWPIPE_BETA__RUNE = 25490; + public static final int TOXIC_BLOWPIPE_BETA__DRAGON = 25491; + public static final int BLACK_DHIDE_BODY_BETA = 25492; + public static final int BLACK_DHIDE_CHAPS_BETA = 25493; + public static final int BLACK_DHIDE_VAMBRACES_BETA = 25494; + public static final int CRYSTAL_HELM_BETA = 25495; + public static final int CRYSTAL_BODY_BETA = 25496; + public static final int CRYSTAL_LEGS_BETA = 25497; /* This file is automatically generated. Do not edit. */ } \ No newline at end of file diff --git a/runelite-api/src/main/java/net/runelite/api/MenuAction.java b/runelite-api/src/main/java/net/runelite/api/MenuAction.java index 8d5074025b..c441e25b03 100644 --- a/runelite-api/src/main/java/net/runelite/api/MenuAction.java +++ b/runelite-api/src/main/java/net/runelite/api/MenuAction.java @@ -188,10 +188,6 @@ public enum MenuAction * Fifth menu action for an item. */ ITEM_FIFTH_OPTION(37), - /** - * Menu action to drop an item (identical to ITEM_FIFTH_OPTION). - */ - ITEM_DROP(37), /** * Menu action to use an item. */ diff --git a/runelite-api/src/main/java/net/runelite/api/MenuEntry.java b/runelite-api/src/main/java/net/runelite/api/MenuEntry.java index d224e6b183..9b0dd9061c 100644 --- a/runelite-api/src/main/java/net/runelite/api/MenuEntry.java +++ b/runelite-api/src/main/java/net/runelite/api/MenuEntry.java @@ -35,11 +35,11 @@ import lombok.NoArgsConstructor; public class MenuEntry implements Cloneable { /** - * The option text added to the menu (ie. "Walk here", "Use"). + * The option text added to the menu. (ie. "Walk here", "Use") */ private String option; /** - * The target of the action (ie. Item or Actor name). + * The target of the action. (ie. Item or Actor name) *

* If the option does not apply to any target, this field * will be set to empty string. diff --git a/runelite-api/src/main/java/net/runelite/api/MessageNode.java b/runelite-api/src/main/java/net/runelite/api/MessageNode.java index b191555d05..bd1e79ce77 100644 --- a/runelite-api/src/main/java/net/runelite/api/MessageNode.java +++ b/runelite-api/src/main/java/net/runelite/api/MessageNode.java @@ -58,7 +58,7 @@ public interface MessageNode extends Node void setName(String name); /** - * Gets the sender of the message (ie. friends chat name). + * Gets the sender of the message. (ie. friends chat name) * * @return the message sender */ diff --git a/runelite-api/src/main/java/net/runelite/api/NpcID.java b/runelite-api/src/main/java/net/runelite/api/NpcID.java index 55a7703203..f6bef67796 100644 --- a/runelite-api/src/main/java/net/runelite/api/NpcID.java +++ b/runelite-api/src/main/java/net/runelite/api/NpcID.java @@ -2657,9 +2657,8 @@ public final class NpcID public static final int DRYAD = 2828; public static final int FAIRY_2829 = 2829; public static final int MYSTERIOUS_OLD_MAN = 2830; - public static final int LIZARD_MAN = 2831; - public static final int ORC = 2832; - public static final int TROLL_2833 = 2833; + public static final int CHAIR = 2832; + public static final int LIL_CREATOR = 2833; public static final int GIANT_BAT = 2834; public static final int CAMEL = 2835; public static final int GOLEM = 2836; @@ -3340,9 +3339,9 @@ public final class NpcID public static final int VERONICA = 3561; public static final int PROFESSOR_ODDENSTEIN = 3562; public static final int ERNEST = 3563; - public static final int CHICKEN_3564 = 3564; + public static final int LIL_DESTRUCTOR = 3564; public static final int SKELETON_3565 = 3565; - public static final int WITCH_3566 = 3566; + public static final int LIL_CREATOR_3566 = 3566; public static final int PENTYN = 3568; public static final int ARISTARCHUS = 3569; public static final int BONEGUARD = 3570; @@ -4683,7 +4682,7 @@ public final class NpcID public static final int ELEMENTAL_BALANCE_5004 = 5004; public static final int WIZARD_GRAYZAG = 5006; public static final int IMP_5007 = 5007; - public static final int IMP_5008 = 5008; + public static final int LIL_DESTRUCTOR_5008 = 5008; public static final int ELEMENTAL_BALANCE_5009 = 5009; public static final int ELEMENTAL_BALANCE_5010 = 5010; public static final int ELEMENTAL_BALANCE_5011 = 5011; @@ -5718,6 +5717,7 @@ public final class NpcID public static final int THE_INADEQUACY_HARD = 6119; public static final int THE_EVERLASTING_HARD = 6120; public static final int THE_UNTOUCHABLE_HARD = 6121; + public static final int URIUM_SHADOW = 6143; public static final int SCION_6177 = 6177; public static final int JUNGLE_SPIDER_6267 = 6267; public static final int JUNGLE_SPIDER_6271 = 6271; @@ -7708,8 +7708,7 @@ public final class NpcID public static final int CAT_8594 = 8594; public static final int FELFIZ_YARYUS = 8595; public static final int KEITH = 8596; - public static final int GORDON = 8597; - public static final int MARY_8598 = 8598; + public static final int ORNATE_COMBAT_DUMMY = 8598; public static final int SHAYZIEN_SOLDIER_8599 = 8599; public static final int SHAYZIEN_SERGEANT = 8600; public static final int SHAYZIEN_ARCHER = 8601; @@ -8869,5 +8868,68 @@ public final class NpcID public static final int CAPTAIN_SHORACKS_10489 = 10489; public static final int CAPTAIN_SHORACKS_10490 = 10490; public static final int CAPTAIN_SHORACKS_10491 = 10491; + public static final int HEADLESS_BEAST_HARD = 10492; + public static final int HEADLESS_BEAST = 10493; + public static final int CHICKEN_10494 = 10494; + public static final int CHICKEN_10495 = 10495; + public static final int CHICKEN_10496 = 10496; + public static final int CHICKEN_10497 = 10497; + public static final int CHICKEN_10498 = 10498; + public static final int CHICKEN_10499 = 10499; + public static final int GORDON = 10500; + public static final int GORDON_10501 = 10501; + public static final int MARY_10502 = 10502; + public static final int MARY_10503 = 10503; + public static final int MARY_10504 = 10504; + public static final int SHAYZIEN_SERGEANT_10505 = 10505; + public static final int HEADLESS_BEAST_10506 = 10506; + public static final int ORNATE_UNDEAD_COMBAT_DUMMY = 10507; + public static final int ORNATE_WILDERNESS_COMBAT_DUMMY = 10508; + public static final int ORNATE_KALPHITE_COMBAT_DUMMY = 10509; + public static final int ORNATE_KURASK_COMBAT_DUMMY = 10510; + public static final int ORNATE_UNDEAD_COMBAT_DUMMY_10511 = 10511; + public static final int ORNATE_UNDEAD_COMBAT_DUMMY_10512 = 10512; + public static final int FISHING_SPOT_10513 = 10513; + public static final int FISHING_SPOT_10514 = 10514; + public static final int FISHING_SPOT_10515 = 10515; + public static final int NOMAD = 10516; + public static final int ZIMBERFIZZ = 10517; + public static final int ZIMBERFIZZ_10518 = 10518; + public static final int ZIMBERFIZZ_10519 = 10519; + public static final int AVATAR_OF_CREATION = 10520; + public static final int AVATAR_OF_DESTRUCTION = 10521; + public static final int WOLF_10522 = 10522; + public static final int FORGOTTEN_SOUL = 10523; + public static final int FORGOTTEN_SOUL_10524 = 10524; + public static final int FORGOTTEN_SOUL_10525 = 10525; + public static final int FORGOTTEN_SOUL_10526 = 10526; + public static final int NOMAD_10528 = 10528; + public static final int NOMAD_10529 = 10529; + public static final int ZIMBERFIZZ_10530 = 10530; + public static final int AVATAR_OF_CREATION_10531 = 10531; + public static final int AVATAR_OF_DESTRUCTION_10532 = 10532; + public static final int WOLF_10533 = 10533; + public static final int FORGOTTEN_SOUL_10534 = 10534; + public static final int FORGOTTEN_SOUL_10535 = 10535; + public static final int FORGOTTEN_SOUL_10536 = 10536; + public static final int FORGOTTEN_SOUL_10537 = 10537; + public static final int GHOST_10538 = 10538; + public static final int BARRICADE_10539 = 10539; + public static final int BARRICADE_10540 = 10540; + public static final int BIRD_10541 = 10541; + public static final int FORGOTTEN_SOUL_10544 = 10544; + public static final int FORGOTTEN_SOUL_10545 = 10545; + public static final int DUCK_10546 = 10546; + public static final int DUCK_10547 = 10547; + public static final int CHICKEN_10556 = 10556; + public static final int SCRUBFOOT = 10559; + public static final int RED_FIREFLIES = 10561; + public static final int GREEN_FIREFLIES = 10564; + public static final int GOBLIN_10566 = 10566; + public static final int GOBLIN_10567 = 10567; + public static final int URIUM_SHADE = 10589; + public static final int DAMPE = 10590; + public static final int UNDEAD_ZEALOT = 10591; + public static final int UNDEAD_ZEALOT_10592 = 10592; /* This file is automatically generated. Do not edit. */ } diff --git a/runelite-api/src/main/java/net/runelite/api/NullItemID.java b/runelite-api/src/main/java/net/runelite/api/NullItemID.java index 158ae3fb3b..a0bc89a2aa 100644 --- a/runelite-api/src/main/java/net/runelite/api/NullItemID.java +++ b/runelite-api/src/main/java/net/runelite/api/NullItemID.java @@ -2128,6 +2128,7 @@ public final class NullItemID public static final int NULL_5550 = 5550; public static final int NULL_5551 = 5551; public static final int NULL_5552 = 5552; + public static final int NULL_5572 = 5572; public static final int NULL_5611 = 5611; public static final int NULL_5612 = 5612; public static final int NULL_5613 = 5613; @@ -13325,6 +13326,7 @@ public final class NullItemID public static final int NULL_25036 = 25036; public static final int NULL_25038 = 25038; public static final int NULL_25039 = 25039; + public static final int NULL_25040 = 25040; public static final int NULL_25041 = 25041; public static final int NULL_25043 = 25043; public static final int NULL_25045 = 25045; @@ -13387,5 +13389,152 @@ public final class NullItemID public static final int NULL_25142 = 25142; public static final int NULL_25143 = 25143; public static final int NULL_25144 = 25144; + public static final int NULL_25148 = 25148; + public static final int NULL_25149 = 25149; + public static final int NULL_25150 = 25150; + public static final int NULL_25151 = 25151; + public static final int NULL_25153 = 25153; + public static final int NULL_25156 = 25156; + public static final int NULL_25158 = 25158; + public static final int NULL_25164 = 25164; + public static final int NULL_25166 = 25166; + public static final int NULL_25168 = 25168; + public static final int NULL_25170 = 25170; + public static final int NULL_25172 = 25172; + public static final int NULL_25175 = 25175; + public static final int NULL_25178 = 25178; + public static final int NULL_25180 = 25180; + public static final int NULL_25182 = 25182; + public static final int NULL_25184 = 25184; + public static final int NULL_25186 = 25186; + public static final int NULL_25188 = 25188; + public static final int NULL_25190 = 25190; + public static final int NULL_25192 = 25192; + public static final int NULL_25194 = 25194; + public static final int NULL_25198 = 25198; + public static final int NULL_25200 = 25200; + public static final int NULL_25245 = 25245; + public static final int NULL_25247 = 25247; + public static final int NULL_25249 = 25249; + public static final int NULL_25251 = 25251; + public static final int NULL_25253 = 25253; + public static final int NULL_25255 = 25255; + public static final int NULL_25257 = 25257; + public static final int NULL_25259 = 25259; + public static final int NULL_25261 = 25261; + public static final int NULL_25263 = 25263; + public static final int NULL_25265 = 25265; + public static final int NULL_25277 = 25277; + public static final int NULL_25279 = 25279; + public static final int NULL_25281 = 25281; + public static final int NULL_25291 = 25291; + public static final int NULL_25292 = 25292; + public static final int NULL_25293 = 25293; + public static final int NULL_25294 = 25294; + public static final int NULL_25295 = 25295; + public static final int NULL_25296 = 25296; + public static final int NULL_25297 = 25297; + public static final int NULL_25298 = 25298; + public static final int NULL_25299 = 25299; + public static final int NULL_25300 = 25300; + public static final int NULL_25301 = 25301; + public static final int NULL_25302 = 25302; + public static final int NULL_25303 = 25303; + public static final int NULL_25304 = 25304; + public static final int NULL_25305 = 25305; + public static final int NULL_25306 = 25306; + public static final int NULL_25307 = 25307; + public static final int NULL_25308 = 25308; + public static final int NULL_25309 = 25309; + public static final int NULL_25310 = 25310; + public static final int NULL_25311 = 25311; + public static final int NULL_25312 = 25312; + public static final int NULL_25313 = 25313; + public static final int NULL_25315 = 25315; + public static final int NULL_25317 = 25317; + public static final int NULL_25318 = 25318; + public static final int NULL_25320 = 25320; + public static final int NULL_25321 = 25321; + public static final int NULL_25323 = 25323; + public static final int NULL_25325 = 25325; + public static final int NULL_25327 = 25327; + public static final int NULL_25329 = 25329; + public static final int NULL_25331 = 25331; + public static final int NULL_25333 = 25333; + public static final int NULL_25335 = 25335; + public static final int NULL_25337 = 25337; + public static final int NULL_25339 = 25339; + public static final int NULL_25341 = 25341; + public static final int NULL_25343 = 25343; + public static final int NULL_25345 = 25345; + public static final int NULL_25347 = 25347; + public static final int NULL_25349 = 25349; + public static final int NULL_25368 = 25368; + public static final int NULL_25370 = 25370; + public static final int NULL_25372 = 25372; + public static final int NULL_25374 = 25374; + public static final int NULL_25375 = 25375; + public static final int NULL_25377 = 25377; + public static final int NULL_25379 = 25379; + public static final int NULL_25381 = 25381; + public static final int NULL_25382 = 25382; + public static final int NULL_25384 = 25384; + public static final int NULL_25385 = 25385; + public static final int NULL_25387 = 25387; + public static final int NULL_25388 = 25388; + public static final int NULL_25390 = 25390; + public static final int NULL_25391 = 25391; + public static final int NULL_25393 = 25393; + public static final int NULL_25394 = 25394; + public static final int NULL_25396 = 25396; + public static final int NULL_25397 = 25397; + public static final int NULL_25399 = 25399; + public static final int NULL_25400 = 25400; + public static final int NULL_25402 = 25402; + public static final int NULL_25403 = 25403; + public static final int NULL_25405 = 25405; + public static final int NULL_25406 = 25406; + public static final int NULL_25408 = 25408; + public static final int NULL_25409 = 25409; + public static final int NULL_25411 = 25411; + public static final int NULL_25412 = 25412; + public static final int NULL_25414 = 25414; + public static final int NULL_25415 = 25415; + public static final int NULL_25417 = 25417; + public static final int NULL_25418 = 25418; + public static final int NULL_25420 = 25420; + public static final int NULL_25421 = 25421; + public static final int NULL_25423 = 25423; + public static final int NULL_25425 = 25425; + public static final int NULL_25427 = 25427; + public static final int NULL_25429 = 25429; + public static final int NULL_25431 = 25431; + public static final int NULL_25433 = 25433; + public static final int NULL_25435 = 25435; + public static final int NULL_25437 = 25437; + public static final int NULL_25439 = 25439; + public static final int NULL_25441 = 25441; + public static final int NULL_25443 = 25443; + public static final int NULL_25444 = 25444; + public static final int NULL_25446 = 25446; + public static final int NULL_25447 = 25447; + public static final int NULL_25449 = 25449; + public static final int NULL_25450 = 25450; + public static final int NULL_25452 = 25452; + public static final int NULL_25453 = 25453; + public static final int NULL_25455 = 25455; + public static final int NULL_25456 = 25456; + public static final int NULL_25458 = 25458; + public static final int NULL_25460 = 25460; + public static final int NULL_25462 = 25462; + public static final int NULL_25464 = 25464; + public static final int NULL_25466 = 25466; + public static final int NULL_25468 = 25468; + public static final int NULL_25475 = 25475; + public static final int NULL_25477 = 25477; + public static final int NULL_25479 = 25479; + public static final int NULL_25480 = 25480; + public static final int NULL_25482 = 25482; + public static final int NULL_25483 = 25483; /* This file is automatically generated. Do not edit. */ } diff --git a/runelite-api/src/main/java/net/runelite/api/NullNpcID.java b/runelite-api/src/main/java/net/runelite/api/NullNpcID.java index 44075d54de..c0acd7f40c 100644 --- a/runelite-api/src/main/java/net/runelite/api/NullNpcID.java +++ b/runelite-api/src/main/java/net/runelite/api/NullNpcID.java @@ -173,6 +173,7 @@ public final class NullNpcID public static final int NULL_2779 = 2779; public static final int NULL_2780 = 2780; public static final int NULL_2781 = 2781; + public static final int NULL_2831 = 2831; public static final int NULL_2934 = 2934; public static final int NULL_2935 = 2935; public static final int NULL_2936 = 2936; @@ -421,7 +422,6 @@ public final class NullNpcID public static final int NULL_6140 = 6140; public static final int NULL_6141 = 6141; public static final int NULL_6142 = 6142; - public static final int NULL_6143 = 6143; public static final int NULL_6144 = 6144; public static final int NULL_6145 = 6145; public static final int NULL_6146 = 6146; @@ -873,6 +873,7 @@ public final class NullNpcID public static final int NULL_8489 = 8489; public static final int NULL_8490 = 8490; public static final int NULL_8516 = 8516; + public static final int NULL_8597 = 8597; public static final int NULL_8624 = 8624; public static final int NULL_8625 = 8625; public static final int NULL_8626 = 8626; @@ -1606,5 +1607,16 @@ public final class NullNpcID public static final int NULL_10441 = 10441; public static final int NULL_10474 = 10474; public static final int NULL_10475 = 10475; + public static final int NULL_10527 = 10527; + public static final int NULL_10542 = 10542; + public static final int NULL_10543 = 10543; + public static final int NULL_10548 = 10548; + public static final int NULL_10549 = 10549; + public static final int NULL_10550 = 10550; + public static final int NULL_10551 = 10551; + public static final int NULL_10552 = 10552; + public static final int NULL_10553 = 10553; + public static final int NULL_10554 = 10554; + public static final int NULL_10555 = 10555; /* This file is automatically generated. Do not edit. */ } diff --git a/runelite-api/src/main/java/net/runelite/api/NullObjectID.java b/runelite-api/src/main/java/net/runelite/api/NullObjectID.java index f3c11e2598..91bb2fdc18 100644 --- a/runelite-api/src/main/java/net/runelite/api/NullObjectID.java +++ b/runelite-api/src/main/java/net/runelite/api/NullObjectID.java @@ -879,7 +879,6 @@ public final class NullObjectID public static final int NULL_1793 = 1793; public static final int NULL_1794 = 1794; public static final int NULL_1795 = 1795; - public static final int NULL_1796 = 1796; public static final int NULL_1798 = 1798; public static final int NULL_1799 = 1799; public static final int NULL_1800 = 1800; @@ -9386,6 +9385,7 @@ public final class NullObjectID public static final int NULL_20842 = 20842; public static final int NULL_20846 = 20846; public static final int NULL_20857 = 20857; + public static final int NULL_20858 = 20858; public static final int NULL_20859 = 20859; public static final int NULL_20860 = 20860; public static final int NULL_20861 = 20861; @@ -19725,9 +19725,307 @@ public final class NullObjectID public static final int NULL_40352 = 40352; public static final int NULL_40353 = 40353; public static final int NULL_40354 = 40354; + public static final int NULL_40368 = 40368; + public static final int NULL_40369 = 40369; + public static final int NULL_40370 = 40370; + public static final int NULL_40371 = 40371; + public static final int NULL_40372 = 40372; + public static final int NULL_40373 = 40373; + public static final int NULL_40374 = 40374; + public static final int NULL_40375 = 40375; + public static final int NULL_40376 = 40376; + public static final int NULL_40377 = 40377; + public static final int NULL_40378 = 40378; + public static final int NULL_40379 = 40379; + public static final int NULL_40380 = 40380; public static final int NULL_40392 = 40392; public static final int NULL_40393 = 40393; public static final int NULL_40394 = 40394; public static final int NULL_40395 = 40395; + public static final int NULL_40427 = 40427; + public static final int NULL_40428 = 40428; + public static final int NULL_40429 = 40429; + public static final int NULL_40470 = 40470; + public static final int NULL_40477 = 40477; + public static final int NULL_40478 = 40478; + public static final int NULL_40479 = 40479; + public static final int NULL_40480 = 40480; + public static final int NULL_40481 = 40481; + public static final int NULL_40482 = 40482; + public static final int NULL_40483 = 40483; + public static final int NULL_40484 = 40484; + public static final int NULL_40485 = 40485; + public static final int NULL_40486 = 40486; + public static final int NULL_40487 = 40487; + public static final int NULL_40488 = 40488; + public static final int NULL_40489 = 40489; + public static final int NULL_40490 = 40490; + public static final int NULL_40500 = 40500; + public static final int NULL_40501 = 40501; + public static final int NULL_40502 = 40502; + public static final int NULL_40503 = 40503; + public static final int NULL_40504 = 40504; + public static final int NULL_40505 = 40505; + public static final int NULL_40506 = 40506; + public static final int NULL_40507 = 40507; + public static final int NULL_40508 = 40508; + public static final int NULL_40509 = 40509; + public static final int NULL_40510 = 40510; + public static final int NULL_40511 = 40511; + public static final int NULL_40512 = 40512; + public static final int NULL_40513 = 40513; + public static final int NULL_40514 = 40514; + public static final int NULL_40515 = 40515; + public static final int NULL_40516 = 40516; + public static final int NULL_40517 = 40517; + public static final int NULL_40518 = 40518; + public static final int NULL_40519 = 40519; + public static final int NULL_40520 = 40520; + public static final int NULL_40521 = 40521; + public static final int NULL_40522 = 40522; + public static final int NULL_40523 = 40523; + public static final int NULL_40524 = 40524; + public static final int NULL_40525 = 40525; + public static final int NULL_40526 = 40526; + public static final int NULL_40527 = 40527; + public static final int NULL_40528 = 40528; + public static final int NULL_40529 = 40529; + public static final int NULL_40530 = 40530; + public static final int NULL_40531 = 40531; + public static final int NULL_40532 = 40532; + public static final int NULL_40533 = 40533; + public static final int NULL_40534 = 40534; + public static final int NULL_40535 = 40535; + public static final int NULL_40536 = 40536; + public static final int NULL_40537 = 40537; + public static final int NULL_40538 = 40538; + public static final int NULL_40539 = 40539; + public static final int NULL_40540 = 40540; + public static final int NULL_40541 = 40541; + public static final int NULL_40542 = 40542; + public static final int NULL_40543 = 40543; + public static final int NULL_40552 = 40552; + public static final int NULL_40553 = 40553; + public static final int NULL_40554 = 40554; + public static final int NULL_40555 = 40555; + public static final int NULL_40556 = 40556; + public static final int NULL_40557 = 40557; + public static final int NULL_40558 = 40558; + public static final int NULL_40559 = 40559; + public static final int NULL_40560 = 40560; + public static final int NULL_40561 = 40561; + public static final int NULL_40562 = 40562; + public static final int NULL_40563 = 40563; + public static final int NULL_40564 = 40564; + public static final int NULL_40565 = 40565; + public static final int NULL_40566 = 40566; + public static final int NULL_40567 = 40567; + public static final int NULL_40568 = 40568; + public static final int NULL_40569 = 40569; + public static final int NULL_40570 = 40570; + public static final int NULL_40571 = 40571; + public static final int NULL_40572 = 40572; + public static final int NULL_40573 = 40573; + public static final int NULL_40574 = 40574; + public static final int NULL_40575 = 40575; + public static final int NULL_40576 = 40576; + public static final int NULL_40577 = 40577; + public static final int NULL_40578 = 40578; + public static final int NULL_40579 = 40579; + public static final int NULL_40580 = 40580; + public static final int NULL_40581 = 40581; + public static final int NULL_40582 = 40582; + public static final int NULL_40583 = 40583; + public static final int NULL_40584 = 40584; + public static final int NULL_40585 = 40585; + public static final int NULL_40586 = 40586; + public static final int NULL_40587 = 40587; + public static final int NULL_40591 = 40591; + public static final int NULL_40592 = 40592; + public static final int NULL_40593 = 40593; + public static final int NULL_40594 = 40594; + public static final int NULL_40595 = 40595; + public static final int NULL_40596 = 40596; + public static final int NULL_40597 = 40597; + public static final int NULL_40598 = 40598; + public static final int NULL_40599 = 40599; + public static final int NULL_40600 = 40600; + public static final int NULL_40601 = 40601; + public static final int NULL_40602 = 40602; + public static final int NULL_40603 = 40603; + public static final int NULL_40604 = 40604; + public static final int NULL_40605 = 40605; + public static final int NULL_40606 = 40606; + public static final int NULL_40607 = 40607; + public static final int NULL_40608 = 40608; + public static final int NULL_40609 = 40609; + public static final int NULL_40610 = 40610; + public static final int NULL_40611 = 40611; + public static final int NULL_40612 = 40612; + public static final int NULL_40613 = 40613; + public static final int NULL_40614 = 40614; + public static final int NULL_40615 = 40615; + public static final int NULL_40616 = 40616; + public static final int NULL_40617 = 40617; + public static final int NULL_40618 = 40618; + public static final int NULL_40619 = 40619; + public static final int NULL_40620 = 40620; + public static final int NULL_40621 = 40621; + public static final int NULL_40622 = 40622; + public static final int NULL_40623 = 40623; + public static final int NULL_40624 = 40624; + public static final int NULL_40625 = 40625; + public static final int NULL_40626 = 40626; + public static final int NULL_40627 = 40627; + public static final int NULL_40628 = 40628; + public static final int NULL_40629 = 40629; + public static final int NULL_40630 = 40630; + public static final int NULL_40631 = 40631; + public static final int NULL_40632 = 40632; + public static final int NULL_40633 = 40633; + public static final int NULL_40634 = 40634; + public static final int NULL_40635 = 40635; + public static final int NULL_40636 = 40636; + public static final int NULL_40637 = 40637; + public static final int NULL_40638 = 40638; + public static final int NULL_40639 = 40639; + public static final int NULL_40640 = 40640; + public static final int NULL_40641 = 40641; + public static final int NULL_40642 = 40642; + public static final int NULL_40643 = 40643; + public static final int NULL_40644 = 40644; + public static final int NULL_40645 = 40645; + public static final int NULL_40646 = 40646; + public static final int NULL_40647 = 40647; + public static final int NULL_40648 = 40648; + public static final int NULL_40649 = 40649; + public static final int NULL_40650 = 40650; + public static final int NULL_40651 = 40651; + public static final int NULL_40652 = 40652; + public static final int NULL_40653 = 40653; + public static final int NULL_40654 = 40654; + public static final int NULL_40655 = 40655; + public static final int NULL_40656 = 40656; + public static final int NULL_40657 = 40657; + public static final int NULL_40658 = 40658; + public static final int NULL_40659 = 40659; + public static final int NULL_40660 = 40660; + public static final int NULL_40661 = 40661; + public static final int NULL_40662 = 40662; + public static final int NULL_40663 = 40663; + public static final int NULL_40664 = 40664; + public static final int NULL_40665 = 40665; + public static final int NULL_40666 = 40666; + public static final int NULL_40667 = 40667; + public static final int NULL_40668 = 40668; + public static final int NULL_40669 = 40669; + public static final int NULL_40670 = 40670; + public static final int NULL_40671 = 40671; + public static final int NULL_40672 = 40672; + public static final int NULL_40673 = 40673; + public static final int NULL_40674 = 40674; + public static final int NULL_40675 = 40675; + public static final int NULL_40676 = 40676; + public static final int NULL_40677 = 40677; + public static final int NULL_40678 = 40678; + public static final int NULL_40679 = 40679; + public static final int NULL_40680 = 40680; + public static final int NULL_40681 = 40681; + public static final int NULL_40682 = 40682; + public static final int NULL_40683 = 40683; + public static final int NULL_40684 = 40684; + public static final int NULL_40685 = 40685; + public static final int NULL_40686 = 40686; + public static final int NULL_40687 = 40687; + public static final int NULL_40688 = 40688; + public static final int NULL_40689 = 40689; + public static final int NULL_40690 = 40690; + public static final int NULL_40691 = 40691; + public static final int NULL_40692 = 40692; + public static final int NULL_40693 = 40693; + public static final int NULL_40694 = 40694; + public static final int NULL_40695 = 40695; + public static final int NULL_40696 = 40696; + public static final int NULL_40697 = 40697; + public static final int NULL_40698 = 40698; + public static final int NULL_40699 = 40699; + public static final int NULL_40700 = 40700; + public static final int NULL_40701 = 40701; + public static final int NULL_40702 = 40702; + public static final int NULL_40703 = 40703; + public static final int NULL_40704 = 40704; + public static final int NULL_40705 = 40705; + public static final int NULL_40706 = 40706; + public static final int NULL_40707 = 40707; + public static final int NULL_40708 = 40708; + public static final int NULL_40709 = 40709; + public static final int NULL_40710 = 40710; + public static final int NULL_40711 = 40711; + public static final int NULL_40712 = 40712; + public static final int NULL_40713 = 40713; + public static final int NULL_40714 = 40714; + public static final int NULL_40717 = 40717; + public static final int NULL_40718 = 40718; + public static final int NULL_40719 = 40719; + public static final int NULL_40720 = 40720; + public static final int NULL_40721 = 40721; + public static final int NULL_40722 = 40722; + public static final int NULL_40724 = 40724; + public static final int NULL_40726 = 40726; + public static final int NULL_40727 = 40727; + public static final int NULL_40729 = 40729; + public static final int NULL_40730 = 40730; + public static final int NULL_40740 = 40740; + public static final int NULL_40743 = 40743; + public static final int NULL_40747 = 40747; + public static final int NULL_40748 = 40748; + public static final int NULL_40749 = 40749; + public static final int NULL_40762 = 40762; + public static final int NULL_40763 = 40763; + public static final int NULL_40764 = 40764; + public static final int NULL_40765 = 40765; + public static final int NULL_40766 = 40766; + public static final int NULL_40767 = 40767; + public static final int NULL_40779 = 40779; + public static final int NULL_40862 = 40862; + public static final int NULL_40863 = 40863; + public static final int NULL_40864 = 40864; + public static final int NULL_40865 = 40865; + public static final int NULL_40866 = 40866; + public static final int NULL_40867 = 40867; + public static final int NULL_40868 = 40868; + public static final int NULL_40869 = 40869; + public static final int NULL_40870 = 40870; + public static final int NULL_40890 = 40890; + public static final int NULL_40895 = 40895; + public static final int NULL_40898 = 40898; + public static final int NULL_40907 = 40907; + public static final int NULL_40908 = 40908; + public static final int NULL_40925 = 40925; + public static final int NULL_40926 = 40926; + public static final int NULL_40927 = 40927; + public static final int NULL_40928 = 40928; + public static final int NULL_40934 = 40934; + public static final int NULL_40935 = 40935; + public static final int NULL_40936 = 40936; + public static final int NULL_41022 = 41022; + public static final int NULL_41191 = 41191; + public static final int NULL_41192 = 41192; + public static final int NULL_41193 = 41193; + public static final int NULL_41194 = 41194; + public static final int NULL_41195 = 41195; + public static final int NULL_41196 = 41196; + public static final int NULL_41197 = 41197; + public static final int NULL_41198 = 41198; + public static final int NULL_41201 = 41201; + public static final int NULL_41202 = 41202; + public static final int NULL_41203 = 41203; + public static final int NULL_41204 = 41204; + public static final int NULL_41205 = 41205; + public static final int NULL_41206 = 41206; + public static final int NULL_41207 = 41207; + public static final int NULL_41208 = 41208; + public static final int NULL_41209 = 41209; + public static final int NULL_41211 = 41211; /* This file is automatically generated. Do not edit. */ } diff --git a/runelite-api/src/main/java/net/runelite/api/ObjectID.java b/runelite-api/src/main/java/net/runelite/api/ObjectID.java index b632893cdc..8bf9ca4de0 100644 --- a/runelite-api/src/main/java/net/runelite/api/ObjectID.java +++ b/runelite-api/src/main/java/net/runelite/api/ObjectID.java @@ -928,8 +928,7 @@ public final class ObjectID public static final int DOOR_1805 = 1805; public static final int WEB_1810 = 1810; public static final int SLICED_WEB = 1811; - public static final int PORTAL = 1812; - public static final int STONE_STAND = 1813; + public static final int BANDAGE_TABLE = 1813; public static final int LEVER_1814 = 1814; public static final int LEVER_1816 = 1816; public static final int LEVER_1817 = 1817; @@ -2233,7 +2232,7 @@ public final class ObjectID public static final int SHELF_4062 = 4062; public static final int SINK_4063 = 4063; public static final int SMASHED_TABLE_4064 = 4064; - public static final int STONE_STAND_4065 = 4065; + public static final int STONE_STAND = 4065; public static final int SIGNPOST_4066 = 4066; public static final int WARNING_SIGN = 4067; public static final int BROKEN_WALL = 4068; @@ -2312,7 +2311,7 @@ public final class ObjectID public static final int CAVE_ENTRANCE_4147 = 4147; public static final int DOOR_4148 = 4148; public static final int LALLIS_STEW = 4149; - public static final int PORTAL_4150 = 4150; + public static final int PORTAL = 4150; public static final int PORTAL_4151 = 4151; public static final int PORTAL_4152 = 4152; public static final int PORTAL_4153 = 4153; @@ -6988,11 +6987,19 @@ public final class ObjectID public static final int LADDER_12389 = 12389; public static final int LADDER_12390 = 12390; public static final int LADDER_12391 = 12391; + public static final int SACKS_12392 = 12392; + public static final int SACKS_12393 = 12393; + public static final int SACK_PILE = 12394; + public static final int SACK_PILE_12395 = 12395; public static final int SACK_12396 = 12396; public static final int SACK_12399 = 12399; public static final int CAULDRON_12400 = 12400; public static final int CAULDRON_12401 = 12401; public static final int EXPLOSION = 12402; + public static final int SHELVES_12403 = 12403; + public static final int SHELVES_12404 = 12404; + public static final int CUPBOARD_12405 = 12405; + public static final int CUPBOARD_12406 = 12406; public static final int STOOL_12407 = 12407; public static final int STOOL_12408 = 12408; public static final int STOOL_12409 = 12409; @@ -9024,7 +9031,7 @@ public final class ObjectID public static final int LARGE_DOOR_15758 = 15758; public static final int DOOR_15759 = 15759; public static final int SACK_15760 = 15760; - public static final int SACK_PILE = 15761; + public static final int SACK_PILE_15761 = 15761; public static final int SACKS_15762 = 15762; public static final int BED_15767 = 15767; public static final int CRATE_15768 = 15768; @@ -18575,7 +18582,7 @@ public final class ObjectID public static final int RUBBLE_34803 = 34803; public static final int RUBBLE_34804 = 34804; public static final int RUBBLE_34805 = 34805; - public static final int JADFEST_PORTAL = 34826; + public static final int HANDY_PORTAL = 34826; public static final int LARRANS_SMALL_CHEST_34828 = 34828; public static final int LARRANS_BIG_CHEST = 34829; public static final int LARRANS_BIG_CHEST_34830 = 34830; @@ -19612,7 +19619,7 @@ public final class ObjectID public static final int GATE_37954 = 37954; public static final int LADDER_37955 = 37955; public static final int LADDER_37956 = 37956; - public static final int HANDY_PORTAL = 37957; + public static final int HANDY_PORTAL_37957 = 37957; public static final int BANK_BOOTH_37959 = 37959; public static final int DOOR_37961 = 37961; public static final int DOOR_37963 = 37963; @@ -20674,7 +20681,7 @@ public final class ObjectID public static final int NEUTRAL_BARRIER = 40439; public static final int PORTAL_40440 = 40440; public static final int PORTAL_40441 = 40441; - public static final int BANDAGE_TABLE = 40442; + public static final int BANDAGE_TABLE_40442 = 40442; public static final int BARRICADE_TABLE = 40443; public static final int BARRICADE_TABLE_40444 = 40444; public static final int EXPLOSIVE_POTION_TABLE = 40445; @@ -20702,9 +20709,8 @@ public final class ObjectID public static final int EXPLOSIVE_POTION_TABLE_40467 = 40467; public static final int POTION_OF_POWER_TABLE_40468 = 40468; public static final int POTION_OF_POWER_TABLE_40469 = 40469; - public static final int BLUE_BARRIER_40470 = 40470; - public static final int RED_BARRIER_40471 = 40471; - public static final int BALANCE_PORTAL = 40472; + public static final int GRAVESTONE_40471 = 40471; + public static final int COFFIN_40472 = 40472; public static final int BANK_CHEST_40473 = 40473; public static final int SOUL_WARS_PORTAL = 40474; public static final int SOUL_WARS_PORTAL_40475 = 40475; @@ -20746,6 +20752,8 @@ public final class ObjectID public static final int CHEST_40741 = 40741; public static final int LOCKED_CHEST_40742 = 40742; public static final int BARREL_40744 = 40744; + public static final int LADDER_40745 = 40745; + public static final int LADDER_40746 = 40746; public static final int TREE_40750 = 40750; public static final int TREE_STUMP_40751 = 40751; public static final int TREE_40752 = 40752; @@ -20851,22 +20859,22 @@ public final class ObjectID public static final int DOOR_40859 = 40859; public static final int DOOR_40860 = 40860; public static final int DOOR_40861 = 40861; - public static final int SACKS_40871 = 40871; - public static final int SACKS_40872 = 40872; - public static final int SACKS_40873 = 40873; - public static final int SACKS_40874 = 40874; - public static final int SACK_PILE_40875 = 40875; - public static final int SACK_PILE_40876 = 40876; - public static final int SACK_PILE_40877 = 40877; - public static final int SACK_PILE_40878 = 40878; - public static final int SHELVES_40879 = 40879; - public static final int SHELVES_40880 = 40880; - public static final int SHELVES_40881 = 40881; - public static final int SHELVES_40882 = 40882; - public static final int CUPBOARD_40883 = 40883; - public static final int CUPBOARD_40884 = 40884; - public static final int CUPBOARD_40885 = 40885; - public static final int CUPBOARD_40886 = 40886; + public static final int ICON_OF_GNOME_CHILD = 40871; + public static final int ALTAR_40872 = 40872; + public static final int ALTAR_40873 = 40873; + public static final int ALTAR_40874 = 40874; + public static final int ALTAR_40875 = 40875; + public static final int ALTAR_40876 = 40876; + public static final int ALTAR_40877 = 40877; + public static final int ALTAR_40878 = 40878; + public static final int DECORATIVE_WINDOW_40879 = 40879; + public static final int STAINEDGLASS_WINDOW_40880 = 40880; + public static final int DECORATIVE_WINDOW_40881 = 40881; + public static final int STAINEDGLASS_WINDOW_40882 = 40882; + public static final int DECORATIVE_WINDOW_40883 = 40883; + public static final int STAINEDGLASS_WINDOW_40884 = 40884; + public static final int DECORATIVE_WINDOW_40885 = 40885; + public static final int STAINEDGLASS_WINDOW_40886 = 40886; public static final int CAVE_ENTRANCE_40887 = 40887; public static final int CAVE_EXIT_40888 = 40888; public static final int CREVICE_40889 = 40889; @@ -20876,19 +20884,206 @@ public final class ObjectID public static final int SLOPE_END = 40894; public static final int PEBBLES = 40896; public static final int BOULDER_40897 = 40897; - public static final int BOULDER_40899 = 40899; - public static final int STICK_40901 = 40901; - public static final int STICK_40902 = 40902; - public static final int CAULDRON_40903 = 40903; - public static final int TREASURE_CHEST_40904 = 40904; + public static final int DECORATIVE_WINDOW_40899 = 40899; + public static final int STAINEDGLASS_WINDOW_40900 = 40900; + public static final int DECORATIVE_WINDOW_40901 = 40901; + public static final int STAINEDGLASS_WINDOW_40902 = 40902; + public static final int DECORATIVE_WINDOW_40903 = 40903; + public static final int STAINEDGLASS_WINDOW_40904 = 40904; public static final int ROCKS_40905 = 40905; public static final int ROCKS_40906 = 40906; - public static final int SOCKING = 40909; - public static final int SOCKING_40910 = 40910; - public static final int SOCKING_40911 = 40911; + public static final int DECORATIVE_WINDOW_40909 = 40909; + public static final int STAINEDGLASS_WINDOW_40910 = 40910; + public static final int DECORATIVE_WINDOW_40911 = 40911; + public static final int STAINEDGLASS_WINDOW_40912 = 40912; + public static final int DECORATIVE_WINDOW_40913 = 40913; + public static final int STAINEDGLASS_WINDOW_40914 = 40914; + public static final int STATUE_40915 = 40915; + public static final int STATUE_40916 = 40916; + public static final int STATUE_40917 = 40917; public static final int EVERGREEN_40932 = 40932; public static final int EVERGREEN_40933 = 40933; - public static final int TREE_40937 = 40937; - public static final int TREE_40938 = 40938; + public static final int POTION_OF_POWER_TABLE_41023 = 41023; + public static final int PEDESTAL_SPACE = 41024; + public static final int PEDESTAL_SPACE_41025 = 41025; + public static final int PEDESTAL_SPACE_41026 = 41026; + public static final int TROPHY_CASE_SPACE = 41027; + public static final int BANNER_STAND_SPACE = 41028; + public static final int OUTFIT_STAND_SPACE = 41029; + public static final int STATUE_SPACE_41030 = 41030; + public static final int RUG_SPACE_41031 = 41031; + public static final int RUG_SPACE_41032 = 41032; + public static final int RUG_SPACE_41033 = 41033; + public static final int ACCOMPLISHMENT_SCROLL_SPACE = 41034; + public static final int TROPHY_PEDESTAL = 41035; + public static final int TROPHY_PEDESTAL_41036 = 41036; + public static final int TROPHY_PEDESTAL_41037 = 41037; + public static final int TROPHY_PEDESTAL_41038 = 41038; + public static final int TROPHY_PEDESTAL_41039 = 41039; + public static final int TROPHY_PEDESTAL_41040 = 41040; + public static final int TROPHY_PEDESTAL_41041 = 41041; + public static final int TROPHY_PEDESTAL_41042 = 41042; + public static final int TROPHY_PEDESTAL_41043 = 41043; + public static final int TROPHY_PEDESTAL_41044 = 41044; + public static final int TROPHY_PEDESTAL_41045 = 41045; + public static final int TROPHY_PEDESTAL_41046 = 41046; + public static final int TROPHY_PEDESTAL_41047 = 41047; + public static final int TROPHY_PEDESTAL_41048 = 41048; + public static final int TROPHY_PEDESTAL_41049 = 41049; + public static final int ORNATE_TROPHY_PEDESTAL = 41050; + public static final int ORNATE_TROPHY_PEDESTAL_41051 = 41051; + public static final int ORNATE_TROPHY_PEDESTAL_41052 = 41052; + public static final int ORNATE_TROPHY_PEDESTAL_41053 = 41053; + public static final int ORNATE_TROPHY_PEDESTAL_41054 = 41054; + public static final int ORNATE_TROPHY_PEDESTAL_41055 = 41055; + public static final int ORNATE_TROPHY_PEDESTAL_41056 = 41056; + public static final int ORNATE_TROPHY_PEDESTAL_41057 = 41057; + public static final int ORNATE_TROPHY_PEDESTAL_41058 = 41058; + public static final int ORNATE_TROPHY_PEDESTAL_41059 = 41059; + public static final int ORNATE_TROPHY_PEDESTAL_41060 = 41060; + public static final int ORNATE_TROPHY_PEDESTAL_41061 = 41061; + public static final int ORNATE_TROPHY_PEDESTAL_41062 = 41062; + public static final int ORNATE_TROPHY_PEDESTAL_41063 = 41063; + public static final int ORNATE_TROPHY_PEDESTAL_41064 = 41064; + public static final int TROPHY_PEDESTAL_41065 = 41065; + public static final int TROPHY_PEDESTAL_41066 = 41066; + public static final int TROPHY_PEDESTAL_41067 = 41067; + public static final int TROPHY_PEDESTAL_41068 = 41068; + public static final int TROPHY_PEDESTAL_41069 = 41069; + public static final int TROPHY_PEDESTAL_41070 = 41070; + public static final int TROPHY_PEDESTAL_41071 = 41071; + public static final int TROPHY_PEDESTAL_41072 = 41072; + public static final int TROPHY_PEDESTAL_41073 = 41073; + public static final int TROPHY_PEDESTAL_41074 = 41074; + public static final int TROPHY_PEDESTAL_41075 = 41075; + public static final int TROPHY_PEDESTAL_41076 = 41076; + public static final int TROPHY_PEDESTAL_41077 = 41077; + public static final int TROPHY_PEDESTAL_41078 = 41078; + public static final int TROPHY_PEDESTAL_41079 = 41079; + public static final int ORNATE_TROPHY_PEDESTAL_41080 = 41080; + public static final int ORNATE_TROPHY_PEDESTAL_41081 = 41081; + public static final int ORNATE_TROPHY_PEDESTAL_41082 = 41082; + public static final int ORNATE_TROPHY_PEDESTAL_41083 = 41083; + public static final int ORNATE_TROPHY_PEDESTAL_41084 = 41084; + public static final int ORNATE_TROPHY_PEDESTAL_41085 = 41085; + public static final int ORNATE_TROPHY_PEDESTAL_41086 = 41086; + public static final int ORNATE_TROPHY_PEDESTAL_41087 = 41087; + public static final int ORNATE_TROPHY_PEDESTAL_41088 = 41088; + public static final int ORNATE_TROPHY_PEDESTAL_41089 = 41089; + public static final int ORNATE_TROPHY_PEDESTAL_41090 = 41090; + public static final int ORNATE_TROPHY_PEDESTAL_41091 = 41091; + public static final int ORNATE_TROPHY_PEDESTAL_41092 = 41092; + public static final int ORNATE_TROPHY_PEDESTAL_41093 = 41093; + public static final int ORNATE_TROPHY_PEDESTAL_41094 = 41094; + public static final int TROPHY_PEDESTAL_41095 = 41095; + public static final int TROPHY_PEDESTAL_41096 = 41096; + public static final int TROPHY_PEDESTAL_41097 = 41097; + public static final int TROPHY_PEDESTAL_41098 = 41098; + public static final int TROPHY_PEDESTAL_41099 = 41099; + public static final int TROPHY_PEDESTAL_41100 = 41100; + public static final int TROPHY_PEDESTAL_41101 = 41101; + public static final int TROPHY_PEDESTAL_41102 = 41102; + public static final int TROPHY_PEDESTAL_41103 = 41103; + public static final int TROPHY_PEDESTAL_41104 = 41104; + public static final int TROPHY_PEDESTAL_41105 = 41105; + public static final int TROPHY_PEDESTAL_41106 = 41106; + public static final int TROPHY_PEDESTAL_41107 = 41107; + public static final int TROPHY_PEDESTAL_41108 = 41108; + public static final int TROPHY_PEDESTAL_41109 = 41109; + public static final int ORNATE_TROPHY_PEDESTAL_41110 = 41110; + public static final int ORNATE_TROPHY_PEDESTAL_41111 = 41111; + public static final int ORNATE_TROPHY_PEDESTAL_41112 = 41112; + public static final int ORNATE_TROPHY_PEDESTAL_41113 = 41113; + public static final int ORNATE_TROPHY_PEDESTAL_41114 = 41114; + public static final int ORNATE_TROPHY_PEDESTAL_41115 = 41115; + public static final int ORNATE_TROPHY_PEDESTAL_41116 = 41116; + public static final int ORNATE_TROPHY_PEDESTAL_41117 = 41117; + public static final int ORNATE_TROPHY_PEDESTAL_41118 = 41118; + public static final int ORNATE_TROPHY_PEDESTAL_41119 = 41119; + public static final int ORNATE_TROPHY_PEDESTAL_41120 = 41120; + public static final int ORNATE_TROPHY_PEDESTAL_41121 = 41121; + public static final int ORNATE_TROPHY_PEDESTAL_41122 = 41122; + public static final int ORNATE_TROPHY_PEDESTAL_41123 = 41123; + public static final int ORNATE_TROPHY_PEDESTAL_41124 = 41124; + public static final int RUG_41125 = 41125; + public static final int OPULENT_RUG = 41126; + public static final int RUG_41127 = 41127; + public static final int OPULENT_RUG_41128 = 41128; + public static final int RUG_41129 = 41129; + public static final int OPULENT_RUG_41130 = 41130; + public static final int TRAILBLAZER_RUG = 41131; + public static final int TRAILBLAZER_RUG_41132 = 41132; + public static final int TRAILBLAZER_RUG_41133 = 41133; + public static final int TRAILBLAZER_RUG_41134 = 41134; + public static final int TRAILBLAZER_RUG_41135 = 41135; + public static final int TRAILBLAZER_RUG_41136 = 41136; + public static final int TRAILBLAZER_RUG_41137 = 41137; + public static final int TRAILBLAZER_RUG_41138 = 41138; + public static final int TRAILBLAZER_RUG_41139 = 41139; + public static final int TRAILBLAZER_RUG_41140 = 41140; + public static final int TRAILBLAZER_RUG_41141 = 41141; + public static final int TRAILBLAZER_RUG_41142 = 41142; + public static final int TRAILBLAZER_RUG_41143 = 41143; + public static final int TRAILBLAZER_RUG_41144 = 41144; + public static final int TRAILBLAZER_RUG_41145 = 41145; + public static final int TRAILBLAZER_RUG_41146 = 41146; + public static final int TRAILBLAZER_RUG_41147 = 41147; + public static final int TRAILBLAZER_RUG_41148 = 41148; + public static final int TRAILBLAZER_RUG_41149 = 41149; + public static final int TRAILBLAZER_RUG_41150 = 41150; + public static final int TRAILBLAZER_RUG_41151 = 41151; + public static final int TRAILBLAZER_RUG_41152 = 41152; + public static final int TRAILBLAZER_RUG_41153 = 41153; + public static final int TRAILBLAZER_RUG_41154 = 41154; + public static final int OAK_TROPHY_CASE = 41155; + public static final int OAK_TROPHY_CASE_41156 = 41156; + public static final int MAHOGANY_TROPHY_CASE = 41157; + public static final int MAHOGANY_TROPHY_CASE_41158 = 41158; + public static final int BANNER_STAND = 41159; + public static final int BANNER_STAND_41160 = 41160; + public static final int BANNER_STAND_41161 = 41161; + public static final int ORNATE_BANNER_STAND = 41162; + public static final int ORNATE_BANNER_STAND_41163 = 41163; + public static final int ORNATE_BANNER_STAND_41164 = 41164; + public static final int OAK_OUTFIT_STAND = 41165; + public static final int OAK_OUTFIT_STAND_41166 = 41166; + public static final int OAK_OUTFIT_STAND_41167 = 41167; + public static final int OAK_OUTFIT_STAND_41168 = 41168; + public static final int OAK_OUTFIT_STAND_41169 = 41169; + public static final int OAK_OUTFIT_STAND_41170 = 41170; + public static final int OAK_OUTFIT_STAND_41171 = 41171; + public static final int MAHOGANY_OUTFIT_STAND = 41172; + public static final int MAHOGANY_OUTFIT_STAND_41173 = 41173; + public static final int MAHOGANY_OUTFIT_STAND_41174 = 41174; + public static final int MAHOGANY_OUTFIT_STAND_41175 = 41175; + public static final int MAHOGANY_OUTFIT_STAND_41176 = 41176; + public static final int MAHOGANY_OUTFIT_STAND_41177 = 41177; + public static final int MAHOGANY_OUTFIT_STAND_41178 = 41178; + public static final int LEAGUE_STATUE = 41179; + public static final int ORNATE_LEAGUE_STATUE = 41180; + public static final int TRAILBLAZER_GLOBE = 41181; + public static final int LEAGUE_ACCOMPLISHMENT_SCROLL = 41182; + public static final int ANCIENT_BRAZIER = 41183; + public static final int ANCIENT_BRAZIER_41184 = 41184; + public static final int ANCIENT_BRAZIER_41185 = 41185; + public static final int ANCIENT_BRAZIER_41186 = 41186; + public static final int ANCIENT_BRAZIER_41187 = 41187; + public static final int ANCIENT_BRAZIER_41188 = 41188; + public static final int ANCIENT_BRAZIER_41189 = 41189; + public static final int ANCIENT_BRAZIER_41190 = 41190; + public static final int BARRIER_41199 = 41199; + public static final int BARRIER_41200 = 41200; + public static final int SOLID_GOLD_DOOR = 41210; + public static final int GOLD_CHEST = 41212; + public static final int GOLD_CHEST_41213 = 41213; + public static final int GOLD_CHEST_41214 = 41214; + public static final int GOLD_CHEST_41215 = 41215; + public static final int GOLD_CHEST_41216 = 41216; + public static final int GOLD_CHEST_41217 = 41217; + public static final int GOLD_CHEST_41218 = 41218; + public static final int GOLD_CHEST_41219 = 41219; + public static final int GOLD_CHEST_41220 = 41220; + public static final int GOLD_CHEST_41221 = 41221; + public static final int ALTAR_41222 = 41222; /* This file is automatically generated. Do not edit. */ -} \ No newline at end of file +} diff --git a/runelite-api/src/main/java/net/runelite/api/ParamHolder.java b/runelite-api/src/main/java/net/runelite/api/ParamHolder.java index 9ccc1328bf..694a9448f0 100644 --- a/runelite-api/src/main/java/net/runelite/api/ParamHolder.java +++ b/runelite-api/src/main/java/net/runelite/api/ParamHolder.java @@ -54,4 +54,4 @@ public interface ParamHolder * Sets the value of a given {@link ParamID} */ void setValue(int paramID, String value); -} \ No newline at end of file +} diff --git a/runelite-api/src/main/java/net/runelite/api/ParamID.java b/runelite-api/src/main/java/net/runelite/api/ParamID.java index 3c2cae2109..9be05d76ef 100644 --- a/runelite-api/src/main/java/net/runelite/api/ParamID.java +++ b/runelite-api/src/main/java/net/runelite/api/ParamID.java @@ -45,4 +45,4 @@ public class ParamID public static final int SETTING_SLIDER_IS_DRAGGABLE = 1108; public static final int SETTING_SLIDER_DEADZONE = 1109; public static final int SETTING_SLIDER_DEADTIME = 1110; -} \ No newline at end of file +} diff --git a/runelite-api/src/main/java/net/runelite/api/Perspective.java b/runelite-api/src/main/java/net/runelite/api/Perspective.java index 7c8a3c3ba0..9998d54923 100644 --- a/runelite-api/src/main/java/net/runelite/api/Perspective.java +++ b/runelite-api/src/main/java/net/runelite/api/Perspective.java @@ -376,7 +376,7 @@ public class Perspective */ public static Polygon getCanvasTilePoly(@Nonnull Client client, @Nonnull LocalPoint localLocation, int zOffset) { - return getCanvasTileAreaPoly(client, localLocation, 1, zOffset); + return getCanvasTileAreaPoly(client, localLocation, 1, 1, zOffset); } /** @@ -389,7 +389,7 @@ public class Perspective */ public static Polygon getCanvasTileAreaPoly(@Nonnull Client client, @Nonnull LocalPoint localLocation, int size) { - return getCanvasTileAreaPoly(client, localLocation, size, 0); + return getCanvasTileAreaPoly(client, localLocation, size, size, 0); } /** @@ -397,23 +397,25 @@ public class Perspective * * @param client the game client * @param localLocation the center location of the AoE - * @param size the size of the area (ie. 3x3 AoE evaluates to size 3) + * @param sizeX the size of the area in tiles on the x axis + * @param sizeY the size of the area in tiles on the y axis * @param zOffset offset from ground plane * @return a polygon representing the tiles in the area */ public static Polygon getCanvasTileAreaPoly( @Nonnull Client client, @Nonnull LocalPoint localLocation, - int size, + int sizeX, + int sizeY, int zOffset) { final int plane = client.getPlane(); - final int swX = localLocation.getX() - (size * LOCAL_TILE_SIZE / 2); - final int swY = localLocation.getY() - (size * LOCAL_TILE_SIZE / 2); + final int swX = localLocation.getX() - (sizeX * LOCAL_TILE_SIZE / 2); + final int swY = localLocation.getY() - (sizeY * LOCAL_TILE_SIZE / 2); - final int neX = localLocation.getX() + (size * LOCAL_TILE_SIZE / 2); - final int neY = localLocation.getY() + (size * LOCAL_TILE_SIZE / 2); + final int neX = localLocation.getX() + (sizeX * LOCAL_TILE_SIZE / 2); + final int neY = localLocation.getY() + (sizeY * LOCAL_TILE_SIZE / 2); final byte[][][] tileSettings = client.getTileSettings(); @@ -683,6 +685,7 @@ public class Perspective { int[] x2d = new int[m.getVerticesCount()]; int[] y2d = new int[m.getVerticesCount()]; + final int[] faceColors3 = m.getFaceColors3(); Perspective.modelToCanvas(client, m.getVerticesCount(), @@ -709,6 +712,11 @@ public class Perspective nextTri: for (int tri = 0; tri < m.getTrianglesCount(); tri++) { + if (faceColors3[tri] == -2) + { + continue; + } + int minX = Integer.MAX_VALUE, minY = Integer.MAX_VALUE, diff --git a/runelite-api/src/main/java/net/runelite/api/Preferences.java b/runelite-api/src/main/java/net/runelite/api/Preferences.java index d7b67242bf..5925c1c764 100644 --- a/runelite-api/src/main/java/net/runelite/api/Preferences.java +++ b/runelite-api/src/main/java/net/runelite/api/Preferences.java @@ -66,4 +66,9 @@ public interface Preferences * @param volume 0-127 inclusive */ void setAreaSoundEffectVolume(int volume); + + /** + * Gets if the login name should be replaced with asterisks + */ + boolean getHideUsername(); } diff --git a/runelite-api/src/main/java/net/runelite/api/Projectile.java b/runelite-api/src/main/java/net/runelite/api/Projectile.java index d298135af9..a539f55bfd 100644 --- a/runelite-api/src/main/java/net/runelite/api/Projectile.java +++ b/runelite-api/src/main/java/net/runelite/api/Projectile.java @@ -25,7 +25,7 @@ package net.runelite.api; /** - * Represents a projectile entity (ie. cannonball, arrow). + * Represents a projectile entity. (ie. cannonball, arrow) */ public interface Projectile extends Renderable { diff --git a/runelite-api/src/main/java/net/runelite/api/Quest.java b/runelite-api/src/main/java/net/runelite/api/Quest.java index 656bc19f9e..14ab4e8599 100644 --- a/runelite-api/src/main/java/net/runelite/api/Quest.java +++ b/runelite-api/src/main/java/net/runelite/api/Quest.java @@ -36,7 +36,7 @@ public enum Quest THE_CORSAIR_CURSE(301, "The Corsair Curse"), DEMON_SLAYER(302, "Demon Slayer"), DORICS_QUEST(303, "Doric's Quest"), - DRAGON_SLAYER(304, "Dragon Slayer"), + DRAGON_SLAYER_I(304, "Dragon Slayer I"), ERNEST_THE_CHICKEN(305, "Ernest the Chicken"), GOBLIN_DIPLOMACY(306, "Goblin Diplomacy"), IMP_CATCHER(307, "Imp Catcher"), @@ -133,7 +133,7 @@ public enum Quest PLAGUE_CITY(407, "Plague City"), PRIEST_IN_PERIL(408, "Priest in Peril"), THE_QUEEN_OF_THIEVES(409, "The Queen of Thieves"), - RAG_AND_BONE_MAN(410, "Rag and Bone Man"), + RAG_AND_BONE_MAN_I(410, "Rag and Bone Man I"), RAG_AND_BONE_MAN_II(411, "Rag and Bone Man II"), RATCATCHERS(412, "Ratcatchers"), RECIPE_FOR_DISASTER(413, "Recipe for Disaster"), diff --git a/runelite-api/src/main/java/net/runelite/api/ScriptEvent.java b/runelite-api/src/main/java/net/runelite/api/ScriptEvent.java index 361a71e3b1..2436c9ac3b 100644 --- a/runelite-api/src/main/java/net/runelite/api/ScriptEvent.java +++ b/runelite-api/src/main/java/net/runelite/api/ScriptEvent.java @@ -93,4 +93,4 @@ public interface ScriptEvent * This method must be ran on the client thread and is not reentrant */ void run(); -} \ No newline at end of file +} diff --git a/runelite-api/src/main/java/net/runelite/api/ScriptID.java b/runelite-api/src/main/java/net/runelite/api/ScriptID.java index 215a871a6f..ac7a9c7566 100644 --- a/runelite-api/src/main/java/net/runelite/api/ScriptID.java +++ b/runelite-api/src/main/java/net/runelite/api/ScriptID.java @@ -370,4 +370,4 @@ public final class ScriptID */ @ScriptArguments(integer = 4) public static final int WIKI_ICON_UPDATE = 3306; -} +} \ No newline at end of file diff --git a/runelite-api/src/main/java/net/runelite/api/SettingID.java b/runelite-api/src/main/java/net/runelite/api/SettingID.java index fd1b2859db..2d471d16f2 100644 --- a/runelite-api/src/main/java/net/runelite/api/SettingID.java +++ b/runelite-api/src/main/java/net/runelite/api/SettingID.java @@ -24,6 +24,9 @@ */ package net.runelite.api; +/** + * @see ParamID#SETTING_ID + */ public class SettingID { public static final int CAMERA_ZOOM = 14; @@ -31,4 +34,4 @@ public class SettingID public static final int MUSIC_VOLUME = 30; public static final int EFFECT_VOLUME = 31; public static final int AREA_VOLUME = 32; -} \ No newline at end of file +} diff --git a/runelite-api/src/main/java/net/runelite/api/StructComposition.java b/runelite-api/src/main/java/net/runelite/api/StructComposition.java index 5edc073bd4..b395a3beb2 100644 --- a/runelite-api/src/main/java/net/runelite/api/StructComposition.java +++ b/runelite-api/src/main/java/net/runelite/api/StructComposition.java @@ -35,4 +35,4 @@ package net.runelite.api; public interface StructComposition extends ParamHolder { int getId(); -} \ No newline at end of file +} diff --git a/runelite-api/src/main/java/net/runelite/api/StructID.java b/runelite-api/src/main/java/net/runelite/api/StructID.java index d12d8ed0ec..e1dab81026 100644 --- a/runelite-api/src/main/java/net/runelite/api/StructID.java +++ b/runelite-api/src/main/java/net/runelite/api/StructID.java @@ -34,4 +34,4 @@ public class StructID public static final int SETTINGS_MUSIC_VOLUME = 2753; public static final int SETTINGS_EFFECT_VOLUME = 2754; public static final int SETTINGS_AREA_VOLUME = 2755; -} \ No newline at end of file +} diff --git a/runelite-api/src/main/java/net/runelite/api/Tile.java b/runelite-api/src/main/java/net/runelite/api/Tile.java index 13b4a14bd7..46ada0f10e 100644 --- a/runelite-api/src/main/java/net/runelite/api/Tile.java +++ b/runelite-api/src/main/java/net/runelite/api/Tile.java @@ -59,6 +59,13 @@ public interface Tile extends TileObject */ GroundObject getGroundObject(); + /** + * Sets the object on the ground layer of the tile. + * + * @param groundObject the ground object + */ + void setGroundObject(GroundObject groundObject); + /** * Gets the wall of the tile. * diff --git a/runelite-api/src/main/java/net/runelite/api/Varbits.java b/runelite-api/src/main/java/net/runelite/api/Varbits.java index 90128c71d6..0bdf355c33 100644 --- a/runelite-api/src/main/java/net/runelite/api/Varbits.java +++ b/runelite-api/src/main/java/net/runelite/api/Varbits.java @@ -42,11 +42,6 @@ import lombok.Getter; @Getter public enum Varbits { - /* - * Kharedst's Memoirs Teleport Item - */ - KHAREDSTS_MEMOIRS_CHARGES(6035), - /* * If chatbox is transparent or not */ @@ -62,11 +57,6 @@ public enum Varbits */ CHAT_SCROLLBAR_ON_LEFT(6374), - /** - * Grand Exchange - */ - GRAND_EXCHANGE_PRICE_PER_ITEM(4398), - /** * Runepouch */ @@ -110,19 +100,6 @@ public enum Varbits PRAYER_PRESERVE(5466), PRAYER_RIGOUR(5464), PRAYER_AUGURY(5465), - - /** - * Locked Prayers - * 0-7 = Locked - * 8 = Unlocked - */ - CHIVPIETY_UNLOCKED(3909), - - /** - * Locked Prayers - * 0 = Locked - * 1 = Unlocked - */ RIGOUR_UNLOCKED(5451), AUGURY_UNLOCKED(5452), @@ -209,6 +186,10 @@ public enum Varbits * Defensive casting mode */ DEFENSIVE_CASTING_MODE(2668), + /** + * Spells being auto-casted + */ + AUTO_CAST_SPELL(276), /** * Options @@ -275,12 +256,12 @@ public enum Varbits /** * Blast Furnace Bar Dispenser - *

+ * * These are the expected values: - * 0 = No bars being processed - * 1 = Ores are being processed on the conveyor belt, bar dispenser cannot be checked - * 2 = Bars are cooling down - * 3 = Bars can be collected + * 0 = No bars being processed + * 1 = Ores are being processed on the conveyor belt, bar dispenser cannot be checked + * 2 = Bars are cooling down + * 3 = Bars can be collected */ BAR_DISPENSER(936), @@ -292,11 +273,11 @@ public enum Varbits /** * Experience tracker - *

+ * * EXPERIENCE_TRACKER_POSITION expected values: - * 0 = Right - * 1 = Middle - * 2 = Left + * 0 = Right + * 1 = Middle + * 2 = Left */ EXPERIENCE_TRACKER_POSITION(4692), EXPERIENCE_TRACKER_COUNTER(4697), @@ -349,23 +330,12 @@ public enum Varbits * Theatre of Blood 1=In Party, 2=Inside/Spectator, 3=Dead Spectating */ THEATRE_OF_BLOOD(6440), - BLOAT_DOOR(6447), - - /** - * Theatre of Blood orb varbits each number stands for the player's health on a scale of 1-27 (I think), 0 hides the orb - */ - THEATRE_OF_BLOOD_ORB_1(6442), - THEATRE_OF_BLOOD_ORB_2(6443), - THEATRE_OF_BLOOD_ORB_3(6444), - THEATRE_OF_BLOOD_ORB_4(6445), - THEATRE_OF_BLOOD_ORB_5(6446), /** * Nightmare Zone */ NMZ_ABSORPTION(3956), NMZ_POINTS(3949), - NMZ_OVERLOAD(3955), /** * Blast Furnace @@ -394,8 +364,6 @@ public enum Varbits /** * Pyramid plunder */ - PYRAMID_PLUNDER_SARCO_OPEN(2362), - PYRAMID_PLUNDER_CHEST_OPEN(2363), PYRAMID_PLUNDER_ROOM_LOCATION(2365), PYRAMID_PLUNDER_TIMER(2375), PYRAMID_PLUNDER_THIEVING_LEVEL(2376), @@ -426,31 +394,30 @@ public enum Varbits */ MULTICOMBAT_AREA(4605), - /** - * In the Wilderness - */ - IN_THE_WILDERNESS(5963), - /** * Kingdom Management */ KINGDOM_FAVOR(72), 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 */ QUEST_THE_HAND_IN_THE_SAND(1527), + /** + * 0 = Sir Bedivere + * 1 = Sir Pelleas + * 2 = Sir Tristram + * 3 = Sir Palomedes + * 4 = Sir Lucan + * 5 = Sir Gawain + * 6 = Sir Kay + * 7 = Sir Lancelot + * 8 = Completed (Chivalry and Piety are unlocked) + */ + CAMELOT_TRAINING_ROOM_STATUS(3909), + /** * Daily Tasks (Collection availability) */ @@ -464,7 +431,7 @@ public enum Varbits /** * This varbit tracks how much bonemeal has been redeemed from Robin * The player gets 13 for each diary completed above and including Medium, for a maxiumum of 39 - */ + */ DAILY_BONEMEAL_STATE(4543), DAILY_DYNAMITE_COLLECTED(7939), @@ -521,11 +488,6 @@ public enum Varbits */ ACCOUNT_TYPE(1777), - /** - * Varbit used for Slayer reward points - */ - SLAYER_REWARD_POINTS(4068), - /** * The varbit that stores the oxygen percentage for player */ @@ -586,20 +548,6 @@ public enum Varbits */ VENGEANCE_COOLDOWN(2451), - /** - * 0 = standard - * 1 = ancients - * 2 = lunars - * 3 = arrceus - **/ - SPELLBOOK(4070), - - /** - * Bank settings/flags - **/ - BANK_NOTE_FLAG(3958), - - /** * Amount of items in each bank tab */ @@ -619,13 +567,7 @@ public enum Varbits * 1 = sell */ GE_OFFER_CREATION_TYPE(4397), - - - /** - * Spells being auto-casted - */ - AUTO_CAST_SPELL(276), - + GE_OFFER_PRICE_PER_ITEM(4398), /** * The active tab within the quest interface @@ -640,140 +582,8 @@ public enum Varbits EXPLORER_RING_ALCHS(4554), EXPLORER_RING_RUNENERGY(4553), - /** - * Temple Trekking - */ - TREK_POINTS(1955), - TREK_STARTED(1956), - TREK_EVENT(1958), - TREK_STATUS(6719), - BLOAT_ENTERED_ROOM(6447), - - /** - * f2p Quest varbits, these don't hold the completion value. - */ - QUEST_DEMON_SLAYER(2561), - QUEST_GOBLIN_DIPLOMACY(2378), - QUEST_MISTHALIN_MYSTERY(3468), - QUEST_THE_CORSAIR_CURSE(6071), - QUEST_X_MARKS_THE_SPOT(8063), - QUEST_ERNEST_LEVER_A(1788), - QUEST_ERNEST_LEVER_B(1789), - QUEST_ERNEST_LEVER_C(1790), - QUEST_ERNEST_LEVER_D(1791), - QUEST_ERNEST_LEVER_E(1792), - QUEST_ERNEST_LEVER_F(1793), - - /** - * member Quest varbits, these don't hold the completion value. - */ - QUEST_ANIMAL_MAGNETISM(3185), - QUEST_BETWEEN_A_ROCK(299), - QUEST_CONTACT(3274), - QUEST_ZOGRE_FLESH_EATERS(487), - QUEST_DARKNESS_OF_HALLOWVALE(2573), - QUEST_DEATH_TO_THE_DORGESHUUN(2258), - QUEST_DESERT_TREASURE(358), - QUEST_DEVIOUS_MINDS(1465), - QUEST_EAGLES_PEAK(2780), - QUEST_ELEMENTAL_WORKSHOP_II(2639), - QUEST_ENAKHRAS_LAMENT(1560), - QUEST_ENLIGHTENED_JOURNEY(2866), - QUEST_THE_EYES_OF_GLOUPHRIE(2497), - QUEST_FAIRYTALE_I_GROWING_PAINS(1803), - QUEST_FAIRYTALE_II_CURE_A_QUEEN(2326), - QUEST_THE_FEUD(334), // 14 = able to pickpocket - QUEST_FORGETTABLE_TALE(822), - QUEST_GARDEN_OF_TRANQUILLITY(961), - QUEST_GHOSTS_AHOY(217), - QUEST_THE_GIANT_DWARF(571), - QUEST_THE_GOLEM(346), - QUEST_HORROR_FROM_THE_DEEP(34), - QUEST_ICTHLARINS_LITTLE_HELPER(418), - QUEST_IN_AID_OF_THE_MYREQUE(1990), - QUEST_THE_LOST_TRIBE(532), - QUEST_LUNAR_DIPLOMACY(2448), - QUEST_MAKING_HISTORY(1383), - QUEST_MOUNTAIN_DAUGHTER(260), - QUEST_MOURNINGS_END_PART_II(1103), - QUEST_MY_ARMS_BIG_ADVENTURE(2790), - QUEST_RATCATCHERS(1404), - QUEST_RECIPE_FOR_DISASTER(1850), - QUEST_RECRUITMENT_DRIVE(657), - QUEST_ROYAL_TROUBLE(2140), - QUEST_THE_SLUG_MENACE(2610), - QUEST_SHADOW_OF_THE_STORM(1372), - QUEST_A_SOULS_BANE(2011), - QUEST_SPIRITS_OF_THE_ELID(1444), - QUEST_SWAN_SONG(2098), - QUEST_A_TAIL_OF_TWO_CATS(1028), - QUEST_TEARS_OF_GUTHIX(451), - QUEST_WANTED(1051), - QUEST_COLD_WAR(3293), - QUEST_THE_FREMENNIK_ISLES(3311), - QUEST_TOWER_OF_LIFE(3337), - QUEST_WHAT_LIES_BELOW(3523), - QUEST_OLAFS_QUEST(3534), - QUEST_ANOTHER_SLICE_OF_HAM(3550), - QUEST_DREAM_MENTOR(3618), - QUEST_GRIM_TALES(2783), - QUEST_KINGS_RANSOM(3888), - QUEST_MONKEY_MADNESS_II(5027), - QUEST_CLIENT_OF_KOUREND(5619), - QUEST_BONE_VOYAGE(5795), - QUEST_THE_QUEEN_OF_THIEVES(6037), - QUEST_THE_DEPTHS_OF_DESPAIR(6027), - QUEST_DRAGON_SLAYER_II(6104), - QUEST_TALE_OF_THE_RIGHTEOUS(6358), - QUEST_A_TASTE_OF_HOPE(6396), - QUEST_MAKING_FRIENDS_WITH_MY_ARM(6528), - QUEST_THE_ASCENT_OF_ARCEUUS(7856), - QUEST_THE_FORSAKEN_TOWER(7796), - //TODO - QUEST_SONG_OF_THE_ELVES(7796), - - /** - * mini-quest varbits, these don't hold the completion value. - */ - QUEST_ARCHITECTURAL_ALLIANCE(4982), - QUEST_BEAR_YOUR_SOUL(5078), - QUEST_CURSE_OF_THE_EMPTY_LORD(821), - QUEST_ENCHANTED_KEY(1391), - QUEST_THE_GENERALS_SHADOW(3330), - QUEST_SKIPPY_AND_THE_MOGRES(1344), - QUEST_LAIR_OF_TARN_RAZORLOR(3290), - QUEST_FAMILY_PEST(5347), - QUEST_THE_MAGE_ARENA_II(6067), - //TODO - QUEST_IN_SEARCH_OF_KNOWLEDGE(6067), - - /** - * Spellbook filtering (1 = unfiltered, 0 = filtered) - */ - FILTER_SPELLBOOK(6718), - - /** - * POH Building mode (1 = yes, 0 = no) - */ - BUILDING_MODE(2176), - WINTERTODT_TIMER(7980), - /** - * 1 if in game, 0 if not - */ - LMS_IN_GAME(5314), - - /** - * Amount of pvp kills in current game - */ - LMS_KILLS(5315), - - /** - * The x coordinate of the final safespace (world coord) - */ - LMS_SAFE_X(5316), - /** * League relics */ @@ -791,6 +601,15 @@ public enum Varbits MUTED_SOUND_EFFECT_VOLUME(9674), MUTED_AREA_EFFECT_VOLUME(9675), + /** + * Parasite infection status during nightmare of ashihama bossfight + * + * 0 = not infected + * 1 = infected + * + */ + PARASITE(10151), + /** * Whether the Special Attack orb is disabled due to being in a PvP area * @@ -799,69 +618,7 @@ public enum Varbits * * @see The OSRS Wiki's Minimap page */ - PVP_SPEC_ORB(8121), - - LMS_POISON_PROGRESS(5317), - - /** - * The y coordinate of the final safespace (world coord) - */ - LMS_SAFE_Y(5320), - - /** - * 1 is true, 0 is false. - */ - GAUNTLET_FINAL_ROOM_ENTERED(9177), - - /** - * 1 is true, 0 is false. - */ - GAUNTLET_ENTERED(9178), - - WITHDRAW_X_AMOUNT(3960), - - IN_PVP_AREA(8121), - - /** - * Value of hotkey varbits can be 0-13 - * 0 corresponds to no hotkey set - * 1-12 correspond to F1-F12 respectively - * 13 corresponds to escape - */ - COMBAT_TAB_HOTKEY(4675), - STATS_TAB_HOTKEY(4676), - QUESTS_TAB_HOTKEY(4677), - INVENTORY_TAB_HOTKEY(4678), - EQUIPMENT_TAB_HOTKEY(4679), - PRAYER_TAB_HOTKEY(4680), - SPELLBOOK_TAB_HOTKEY(4682), - FRIENDS_TAB_HOTKEY(4684), - ACCOUNT_MANAGEMENT_TAB_HOTKEY(6517), - LOGOUT_TAB_HOTKEY(4689), - OPTIONS_TAB_HOTKEY(4686), - EMOTES_TAB_HOTKEY(4687), - CLAN_TAB_HOTKEY(4683), - MUSIC_TAB_HOTKEY(4688), - - /** - * Chat Notifications settings - *
- * LOOT_DROP_NOTIFICATIONS: 1 is true, 0 is false - * LOOT_DROP_NOTIFICATIONS_VALUE: gp value - * UNTRADEABLE_LOOT_NOTIFICATIONS: 1 is true, 0 is false - * BOSS_KILL_COUNT_UPDATES: 1 is filtered, 0 is unfiltered - * DROP_ITEM_WARNINGS: 1 is true, 0 is false - * DROP_ITEM_WARNINGS_VALUE: gp value - */ - LOOT_DROP_NOTIFICATIONS(5399), - LOOT_DROP_NOTIFICATIONS_VALUE(5400), - UNTRADEABLE_LOOT_NOTIFICATIONS(5402), - BOSS_KILL_COUNT_UPDATES(4930), - DROP_ITEM_WARNINGS(5411), - DROP_ITEM_WARNINGS_VALUE(5412), - - PARASITE(10151), - ; + PVP_SPEC_ORB(8121); /** * The raw varbit ID. diff --git a/runelite-api/src/main/java/net/runelite/api/events/ActorDeath.java b/runelite-api/src/main/java/net/runelite/api/events/ActorDeath.java index c976f2fe9c..b6e4588c0c 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/ActorDeath.java +++ b/runelite-api/src/main/java/net/runelite/api/events/ActorDeath.java @@ -31,7 +31,7 @@ import net.runelite.api.Actor; * An event fired when an actor dies. */ @Value -public class ActorDeath implements Event +public class ActorDeath { Actor actor; } diff --git a/runelite-api/src/main/java/net/runelite/api/events/AnimationChanged.java b/runelite-api/src/main/java/net/runelite/api/events/AnimationChanged.java index 943337f132..5cbc26a97b 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/AnimationChanged.java +++ b/runelite-api/src/main/java/net/runelite/api/events/AnimationChanged.java @@ -17,7 +17,7 @@ import lombok.Data; * @see net.runelite.api.AnimationID */ @Data -public class AnimationChanged implements Event +public class AnimationChanged { /** * The actor that has entered a new animation. diff --git a/runelite-api/src/main/java/net/runelite/api/events/AreaSoundEffectPlayed.java b/runelite-api/src/main/java/net/runelite/api/events/AreaSoundEffectPlayed.java index c40aab4119..4114cb22ca 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/AreaSoundEffectPlayed.java +++ b/runelite-api/src/main/java/net/runelite/api/events/AreaSoundEffectPlayed.java @@ -29,7 +29,7 @@ import lombok.Data; import net.runelite.api.Actor; @Data -public class AreaSoundEffectPlayed implements Event +public class AreaSoundEffectPlayed { @Nullable private final Actor source; diff --git a/runelite-api/src/main/java/net/runelite/api/events/BeforeMenuRender.java b/runelite-api/src/main/java/net/runelite/api/events/BeforeMenuRender.java index 055fb37a41..5d1e10994b 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/BeforeMenuRender.java +++ b/runelite-api/src/main/java/net/runelite/api/events/BeforeMenuRender.java @@ -27,7 +27,7 @@ package net.runelite.api.events; import lombok.Data; @Data -public class BeforeMenuRender implements Event +public class BeforeMenuRender { private boolean consumed; diff --git a/runelite-api/src/main/java/net/runelite/api/events/BeforeRender.java b/runelite-api/src/main/java/net/runelite/api/events/BeforeRender.java index 70d7551ac0..bee23922dd 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/BeforeRender.java +++ b/runelite-api/src/main/java/net/runelite/api/events/BeforeRender.java @@ -27,7 +27,7 @@ package net.runelite.api.events; /** * Posted at the start of every frame */ -public class BeforeRender implements Event +public class BeforeRender { public static final BeforeRender INSTANCE = new BeforeRender(); diff --git a/runelite-api/src/main/java/net/runelite/api/events/CannonChanged.java b/runelite-api/src/main/java/net/runelite/api/events/CannonChanged.java index 4782c8e8a1..4af81c6ccf 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/CannonChanged.java +++ b/runelite-api/src/main/java/net/runelite/api/events/CannonChanged.java @@ -31,7 +31,7 @@ import lombok.Value; * an event posted when a cannonball is fired */ @Value -public class CannonChanged implements Event +public class CannonChanged { /** * The projectile id. diff --git a/runelite-api/src/main/java/net/runelite/api/events/CannonPlaced.java b/runelite-api/src/main/java/net/runelite/api/events/CannonPlaced.java index 8d0aa636c0..8b3f4402bd 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/CannonPlaced.java +++ b/runelite-api/src/main/java/net/runelite/api/events/CannonPlaced.java @@ -33,7 +33,7 @@ import net.runelite.api.coords.WorldPoint; * an event posted when a cannonball is fired */ @Value -public class CannonPlaced implements Event +public class CannonPlaced { /** * Cannon placed or picked up. diff --git a/runelite-api/src/main/java/net/runelite/api/events/CanvasSizeChanged.java b/runelite-api/src/main/java/net/runelite/api/events/CanvasSizeChanged.java index 66ad5dbcec..0efef18d0d 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/CanvasSizeChanged.java +++ b/runelite-api/src/main/java/net/runelite/api/events/CanvasSizeChanged.java @@ -27,7 +27,7 @@ package net.runelite.api.events; /** * An event posted when the canvas size might have changed. */ -public class CanvasSizeChanged implements Event +public class CanvasSizeChanged { public static final CanvasSizeChanged INSTANCE = new CanvasSizeChanged(); diff --git a/runelite-api/src/main/java/net/runelite/api/events/ChatMessage.java b/runelite-api/src/main/java/net/runelite/api/events/ChatMessage.java index 3c6230e6e9..fccf5a98d8 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/ChatMessage.java +++ b/runelite-api/src/main/java/net/runelite/api/events/ChatMessage.java @@ -41,7 +41,7 @@ import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor -public class ChatMessage implements Event +public class ChatMessage { /** * The underlying MessageNode for the message. diff --git a/runelite-api/src/main/java/net/runelite/api/events/ClientTick.java b/runelite-api/src/main/java/net/runelite/api/events/ClientTick.java index 9ffef0d573..6874f4145c 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/ClientTick.java +++ b/runelite-api/src/main/java/net/runelite/api/events/ClientTick.java @@ -27,7 +27,7 @@ package net.runelite.api.events; /** * Posted every client tick */ -public class ClientTick implements Event +public class ClientTick { public static final ClientTick INSTANCE = new ClientTick(); diff --git a/runelite-api/src/main/java/net/runelite/api/events/CommandExecuted.java b/runelite-api/src/main/java/net/runelite/api/events/CommandExecuted.java index a66acb9d5c..fe524a7e76 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/CommandExecuted.java +++ b/runelite-api/src/main/java/net/runelite/api/events/CommandExecuted.java @@ -42,7 +42,7 @@ import lombok.Value; * will set command to "" and arguments to ["hello", "world!"]. */ @Value -public class CommandExecuted implements Event +public class CommandExecuted { /** * The name of the command entered. diff --git a/runelite-api/src/main/java/net/runelite/api/events/ConfigButtonClicked.java b/runelite-api/src/main/java/net/runelite/api/events/ConfigButtonClicked.java index 7aeb4ffa84..24556b1dff 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/ConfigButtonClicked.java +++ b/runelite-api/src/main/java/net/runelite/api/events/ConfigButtonClicked.java @@ -1,10 +1,9 @@ package net.runelite.api.events; import lombok.Data; -import net.runelite.api.events.Event; @Data -public class ConfigButtonClicked implements Event +public class ConfigButtonClicked { private String group, key; } diff --git a/runelite-api/src/main/java/net/runelite/api/events/DecorativeObjectChanged.java b/runelite-api/src/main/java/net/runelite/api/events/DecorativeObjectChanged.java index a64a1c5c47..a18683d7b4 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/DecorativeObjectChanged.java +++ b/runelite-api/src/main/java/net/runelite/api/events/DecorativeObjectChanged.java @@ -33,7 +33,7 @@ import lombok.Data; * has been modified. */ @Data -public class DecorativeObjectChanged implements Event +public class DecorativeObjectChanged { /** * The affected tile. diff --git a/runelite-api/src/main/java/net/runelite/api/events/DecorativeObjectDespawned.java b/runelite-api/src/main/java/net/runelite/api/events/DecorativeObjectDespawned.java index 6760c0d05d..94c06488c7 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/DecorativeObjectDespawned.java +++ b/runelite-api/src/main/java/net/runelite/api/events/DecorativeObjectDespawned.java @@ -33,7 +33,7 @@ import lombok.Data; * is removed. */ @Data -public class DecorativeObjectDespawned implements Event +public class DecorativeObjectDespawned { /** * The affected tile. diff --git a/runelite-api/src/main/java/net/runelite/api/events/DecorativeObjectSpawned.java b/runelite-api/src/main/java/net/runelite/api/events/DecorativeObjectSpawned.java index 37d0a5fab2..fe8d17862f 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/DecorativeObjectSpawned.java +++ b/runelite-api/src/main/java/net/runelite/api/events/DecorativeObjectSpawned.java @@ -32,7 +32,7 @@ import lombok.Data; * An event where a {@link DecorativeObject} is attached to a {@link Tile}. */ @Data -public class DecorativeObjectSpawned implements Event +public class DecorativeObjectSpawned { /** * The affected tile. diff --git a/runelite-api/src/main/java/net/runelite/api/events/DialogProcessed.java b/runelite-api/src/main/java/net/runelite/api/events/DialogProcessed.java new file mode 100644 index 0000000000..c94d82b194 --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/events/DialogProcessed.java @@ -0,0 +1,10 @@ +package net.runelite.api.events; + +import lombok.Value; +import net.runelite.api.DialogOption; + +@Value +public class DialogProcessed +{ + DialogOption dialogOption; +} \ No newline at end of file diff --git a/runelite-api/src/main/java/net/runelite/api/events/DraggingWidgetChanged.java b/runelite-api/src/main/java/net/runelite/api/events/DraggingWidgetChanged.java index 0f9bf09691..8aef02d570 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/DraggingWidgetChanged.java +++ b/runelite-api/src/main/java/net/runelite/api/events/DraggingWidgetChanged.java @@ -31,7 +31,7 @@ import lombok.Data; * the cursor. */ @Data -public class DraggingWidgetChanged implements Event +public class DraggingWidgetChanged { /** * Whether a widget is currently being dragged. diff --git a/runelite-api/src/main/java/net/runelite/api/events/DynamicObjectAnimationChanged.java b/runelite-api/src/main/java/net/runelite/api/events/DynamicObjectAnimationChanged.java index 382cb706fb..1e4571e4fe 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/DynamicObjectAnimationChanged.java +++ b/runelite-api/src/main/java/net/runelite/api/events/DynamicObjectAnimationChanged.java @@ -3,7 +3,7 @@ package net.runelite.api.events; import lombok.Data; @Data -public class DynamicObjectAnimationChanged implements Event +public class DynamicObjectAnimationChanged { /** * The object that has entered a new animation. diff --git a/runelite-api/src/main/java/net/runelite/api/events/Event.java b/runelite-api/src/main/java/net/runelite/api/events/Event.java deleted file mode 100644 index b031dce09e..0000000000 --- a/runelite-api/src/main/java/net/runelite/api/events/Event.java +++ /dev/null @@ -1,3 +0,0 @@ -package net.runelite.api.events; - -public interface Event {} diff --git a/runelite-api/src/main/java/net/runelite/api/events/FakeXpDrop.java b/runelite-api/src/main/java/net/runelite/api/events/FakeXpDrop.java index 0aac13728f..07a98b0eb4 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/FakeXpDrop.java +++ b/runelite-api/src/main/java/net/runelite/api/events/FakeXpDrop.java @@ -28,7 +28,7 @@ import lombok.Value; import net.runelite.api.Skill; @Value -public class FakeXpDrop implements Event +public class FakeXpDrop { Skill skill; int xp; diff --git a/runelite-api/src/main/java/net/runelite/api/events/FocusChanged.java b/runelite-api/src/main/java/net/runelite/api/events/FocusChanged.java index 3f190fd331..fd9fcb6466 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/FocusChanged.java +++ b/runelite-api/src/main/java/net/runelite/api/events/FocusChanged.java @@ -37,7 +37,7 @@ import lombok.Data; * */ @Data -public class FocusChanged implements Event +public class FocusChanged { /** * The new focus state. diff --git a/runelite-api/src/main/java/net/runelite/api/events/FriendAdded.java b/runelite-api/src/main/java/net/runelite/api/events/FriendAdded.java index c7c2160759..37be825080 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/FriendAdded.java +++ b/runelite-api/src/main/java/net/runelite/api/events/FriendAdded.java @@ -6,7 +6,7 @@ import lombok.Value; * An event where a request to add a friend is sent to the server. */ @Value -public class FriendAdded implements Event +public class FriendAdded { /** * The name of the added friend. diff --git a/runelite-api/src/main/java/net/runelite/api/events/FriendsChatChanged.java b/runelite-api/src/main/java/net/runelite/api/events/FriendsChatChanged.java index 12c203769a..271eb83e49 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/FriendsChatChanged.java +++ b/runelite-api/src/main/java/net/runelite/api/events/FriendsChatChanged.java @@ -30,7 +30,7 @@ import lombok.Value; * An event where the client has joined or left a friends chat. */ @Value -public class FriendsChatChanged implements Event +public class FriendsChatChanged { /** * Whether or not the client is now in a friends chat. diff --git a/runelite-api/src/main/java/net/runelite/api/events/FriendsChatMemberJoined.java b/runelite-api/src/main/java/net/runelite/api/events/FriendsChatMemberJoined.java index 7adbf159fe..e5a0cdb8a0 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/FriendsChatMemberJoined.java +++ b/runelite-api/src/main/java/net/runelite/api/events/FriendsChatMemberJoined.java @@ -28,7 +28,7 @@ import lombok.Value; import net.runelite.api.FriendsChatMember; @Value -public class FriendsChatMemberJoined implements Event +public class FriendsChatMemberJoined { /** * The member that joined diff --git a/runelite-api/src/main/java/net/runelite/api/events/FriendsChatMemberLeft.java b/runelite-api/src/main/java/net/runelite/api/events/FriendsChatMemberLeft.java index 49530eb870..0970b762c8 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/FriendsChatMemberLeft.java +++ b/runelite-api/src/main/java/net/runelite/api/events/FriendsChatMemberLeft.java @@ -28,7 +28,7 @@ import lombok.Value; import net.runelite.api.FriendsChatMember; @Value -public class FriendsChatMemberLeft implements Event +public class FriendsChatMemberLeft { /** * The member that left diff --git a/runelite-api/src/main/java/net/runelite/api/events/GameObjectChanged.java b/runelite-api/src/main/java/net/runelite/api/events/GameObjectChanged.java index dee1f261ea..117ad81f60 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/GameObjectChanged.java +++ b/runelite-api/src/main/java/net/runelite/api/events/GameObjectChanged.java @@ -32,7 +32,7 @@ import net.runelite.api.Tile; * An event where a {@link GameObject} on a {@link Tile} has been replaced. */ @Data -public class GameObjectChanged implements Event +public class GameObjectChanged { /** * The affected tile. diff --git a/runelite-api/src/main/java/net/runelite/api/events/GameObjectDespawned.java b/runelite-api/src/main/java/net/runelite/api/events/GameObjectDespawned.java index ed7e11ae2f..5d2e9fad1a 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/GameObjectDespawned.java +++ b/runelite-api/src/main/java/net/runelite/api/events/GameObjectDespawned.java @@ -32,7 +32,7 @@ import lombok.Data; * An event where a {@link GameObject} on a {@link Tile} is removed. */ @Data -public class GameObjectDespawned implements Event +public class GameObjectDespawned { /** * The affected tile. diff --git a/runelite-api/src/main/java/net/runelite/api/events/GameObjectSpawned.java b/runelite-api/src/main/java/net/runelite/api/events/GameObjectSpawned.java index df2b4fcca4..dc9fdbdd24 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/GameObjectSpawned.java +++ b/runelite-api/src/main/java/net/runelite/api/events/GameObjectSpawned.java @@ -32,7 +32,7 @@ import net.runelite.api.Tile; * An event where a {@link GameObject} is added to a {@link Tile}. */ @Data -public class GameObjectSpawned implements Event +public class GameObjectSpawned { /** * The affected tile. diff --git a/runelite-api/src/main/java/net/runelite/api/events/GameStateChanged.java b/runelite-api/src/main/java/net/runelite/api/events/GameStateChanged.java index eb9612211c..2a0b61fc40 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/GameStateChanged.java +++ b/runelite-api/src/main/java/net/runelite/api/events/GameStateChanged.java @@ -31,7 +31,7 @@ import lombok.Data; * An event where the clients game state has changed. */ @Data -public class GameStateChanged implements Event +public class GameStateChanged { /** * The new game state. diff --git a/runelite-api/src/main/java/net/runelite/api/events/GameTick.java b/runelite-api/src/main/java/net/runelite/api/events/GameTick.java index ce3fbaf25f..499b2ae83c 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/GameTick.java +++ b/runelite-api/src/main/java/net/runelite/api/events/GameTick.java @@ -41,7 +41,7 @@ package net.runelite.api.events; * Note that occurrences that take place purely on the client, such as right * click menus, are independent of the game tick. */ -public class GameTick implements Event +public class GameTick { public static final GameTick INSTANCE = new GameTick(); diff --git a/runelite-api/src/main/java/net/runelite/api/events/GrandExchangeOfferChanged.java b/runelite-api/src/main/java/net/runelite/api/events/GrandExchangeOfferChanged.java index 52ae0e6d92..88e4aa1fac 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/GrandExchangeOfferChanged.java +++ b/runelite-api/src/main/java/net/runelite/api/events/GrandExchangeOfferChanged.java @@ -41,7 +41,7 @@ import lombok.Data; * can change into. */ @Data -public class GrandExchangeOfferChanged implements Event +public class GrandExchangeOfferChanged { /** * The offer that has been modified. diff --git a/runelite-api/src/main/java/net/runelite/api/events/GrandExchangeSearched.java b/runelite-api/src/main/java/net/runelite/api/events/GrandExchangeSearched.java index b357240149..aa96680d1c 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/GrandExchangeSearched.java +++ b/runelite-api/src/main/java/net/runelite/api/events/GrandExchangeSearched.java @@ -31,7 +31,7 @@ import lombok.Data; * An event where the Grand Exchange has been searched. */ @Data -public class GrandExchangeSearched implements Event +public class GrandExchangeSearched { /** * Whether or not the event has been consumed by a subscriber. diff --git a/runelite-api/src/main/java/net/runelite/api/events/GraphicChanged.java b/runelite-api/src/main/java/net/runelite/api/events/GraphicChanged.java index ee7b781c82..775487c6d0 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/GraphicChanged.java +++ b/runelite-api/src/main/java/net/runelite/api/events/GraphicChanged.java @@ -19,7 +19,7 @@ import net.runelite.api.Actor; * @see net.runelite.api.GraphicID */ @Data -public class GraphicChanged implements Event +public class GraphicChanged { /** * The actor that has had their graphic changed. diff --git a/runelite-api/src/main/java/net/runelite/api/events/GraphicsObjectCreated.java b/runelite-api/src/main/java/net/runelite/api/events/GraphicsObjectCreated.java index b074e63d40..280cc77624 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/GraphicsObjectCreated.java +++ b/runelite-api/src/main/java/net/runelite/api/events/GraphicsObjectCreated.java @@ -31,7 +31,7 @@ import lombok.Value; * An event where a new {@link GraphicsObject} has been created. */ @Value -public class GraphicsObjectCreated implements Event +public class GraphicsObjectCreated { /** * The newly created graphics object. diff --git a/runelite-api/src/main/java/net/runelite/api/events/GroundObjectChanged.java b/runelite-api/src/main/java/net/runelite/api/events/GroundObjectChanged.java index c58b46575d..8fa97ae503 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/GroundObjectChanged.java +++ b/runelite-api/src/main/java/net/runelite/api/events/GroundObjectChanged.java @@ -32,7 +32,7 @@ import lombok.Data; * An event where the {@link GroundObject} on a {@link Tile} has been changed. */ @Data -public class GroundObjectChanged implements Event +public class GroundObjectChanged { /** * The affected tile. diff --git a/runelite-api/src/main/java/net/runelite/api/events/GroundObjectDespawned.java b/runelite-api/src/main/java/net/runelite/api/events/GroundObjectDespawned.java index 6e793f025e..54bb6dfbe0 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/GroundObjectDespawned.java +++ b/runelite-api/src/main/java/net/runelite/api/events/GroundObjectDespawned.java @@ -32,7 +32,7 @@ import lombok.Data; * An event where a {@link GroundObject} on a {@link Tile} has been removed. */ @Data -public class GroundObjectDespawned implements Event +public class GroundObjectDespawned { /** * The affected tile. diff --git a/runelite-api/src/main/java/net/runelite/api/events/GroundObjectSpawned.java b/runelite-api/src/main/java/net/runelite/api/events/GroundObjectSpawned.java index 2ccce09136..af1f15ab6f 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/GroundObjectSpawned.java +++ b/runelite-api/src/main/java/net/runelite/api/events/GroundObjectSpawned.java @@ -32,7 +32,7 @@ import lombok.Data; * An event where a {@link GroundObject} is added to a {@link Tile}. */ @Data -public class GroundObjectSpawned implements Event +public class GroundObjectSpawned { /** * The affected tile. diff --git a/runelite-api/src/main/java/net/runelite/api/events/HitsplatApplied.java b/runelite-api/src/main/java/net/runelite/api/events/HitsplatApplied.java index d8b22ee2bc..f96a0f08d7 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/HitsplatApplied.java +++ b/runelite-api/src/main/java/net/runelite/api/events/HitsplatApplied.java @@ -36,7 +36,7 @@ import lombok.Data; * visible hitsplats. */ @Data -public class HitsplatApplied implements Event +public class HitsplatApplied { /** * The actor the hitsplat was applied to. diff --git a/runelite-api/src/main/java/net/runelite/api/events/InteractChanged.java b/runelite-api/src/main/java/net/runelite/api/events/InteractChanged.java index 1e08180b88..fcd2e54a43 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/InteractChanged.java +++ b/runelite-api/src/main/java/net/runelite/api/events/InteractChanged.java @@ -28,7 +28,7 @@ import net.runelite.api.Actor; import lombok.Data; @Data -public class InteractChanged implements Event +public class InteractChanged { private Actor actor; } diff --git a/runelite-api/src/main/java/net/runelite/api/events/InteractingChanged.java b/runelite-api/src/main/java/net/runelite/api/events/InteractingChanged.java index a4f22a3583..ef1da8baca 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/InteractingChanged.java +++ b/runelite-api/src/main/java/net/runelite/api/events/InteractingChanged.java @@ -7,7 +7,7 @@ import lombok.Value; * An event called when the actor an actor is interacting with changes */ @Value -public class InteractingChanged implements Event +public class InteractingChanged { Actor source; diff --git a/runelite-api/src/main/java/net/runelite/api/events/ItemContainerChanged.java b/runelite-api/src/main/java/net/runelite/api/events/ItemContainerChanged.java index 82dc290dd0..5a5ddef151 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/ItemContainerChanged.java +++ b/runelite-api/src/main/java/net/runelite/api/events/ItemContainerChanged.java @@ -39,7 +39,7 @@ import lombok.Value; * */ @Value -public class ItemContainerChanged implements Event +public class ItemContainerChanged { /** * The modified container's ID. diff --git a/runelite-api/src/main/java/net/runelite/api/events/ItemDespawned.java b/runelite-api/src/main/java/net/runelite/api/events/ItemDespawned.java index 870a39f29f..22082bfedc 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/ItemDespawned.java +++ b/runelite-api/src/main/java/net/runelite/api/events/ItemDespawned.java @@ -34,7 +34,7 @@ import lombok.Value; * all item piles are implicitly despawned, and despawn events will not be sent. */ @Value -public class ItemDespawned implements Event +public class ItemDespawned { Tile tile; TileItem item; diff --git a/runelite-api/src/main/java/net/runelite/api/events/ItemQuantityChanged.java b/runelite-api/src/main/java/net/runelite/api/events/ItemQuantityChanged.java index 0e596b8397..7971da5f12 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/ItemQuantityChanged.java +++ b/runelite-api/src/main/java/net/runelite/api/events/ItemQuantityChanged.java @@ -33,7 +33,7 @@ import lombok.Value; * Called when the quantity of an item pile changes. */ @Value -public class ItemQuantityChanged implements Event +public class ItemQuantityChanged { TileItem item; Tile tile; diff --git a/runelite-api/src/main/java/net/runelite/api/events/ItemSpawned.java b/runelite-api/src/main/java/net/runelite/api/events/ItemSpawned.java index 9daa54077d..af3c034abc 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/ItemSpawned.java +++ b/runelite-api/src/main/java/net/runelite/api/events/ItemSpawned.java @@ -34,7 +34,7 @@ import lombok.Value; * all item piles are implicitly reset and a new spawn event will be sent. */ @Value -public class ItemSpawned implements Event +public class ItemSpawned { Tile tile; TileItem item; diff --git a/runelite-api/src/main/java/net/runelite/api/events/Menu.java b/runelite-api/src/main/java/net/runelite/api/events/Menu.java index d344397221..d7a5af40cb 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/Menu.java +++ b/runelite-api/src/main/java/net/runelite/api/events/Menu.java @@ -4,7 +4,7 @@ package net.runelite.api.events; * Gets sent before menu handling code is ran, once per client tick. * Can be consumed, skipping this method this tick. */ -public class Menu implements Event +public class Menu { public static final Menu MENU = new Menu(); diff --git a/runelite-api/src/main/java/net/runelite/api/events/MenuEntryAdded.java b/runelite-api/src/main/java/net/runelite/api/events/MenuEntryAdded.java index 7b9c0d3fb3..727476a035 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/MenuEntryAdded.java +++ b/runelite-api/src/main/java/net/runelite/api/events/MenuEntryAdded.java @@ -30,7 +30,7 @@ import net.runelite.api.MenuEntry; /** * An event when a new entry is added to a right-click menu. */ -public class MenuEntryAdded extends MenuEntry implements Event +public class MenuEntryAdded extends MenuEntry { public MenuEntryAdded(String option, String target, int identifier, int opcode, int param0, int param1, boolean forceLeftClick) { diff --git a/runelite-api/src/main/java/net/runelite/api/events/MenuOpened.java b/runelite-api/src/main/java/net/runelite/api/events/MenuOpened.java index ee31b0ad04..6d34000cea 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/MenuOpened.java +++ b/runelite-api/src/main/java/net/runelite/api/events/MenuOpened.java @@ -34,7 +34,7 @@ import lombok.Data; * An event where a menu has been opened. */ @Data -public class MenuOpened implements Event, Iterable +public class MenuOpened implements Iterable { /** * This should be set to true if anything about the menu diff --git a/runelite-api/src/main/java/net/runelite/api/events/MenuOptionClicked.java b/runelite-api/src/main/java/net/runelite/api/events/MenuOptionClicked.java index 0ed4fb0df1..4ff7b8138e 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/MenuOptionClicked.java +++ b/runelite-api/src/main/java/net/runelite/api/events/MenuOptionClicked.java @@ -24,9 +24,8 @@ */ package net.runelite.api.events; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.Setter; +import lombok.Data; +import net.runelite.api.MenuAction; import net.runelite.api.MenuEntry; /** @@ -40,32 +39,44 @@ import net.runelite.api.MenuEntry; * By default, when there is no action performed when left-clicking, * it seems that this event still triggers with the "Cancel" action. */ -@Getter -public class MenuOptionClicked extends MenuEntry implements Event +@Data +public class MenuOptionClicked { - public MenuOptionClicked(String option, String target, int identifier, int opcode, int param0, int param1, boolean forceLeftClick) - { - super(option, target, identifier, opcode, param0, param1, forceLeftClick); - authentic = true; - } - - public MenuOptionClicked(String option, String target, int identifier, int opcode, int param0, int param1, boolean forceLeftClick, boolean authentic, int mouseButton) - { - super(option, target, identifier, opcode, param0, param1, forceLeftClick); - this.authentic = authentic; - this.mouseButton = mouseButton; - } - + /** + * The action parameter used in the click. + */ + private int actionParam; + /** + * The option text added to the menu. + */ + private String menuOption; + /** + * The target of the action. + */ + private String menuTarget; + /** + * The action performed. + */ + private MenuAction menuAction; + /** + * The ID of the object, actor, or item that the interaction targets. + */ + private int id; + /** + * The ID of the widget where the menu was clicked. + * + * @see net.runelite.api.widgets.WidgetID + */ + private int widgetId; + /** + * The selected item index at the time of the option click. + */ + private int selectedItemIndex; /** * Whether or not the event has been consumed by a subscriber. */ private boolean consumed; - /** - * The mouse button will be 1 if a non draggable widget was clicked, - */ - private int mouseButton; - /** * Marks the event as having been consumed. *

@@ -78,35 +89,13 @@ public class MenuOptionClicked extends MenuEntry implements Event this.consumed = true; } - /** - * Whether or not the event is authentic. - */ - @Setter(AccessLevel.NONE) - private final boolean authentic; - - public void setMenuEntry(MenuEntry e) + public void setMenuEntry(MenuEntry entry) { - setOption(e.getOption()); - setTarget(e.getTarget()); - setIdentifier(e.getIdentifier()); - setOpcode(e.getOpcode()); - setActionParam(e.getActionParam()); - setActionParam1(e.getActionParam1()); - setForceLeftClick(e.isForceLeftClick()); - } - - public int getWidgetId() - { - return getActionParam1(); - } - - public String getMenuTarget() - { - return getTarget(); - } - - public String getMenuOption() - { - return getOption(); + this.setMenuOption(entry.getOption()); + this.setMenuTarget(entry.getTarget()); + this.setId(entry.getId()); + this.setMenuAction(MenuAction.of(entry.getOpcode())); + this.setActionParam(entry.getActionParam()); + this.setWidgetId(entry.getActionParam1()); } } diff --git a/runelite-api/src/main/java/net/runelite/api/events/MenuShouldLeftClick.java b/runelite-api/src/main/java/net/runelite/api/events/MenuShouldLeftClick.java index 9652721791..c36372ff2c 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/MenuShouldLeftClick.java +++ b/runelite-api/src/main/java/net/runelite/api/events/MenuShouldLeftClick.java @@ -31,7 +31,7 @@ import lombok.Data; * opened on left click. */ @Data -public class MenuShouldLeftClick implements Event +public class MenuShouldLeftClick { /** * If set to true, the menu will open on left click. diff --git a/runelite-api/src/main/java/net/runelite/api/events/NameableNameChanged.java b/runelite-api/src/main/java/net/runelite/api/events/NameableNameChanged.java index fcf0556e71..18b106ec9f 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/NameableNameChanged.java +++ b/runelite-api/src/main/java/net/runelite/api/events/NameableNameChanged.java @@ -31,7 +31,7 @@ import lombok.Value; * An event where a {@link Nameable} has had their name changed. */ @Value -public class NameableNameChanged implements Event +public class NameableNameChanged { /** * The nameable that changed names. diff --git a/runelite-api/src/main/java/net/runelite/api/events/NpcActionChanged.java b/runelite-api/src/main/java/net/runelite/api/events/NpcActionChanged.java index 20f831e328..7539821167 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/NpcActionChanged.java +++ b/runelite-api/src/main/java/net/runelite/api/events/NpcActionChanged.java @@ -31,7 +31,7 @@ import net.runelite.api.NPCComposition; * An event where an action of an {@link NPCComposition} has changed. */ @Data -public class NpcActionChanged implements Event +public class NpcActionChanged { /** * The NPC composition that has been changed. diff --git a/runelite-api/src/main/java/net/runelite/api/events/NpcChanged.java b/runelite-api/src/main/java/net/runelite/api/events/NpcChanged.java index 606ebcbb7e..f01da68ae2 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/NpcChanged.java +++ b/runelite-api/src/main/java/net/runelite/api/events/NpcChanged.java @@ -32,7 +32,7 @@ import net.runelite.api.NPCComposition; * Fires after the composition of an {@link NPC} changes. */ @Value -public class NpcChanged implements Event +public class NpcChanged { /** * The NPC of which the composition changed. diff --git a/runelite-api/src/main/java/net/runelite/api/events/NpcDespawned.java b/runelite-api/src/main/java/net/runelite/api/events/NpcDespawned.java index 6b7bd48b29..9d2fed4200 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/NpcDespawned.java +++ b/runelite-api/src/main/java/net/runelite/api/events/NpcDespawned.java @@ -32,7 +32,7 @@ import lombok.Value; * An event where an {@link NPC} has despawned. */ @Value -public class NpcDespawned implements Event +public class NpcDespawned { /** * The despawned NPC. diff --git a/runelite-api/src/main/java/net/runelite/api/events/NpcSpawned.java b/runelite-api/src/main/java/net/runelite/api/events/NpcSpawned.java index 0bb3c3f3cb..aab89fffb8 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/NpcSpawned.java +++ b/runelite-api/src/main/java/net/runelite/api/events/NpcSpawned.java @@ -32,7 +32,7 @@ import lombok.Value; * An event where an {@link NPC} has spawned. */ @Value -public class NpcSpawned implements Event +public class NpcSpawned { /** * The spawned NPC. diff --git a/runelite-api/src/main/java/net/runelite/api/events/OverheadPrayerChanged.java b/runelite-api/src/main/java/net/runelite/api/events/OverheadPrayerChanged.java new file mode 100644 index 0000000000..46bf0f4a5c --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/events/OverheadPrayerChanged.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021, ThatGamerBlue + * 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.api.events; + +import lombok.Data; +import net.runelite.api.HeadIcon; +import net.runelite.api.Player; + +@Data +public class OverheadPrayerChanged +{ + private final Player player; + + private final HeadIcon oldHeadIcon; + + private final HeadIcon newHeadIcon; +} diff --git a/runelite-api/src/main/java/net/runelite/api/events/OverheadTextChanged.java b/runelite-api/src/main/java/net/runelite/api/events/OverheadTextChanged.java index 78df69b9de..9e77178776 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/OverheadTextChanged.java +++ b/runelite-api/src/main/java/net/runelite/api/events/OverheadTextChanged.java @@ -4,7 +4,7 @@ import net.runelite.api.Actor; import lombok.Value; @Value -public class OverheadTextChanged implements Event +public class OverheadTextChanged { Actor actor; diff --git a/runelite-api/src/main/java/net/runelite/api/events/PlayerChanged.java b/runelite-api/src/main/java/net/runelite/api/events/PlayerChanged.java index befdc13733..c29f30dc1d 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/PlayerChanged.java +++ b/runelite-api/src/main/java/net/runelite/api/events/PlayerChanged.java @@ -1,14 +1,34 @@ +/* + * Copyright (c) 2020 Abex + * 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.api.events; import lombok.Value; import net.runelite.api.Player; -import net.runelite.api.PlayerComposition; -/** - * This will fire whenever the {@link PlayerComposition} hash changes. - */ @Value -public class PlayerChanged implements Event +public class PlayerChanged { - Player player; + private final Player player; } diff --git a/runelite-api/src/main/java/net/runelite/api/events/PlayerDespawned.java b/runelite-api/src/main/java/net/runelite/api/events/PlayerDespawned.java index 0970c08e9b..ed5f2a9057 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/PlayerDespawned.java +++ b/runelite-api/src/main/java/net/runelite/api/events/PlayerDespawned.java @@ -34,7 +34,7 @@ import lombok.Value; * Note: This event does not get called for the local player. */ @Value -public class PlayerDespawned implements Event +public class PlayerDespawned { /** * The despawned player. diff --git a/runelite-api/src/main/java/net/runelite/api/events/PlayerMenuOptionClicked.java b/runelite-api/src/main/java/net/runelite/api/events/PlayerMenuOptionClicked.java index 14a85b6025..dcfb0421ca 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/PlayerMenuOptionClicked.java +++ b/runelite-api/src/main/java/net/runelite/api/events/PlayerMenuOptionClicked.java @@ -31,7 +31,7 @@ import lombok.Data; * been clicked (ie. HiScore Lookup). */ @Data -public class PlayerMenuOptionClicked implements Event +public class PlayerMenuOptionClicked { /** * The menu option clicked. diff --git a/runelite-api/src/main/java/net/runelite/api/events/PlayerMenuOptionsChanged.java b/runelite-api/src/main/java/net/runelite/api/events/PlayerMenuOptionsChanged.java index a75af8acf3..d33aa4d06c 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/PlayerMenuOptionsChanged.java +++ b/runelite-api/src/main/java/net/runelite/api/events/PlayerMenuOptionsChanged.java @@ -27,7 +27,7 @@ package net.runelite.api.events; import lombok.Data; @Data -public class PlayerMenuOptionsChanged implements Event +public class PlayerMenuOptionsChanged { /** * Index in playerOptions which changed. diff --git a/runelite-api/src/main/java/net/runelite/api/events/PlayerSkullChanged.java b/runelite-api/src/main/java/net/runelite/api/events/PlayerSkullChanged.java new file mode 100644 index 0000000000..931c415ed1 --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/events/PlayerSkullChanged.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021, ThatGamerBlue + * 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.api.events; + +import lombok.Data; +import net.runelite.api.Player; +import net.runelite.api.SkullIcon; + +@Data +public class PlayerSkullChanged +{ + private final Player player; + + private final SkullIcon oldSkullIcon; + + private final SkullIcon newSkullIcon; +} diff --git a/runelite-api/src/main/java/net/runelite/api/events/PlayerSpawned.java b/runelite-api/src/main/java/net/runelite/api/events/PlayerSpawned.java index 9ba53bbc4f..73e1932285 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/PlayerSpawned.java +++ b/runelite-api/src/main/java/net/runelite/api/events/PlayerSpawned.java @@ -32,7 +32,7 @@ import lombok.Value; * An event where a {@link Player} has spawned. */ @Value -public class PlayerSpawned implements Event +public class PlayerSpawned { /** * The spawned player. diff --git a/runelite-api/src/main/java/net/runelite/api/events/PostHealthBar.java b/runelite-api/src/main/java/net/runelite/api/events/PostHealthBar.java index 1f327ec13a..c8896ff945 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/PostHealthBar.java +++ b/runelite-api/src/main/java/net/runelite/api/events/PostHealthBar.java @@ -28,7 +28,7 @@ import net.runelite.api.HealthBar; import lombok.Data; @Data -public class PostHealthBar implements Event +public class PostHealthBar { private HealthBar healthBar; } diff --git a/runelite-api/src/main/java/net/runelite/api/events/PostItemComposition.java b/runelite-api/src/main/java/net/runelite/api/events/PostItemComposition.java index 14ec4d197c..1e9000cfd1 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/PostItemComposition.java +++ b/runelite-api/src/main/java/net/runelite/api/events/PostItemComposition.java @@ -32,7 +32,7 @@ import net.runelite.api.ItemComposition; * its data is initialized. */ @Data -public class PostItemComposition implements Event +public class PostItemComposition { /** * The newly created item. diff --git a/runelite-api/src/main/java/net/runelite/api/events/PostStructComposition.java b/runelite-api/src/main/java/net/runelite/api/events/PostStructComposition.java index 1d947572a6..82238e94fd 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/PostStructComposition.java +++ b/runelite-api/src/main/java/net/runelite/api/events/PostStructComposition.java @@ -38,4 +38,4 @@ public class PostStructComposition * The newly created struct. */ private StructComposition structComposition; -} \ No newline at end of file +} diff --git a/runelite-api/src/main/java/net/runelite/api/events/ProjectileMoved.java b/runelite-api/src/main/java/net/runelite/api/events/ProjectileMoved.java index 82590778be..70d73d7026 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/ProjectileMoved.java +++ b/runelite-api/src/main/java/net/runelite/api/events/ProjectileMoved.java @@ -35,7 +35,7 @@ import lombok.Data; * once (ie. AoE from Lizardman Shaman). */ @Data -public class ProjectileMoved implements Event +public class ProjectileMoved { /** * The projectile being moved. diff --git a/runelite-api/src/main/java/net/runelite/api/events/ProjectileSpawned.java b/runelite-api/src/main/java/net/runelite/api/events/ProjectileSpawned.java index 7c11ea215f..7b7bda43ad 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/ProjectileSpawned.java +++ b/runelite-api/src/main/java/net/runelite/api/events/ProjectileSpawned.java @@ -32,7 +32,7 @@ import lombok.Data; * An event called whenever a {@link Projectile} has spawned. */ @Data -public class ProjectileSpawned implements Event +public class ProjectileSpawned { /** * The spawned projectile. diff --git a/runelite-api/src/main/java/net/runelite/api/events/ResizeableChanged.java b/runelite-api/src/main/java/net/runelite/api/events/ResizeableChanged.java index ecc5c0d380..146f92ac38 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/ResizeableChanged.java +++ b/runelite-api/src/main/java/net/runelite/api/events/ResizeableChanged.java @@ -32,7 +32,7 @@ import lombok.Data; * An event where the game has changed from fixed to resizable mode or vice versa. */ @Data -public class ResizeableChanged implements Event +public class ResizeableChanged { /** * Whether the game is in resizable mode. diff --git a/runelite-api/src/main/java/net/runelite/api/events/ScriptCallbackEvent.java b/runelite-api/src/main/java/net/runelite/api/events/ScriptCallbackEvent.java index 6461cad9e7..716f7bbe90 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/ScriptCallbackEvent.java +++ b/runelite-api/src/main/java/net/runelite/api/events/ScriptCallbackEvent.java @@ -31,7 +31,7 @@ import lombok.Data; * A callback from a runelite_callback opcode in a cs2 */ @Data -public class ScriptCallbackEvent implements Event +public class ScriptCallbackEvent { /** * The script that is currently being executed diff --git a/runelite-api/src/main/java/net/runelite/api/events/ScriptPostFired.java b/runelite-api/src/main/java/net/runelite/api/events/ScriptPostFired.java index 75677640c1..55338bd87a 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/ScriptPostFired.java +++ b/runelite-api/src/main/java/net/runelite/api/events/ScriptPostFired.java @@ -30,7 +30,7 @@ import lombok.Value; * An event that is fired after the designated script is ran */ @Value -public class ScriptPostFired implements Event +public class ScriptPostFired { /** * The script id of the invoked script diff --git a/runelite-api/src/main/java/net/runelite/api/events/ScriptPreFired.java b/runelite-api/src/main/java/net/runelite/api/events/ScriptPreFired.java index 55c58ac4a3..f8e9549281 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/ScriptPreFired.java +++ b/runelite-api/src/main/java/net/runelite/api/events/ScriptPreFired.java @@ -31,7 +31,7 @@ import net.runelite.api.ScriptEvent; * An event that is fired before the designated script is ran */ @Value -public class ScriptPreFired implements Event +public class ScriptPreFired { /** * The script id of the invoked script diff --git a/runelite-api/src/main/java/net/runelite/api/events/SoundEffectPlayed.java b/runelite-api/src/main/java/net/runelite/api/events/SoundEffectPlayed.java index b2edb71708..7c111d1d8d 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/SoundEffectPlayed.java +++ b/runelite-api/src/main/java/net/runelite/api/events/SoundEffectPlayed.java @@ -29,7 +29,7 @@ import lombok.Data; import net.runelite.api.Actor; @Data -public class SoundEffectPlayed implements Event +public class SoundEffectPlayed { @Nullable private final Actor source; diff --git a/runelite-api/src/main/java/net/runelite/api/events/StatChanged.java b/runelite-api/src/main/java/net/runelite/api/events/StatChanged.java index b329e9dbbc..809636f446 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/StatChanged.java +++ b/runelite-api/src/main/java/net/runelite/api/events/StatChanged.java @@ -31,7 +31,7 @@ import net.runelite.api.Skill; * An event where the experience, level, or boosted level of a {@link Skill} has been modified. */ @Value -public class StatChanged implements Event +public class StatChanged { Skill skill; int xp; diff --git a/runelite-api/src/main/java/net/runelite/api/events/UsernameChanged.java b/runelite-api/src/main/java/net/runelite/api/events/UsernameChanged.java index 802df61b63..3dea001150 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/UsernameChanged.java +++ b/runelite-api/src/main/java/net/runelite/api/events/UsernameChanged.java @@ -30,7 +30,7 @@ package net.runelite.api.events; * This event triggers for every character change to the username * in the login screen. */ -public class UsernameChanged implements Event +public class UsernameChanged { public static final UsernameChanged INSTANCE = new UsernameChanged(); diff --git a/runelite-api/src/main/java/net/runelite/api/events/VarClientIntChanged.java b/runelite-api/src/main/java/net/runelite/api/events/VarClientIntChanged.java index adc2be50e1..521e8a62ae 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/VarClientIntChanged.java +++ b/runelite-api/src/main/java/net/runelite/api/events/VarClientIntChanged.java @@ -32,7 +32,7 @@ import lombok.Value; * @see net.runelite.api.VarClientInt */ @Value -public class VarClientIntChanged implements Event +public class VarClientIntChanged { int index; } diff --git a/runelite-api/src/main/java/net/runelite/api/events/VarClientStrChanged.java b/runelite-api/src/main/java/net/runelite/api/events/VarClientStrChanged.java index c63e088470..2fff4da47e 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/VarClientStrChanged.java +++ b/runelite-api/src/main/java/net/runelite/api/events/VarClientStrChanged.java @@ -32,7 +32,7 @@ import lombok.Value; * @see net.runelite.api.VarClientStr */ @Value -public class VarClientStrChanged implements Event +public class VarClientStrChanged { int index; } diff --git a/runelite-api/src/main/java/net/runelite/api/events/VarbitChanged.java b/runelite-api/src/main/java/net/runelite/api/events/VarbitChanged.java index 945222c072..fbac6d5e01 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/VarbitChanged.java +++ b/runelite-api/src/main/java/net/runelite/api/events/VarbitChanged.java @@ -37,7 +37,7 @@ import lombok.Data; * if the VarPlayer has special engine behavior assigned to it. */ @Data -public class VarbitChanged implements Event +public class VarbitChanged { /** * Index in the varp array that was changed. diff --git a/runelite-api/src/main/java/net/runelite/api/events/VolumeChanged.java b/runelite-api/src/main/java/net/runelite/api/events/VolumeChanged.java index 38701712c3..30e87b9c79 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/VolumeChanged.java +++ b/runelite-api/src/main/java/net/runelite/api/events/VolumeChanged.java @@ -28,7 +28,7 @@ package net.runelite.api.events; import lombok.Value; @Value -public class VolumeChanged implements Event +public class VolumeChanged { public enum Type { diff --git a/runelite-api/src/main/java/net/runelite/api/events/WallObjectChanged.java b/runelite-api/src/main/java/net/runelite/api/events/WallObjectChanged.java index 6cf5fd8f25..bea7686602 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/WallObjectChanged.java +++ b/runelite-api/src/main/java/net/runelite/api/events/WallObjectChanged.java @@ -32,7 +32,7 @@ import lombok.Data; * An event where the {@link WallObject} of a {@link Tile} has been changed. */ @Data -public class WallObjectChanged implements Event +public class WallObjectChanged { /** * The affected tile. diff --git a/runelite-api/src/main/java/net/runelite/api/events/WallObjectDespawned.java b/runelite-api/src/main/java/net/runelite/api/events/WallObjectDespawned.java index 8a510a7bae..6ac609a46f 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/WallObjectDespawned.java +++ b/runelite-api/src/main/java/net/runelite/api/events/WallObjectDespawned.java @@ -32,7 +32,7 @@ import lombok.Data; * An event where a {@link WallObject} on a {@link Tile} has been removed. */ @Data -public class WallObjectDespawned implements Event +public class WallObjectDespawned { /** * The affected tile. diff --git a/runelite-api/src/main/java/net/runelite/api/events/WallObjectSpawned.java b/runelite-api/src/main/java/net/runelite/api/events/WallObjectSpawned.java index a1da8542a4..dc22e07f7d 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/WallObjectSpawned.java +++ b/runelite-api/src/main/java/net/runelite/api/events/WallObjectSpawned.java @@ -32,7 +32,7 @@ import lombok.Data; * An event where a {@link WallObject} is added to a {@link Tile}. */ @Data -public class WallObjectSpawned implements Event +public class WallObjectSpawned { /** * The affected tile. diff --git a/runelite-api/src/main/java/net/runelite/api/events/WidgetClosed.java b/runelite-api/src/main/java/net/runelite/api/events/WidgetClosed.java index 218fc9ba70..42193b445f 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/WidgetClosed.java +++ b/runelite-api/src/main/java/net/runelite/api/events/WidgetClosed.java @@ -46,4 +46,4 @@ public class WidgetClosed * If the interface will be unloaded or if it will be immediately reloaded */ private final boolean unload; -} \ No newline at end of file +} diff --git a/runelite-api/src/main/java/net/runelite/api/events/WidgetHiddenChanged.java b/runelite-api/src/main/java/net/runelite/api/events/WidgetHiddenChanged.java new file mode 100644 index 0000000000..705202468e --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/events/WidgetHiddenChanged.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2018, Adam + * 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.api.events; + +import net.runelite.api.widgets.Widget; +import lombok.Data; + +/** + * An event where the hidden state of a {@link Widget} has been modified. + */ +@Data +public class WidgetHiddenChanged +{ + /** + * The affected widget. + */ + private Widget widget; + /** + * The new hidden state of the widget. + */ + private boolean hidden; +} \ No newline at end of file diff --git a/runelite-api/src/main/java/net/runelite/api/events/WidgetLoaded.java b/runelite-api/src/main/java/net/runelite/api/events/WidgetLoaded.java index 5f337603d1..c71bc41634 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/WidgetLoaded.java +++ b/runelite-api/src/main/java/net/runelite/api/events/WidgetLoaded.java @@ -30,7 +30,7 @@ import lombok.Data; * An event where a {@link net.runelite.api.widgets.Widget} has been loaded. */ @Data -public class WidgetLoaded implements Event +public class WidgetLoaded { /** * The group ID of the loaded widget. diff --git a/runelite-api/src/main/java/net/runelite/api/events/WidgetMenuOptionClicked.java b/runelite-api/src/main/java/net/runelite/api/events/WidgetMenuOptionClicked.java index 492767d832..c0e3596085 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/WidgetMenuOptionClicked.java +++ b/runelite-api/src/main/java/net/runelite/api/events/WidgetMenuOptionClicked.java @@ -31,7 +31,7 @@ import lombok.Data; * A MenuManager widget menu was clicked. This event is NOT fired for non-MenuManager menu options */ @Data -public class WidgetMenuOptionClicked implements Event +public class WidgetMenuOptionClicked { /** * The clicked menu option. diff --git a/runelite-api/src/main/java/net/runelite/api/events/WidgetPositioned.java b/runelite-api/src/main/java/net/runelite/api/events/WidgetPositioned.java index 4835db0aa4..6f58e9fe07 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/WidgetPositioned.java +++ b/runelite-api/src/main/java/net/runelite/api/events/WidgetPositioned.java @@ -28,7 +28,7 @@ package net.runelite.api.events; * An event where the position of a {@link net.runelite.api.widgets.Widget} * relative to its parent has changed. */ -public class WidgetPositioned implements Event +public class WidgetPositioned { public static final WidgetPositioned INSTANCE = new WidgetPositioned(); diff --git a/runelite-api/src/main/java/net/runelite/api/events/WidgetPressed.java b/runelite-api/src/main/java/net/runelite/api/events/WidgetPressed.java index b7fd18af4c..cabceb377b 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/WidgetPressed.java +++ b/runelite-api/src/main/java/net/runelite/api/events/WidgetPressed.java @@ -31,7 +31,7 @@ import lombok.Data; * An event where a draggable widget has been pressed. */ @Data -public class WidgetPressed implements Event +public class WidgetPressed { public static final WidgetPressed INSTANCE = new WidgetPressed(); diff --git a/runelite-api/src/main/java/net/runelite/api/events/WorldChanged.java b/runelite-api/src/main/java/net/runelite/api/events/WorldChanged.java index 8976298faf..3b641e27e6 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/WorldChanged.java +++ b/runelite-api/src/main/java/net/runelite/api/events/WorldChanged.java @@ -27,7 +27,7 @@ package net.runelite.api.events; import net.runelite.api.Client; /** - * Posted when the game world the client wants to connect to has changed + * Posted when the game world the client wants to connect to has changed. * This is posted after the world ID and type have updated, but before a new * connection is established * diff --git a/runelite-api/src/main/java/net/runelite/api/events/WorldListLoad.java b/runelite-api/src/main/java/net/runelite/api/events/WorldListLoad.java index ab0d05e5c1..c45f4cf1ae 100644 --- a/runelite-api/src/main/java/net/runelite/api/events/WorldListLoad.java +++ b/runelite-api/src/main/java/net/runelite/api/events/WorldListLoad.java @@ -31,7 +31,7 @@ import lombok.Value; * Event when the world list is loaded for the world switcher */ @Value -public class WorldListLoad implements Event +public class WorldListLoad { World[] worlds; } diff --git a/runelite-api/src/main/java/net/runelite/api/events/player/headicon/OverheadPrayerChanged.java b/runelite-api/src/main/java/net/runelite/api/events/player/headicon/OverheadPrayerChanged.java deleted file mode 100644 index 687a17f6dd..0000000000 --- a/runelite-api/src/main/java/net/runelite/api/events/player/headicon/OverheadPrayerChanged.java +++ /dev/null @@ -1,17 +0,0 @@ -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; - -} diff --git a/runelite-api/src/main/java/net/runelite/api/events/player/headicon/PlayerSkullChanged.java b/runelite-api/src/main/java/net/runelite/api/events/player/headicon/PlayerSkullChanged.java deleted file mode 100644 index b66c558888..0000000000 --- a/runelite-api/src/main/java/net/runelite/api/events/player/headicon/PlayerSkullChanged.java +++ /dev/null @@ -1,17 +0,0 @@ -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; - -} diff --git a/runelite-api/src/main/java/net/runelite/api/kit/KitType.java b/runelite-api/src/main/java/net/runelite/api/kit/KitType.java index f10e0e3280..82c6781949 100644 --- a/runelite-api/src/main/java/net/runelite/api/kit/KitType.java +++ b/runelite-api/src/main/java/net/runelite/api/kit/KitType.java @@ -26,7 +26,6 @@ package net.runelite.api.kit; import lombok.AllArgsConstructor; import lombok.Getter; -import net.runelite.api.widgets.WidgetInfo; /** * Represents an equipment slot in a players composition. @@ -40,26 +39,30 @@ import net.runelite.api.widgets.WidgetInfo; @AllArgsConstructor public enum KitType { - HEAD("Head", 0, WidgetInfo.EQUIPMENT_HELMET), - CAPE("Cape", 1, WidgetInfo.EQUIPMENT_CAPE), - AMULET("Amulet", 2, WidgetInfo.EQUIPMENT_AMULET), - WEAPON("Weapon", 3, WidgetInfo.EQUIPMENT_WEAPON), - TORSO("Torso", 4, WidgetInfo.EQUIPMENT_BODY), - SHIELD("Shield", 5, WidgetInfo.EQUIPMENT_SHIELD), - LEGS("Legs", 7, WidgetInfo.EQUIPMENT_LEGS), - HAIR("Hair", 8, null), - HANDS("Hands", 9, WidgetInfo.EQUIPMENT_GLOVES), - BOOTS("Boots", 10, WidgetInfo.EQUIPMENT_BOOTS), - JAW("Jaw", 11, null), - RING("Ring", 12, WidgetInfo.EQUIPMENT_RING), - AMMUNITION("Ammo", 13, WidgetInfo.EQUIPMENT_AMMO); + HEAD("Head"), + CAPE("Cape"), + AMULET("Amulet"), + WEAPON("Weapon"), + TORSO("Torso"), + SHIELD("Shield"), + ARMS("Arms"), + LEGS("Legs"), + HAIR("Hair"), + HANDS("Hands"), + BOOTS("Boots"), + JAW("Jaw"), + RING("Ring"), + AMMUNITION("Ammo"); private final String name; /** - * Gets the raw equipment index for use in {PlayerAppearance#getEquipmentIds()}. + * Gets the raw equipment index for use in {@link net.runelite.api.PlayerComposition#getEquipmentIds()}. + * + * @return raw equipment index */ - private final int index; - - private final WidgetInfo widgetInfo; + public int getIndex() + { + return ordinal(); + } } \ No newline at end of file diff --git a/runelite-api/src/main/java/net/runelite/api/queries/ShopItemQuery.java b/runelite-api/src/main/java/net/runelite/api/queries/ShopItemQuery.java index a768df8928..0bd789fbac 100644 --- a/runelite-api/src/main/java/net/runelite/api/queries/ShopItemQuery.java +++ b/runelite-api/src/main/java/net/runelite/api/queries/ShopItemQuery.java @@ -32,7 +32,6 @@ import java.util.stream.Collectors; import net.runelite.api.Client; import net.runelite.api.QueryResults; import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetInfo; import net.runelite.api.widgets.WidgetItem; public class ShopItemQuery extends WidgetItemQuery @@ -50,7 +49,7 @@ public class ShopItemQuery extends WidgetItemQuery private Collection getShopItems(Client client) { Collection widgetItems = new ArrayList<>(); - Widget shop = client.getWidget(WidgetInfo.SHOP_ITEMS_CONTAINER); + Widget shop = client.getWidget(300, 2); if (shop != null && !shop.isHidden()) { Widget[] children = shop.getDynamicChildren(); diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java b/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java index 5e35a8cccf..1a40856ad1 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java @@ -25,7 +25,7 @@ package net.runelite.api.widgets; import java.awt.Rectangle; -import java.util.List; +import java.util.Collection; import net.runelite.api.FontTypeFace; import net.runelite.api.Point; import net.runelite.api.SpritePixels; @@ -68,12 +68,6 @@ public interface Widget */ void setType(int type); - int getButtonType(); - - boolean isWidgetItemDragged(int index); - - Point getWidgetItemDragOffsets(); - /** * Gets the type of content displayed by the widget. */ @@ -185,18 +179,6 @@ public interface Widget @Deprecated void setRelativeY(int y); - String getSpellName(); - - /** - * You probably want {@link Widget#getText()} instead - */ - String getRSButtonText(); - - /** - * You probably want {@link Widget#getText()} instead - */ - String getButtonText(); - /** * Gets the text displayed on this widget. * @@ -253,12 +235,6 @@ public interface Widget */ String getName(); - /** - * Gets the internal field returned by getName unfiltered - * @return the unfiltered name - */ - String getRSName(); - /** * Sets the name of the widget. * @@ -266,11 +242,114 @@ public interface Widget */ void setName(String name); + /** + * Gets the Model/NPC/Item ID displayed in the widget. + * + * @see WidgetModelType + */ + int getModelId(); + + /** + * Sets the Model/NPC/Item ID displayed in the widget. + * + * @see WidgetModelType + */ + void setModelId(int id); + + /** + * Gets the model type of the widget. + * + * @see WidgetModelType + */ + int getModelType(); + + /** + * Sets the model type of the widget. + * + * @param type the new model type + * @see WidgetModelType + */ + void setModelType(int type); + + /** + * Gets the sequence ID used to animate the model in the widget + * + * @see net.runelite.api.AnimationID + */ + int getAnimationId(); + + /** + * Sets the sequence ID used to animate the model in the widget + * + * @see net.runelite.api.AnimationID + */ + void setAnimationId(int animationId); + + /** + * Gets the x rotation of the model displayed in the widget. + * 0 = no rotation, 2047 = full rotation + */ + int getRotationX(); + + /** + * Sets the x rotation of the model displayed in the widget. + *
+ * Note: Setting this value outside of the input range defined by {@link Widget#getRotationX()} will cause a client + * crash. + * + * @param modelX the new model x rotation value + */ + void setRotationX(int modelX); + + /** + * Gets the y rotation of the model displayed in the widget. + * 0 = no rotation, 2047 = full rotation + */ + int getRotationY(); + + /** + * Sets the y rotation of the model displayed in the widget. + *
+ * Note: Setting this value outside of the input range defined by {@link Widget#getRotationY()} will cause a client + * crash. + * + * @param modelY the new model y rotation value + */ + void setRotationY(int modelY); + + /** + * Gets the z rotation of the model displayed in the widget. + * 0 = no rotation, 2047 = full rotation + */ + int getRotationZ(); + + /** + * Sets the z rotation of the model displayed in the widget. + *
+ * Note: Setting this value outside of the input range defined by {@link Widget#getRotationZ()} will cause a client + * crash. + * + * @param modelZ the new model z rotation value + */ + void setRotationZ(int modelZ); + + /** + * Gets the amount zoomed in on the model displayed in the widget. + */ + int getModelZoom(); + + /** + * Sets the amount zoomed in on the model displayed in the widget. + * + * @param modelZoom the new model zoom value + */ + void setModelZoom(int modelZoom); + /** * Gets the sprite ID displayed in the widget. * * @return the sprite ID - * SpriteID + * @see net.runelite.api.SpriteID */ int getSpriteId(); @@ -288,7 +367,7 @@ public interface Widget * Sets the sprite ID displayed in the widget. * * @param spriteId the sprite ID - * SpriteID + * @see net.runelite.api.SpriteID */ void setSpriteId(int spriteId); @@ -321,105 +400,6 @@ public interface Widget */ int getIndex(); - /** - * Gets the Model/NPC/Item ID displayed in the widget. - * - * @see WidgetModelType - */ - int getModelId(); - - /** - * Sets the Model/NPC/Item ID displayed in the widget. - * - * @see WidgetModelType - */ - void setModelId(int id); - - /** - * Gets the model type of the widget. - * - * @see WidgetModelType - */ - int getModelType(); - - /** - * Sets the model type of the widget. - * - * @param type the new model type - * @see WidgetModelType - */ - void setModelType(int type); - - /** - * Gets the sequence ID used to animate the model in the widget - * - * @see net.runelite.api.AnimationID - */ - int getAnimationId(); - - /** - * Sets the sequence ID used to animate the model in the widget - * - * @see net.runelite.api.AnimationID - */ - void setAnimationId(int animationId); - - /** - * Gets the x rotation of the model displayed in the widget - * - * @return the x rotation - */ - int getRotationX(); - - /** - * Sets the x rotation of the model displayed in the widget - * - * @param rotationX 0 = no rotation, 2047 = full rotation, outside range = crash - */ - void setRotationX(int rotationX); - - /** - * Gets the y rotation of the model displayed in the widget - * - * @return the y rotation - */ - int getRotationY(); - - /** - * Sets the y rotation of the model displayed in the widget - * - * @param rotationY 0 = no rotation, 2047 = full rotation, outside range = crash - */ - void setRotationY(int rotationY); - - /** - * Gets the z rotation of the model displayed in the widget - * - * @return the z rotation - */ - int getRotationZ(); - - /** - * Sets the z rotation of the model displayed in the widget - * - * @param rotationZ 0 = no rotation, 2047 = full rotation, outside range = crash - */ - void setRotationZ(int rotationZ); - - /** - * Gets the amount zoomed in on the model displayed in the widget - * - * @return the amount zoomed in - */ - int getModelZoom(); - - /** - * Sets the amount zoomed in on the model displayed in the widget - * - * @param modelZoom the new zoom amount - */ - void setModelZoom(int modelZoom); - /** * Gets the location the widget is being drawn on the canvas. *

@@ -433,7 +413,7 @@ public interface Widget /** * Gets the width of the widget. *

- * If this widget is storing any {@link // WidgetItem}s, this value is + * If this widget is storing any {@link WidgetItem}s, this value is * used to store the number of item slot columns. * * @return the width @@ -479,7 +459,7 @@ public interface Widget * * @return any items displayed, or null if there are no items */ - List getWidgetItems(); + Collection getWidgetItems(); /** * Gets a widget item at a specific index. @@ -629,8 +609,6 @@ public interface Widget */ String[] getActions(); - String[] getItemActions(); - /** * Creates a dynamic widget child * @@ -762,6 +740,11 @@ public interface Widget */ Object[] getOnLoadListener(); + /** + * Gets the script and arguments to be ran when one of the listened for inventories changes. + * + * @return + */ Object[] getOnInvTransmitListener(); /** @@ -964,36 +947,6 @@ public interface Widget */ void setNoScrollThrough(boolean noScrollThrough); - /** - * Changes the parent ID for the widget - */ - void setParentId(int id); - - /** - * Changes the ID of the widget - */ - void setId(int id); - - /** - * Sets the index of this element - */ - void setIndex(int index); - - /** - * Seems like this needs to set to true when creating new widgets - */ - void setIsIf3(boolean isIf3); - - /** - * Returns yes if your mouse pointer is over this widget or any of it's children. - */ - boolean containsMouse(); - - /** - * Gets the image which is (or should be) drawn on this widget - */ - SpritePixels getSprite(); - /** * {@link net.runelite.api.VarPlayer}s that triggers this widgets varTransmitListener */ @@ -1051,4 +1004,62 @@ public interface Widget * @param args A ScriptID, then the args for the script */ void setOnVarTransmitListener(Object ...args); -} \ No newline at end of file + + //////////////////////////////////// OPRS + + int getButtonType(); + + boolean isWidgetItemDragged(int index); + + Point getWidgetItemDragOffsets(); + + String getSpellName(); + + /** + * You probably want {@link Widget#getText()} instead + */ + String getRSButtonText(); + + /** + * You probably want {@link Widget#getText()} instead + */ + String getButtonText(); + + /** + * Gets the internal field returned by getName unfiltered + * @return the unfiltered name + */ + String getRSName(); + + String[] getItemActions(); + + /** + * Changes the parent ID for the widget + */ + void setParentId(int id); + + /** + * Changes the ID of the widget + */ + void setId(int id); + + /** + * Sets the index of this element + */ + void setIndex(int index); + + /** + * Seems like this needs to set to true when creating new widgets + */ + void setIsIf3(boolean isIf3); + + /** + * Returns yes if your mouse pointer is over this widget or any of it's children. + */ + boolean containsMouse(); + + /** + * Gets the image which is (or should be) drawn on this widget + */ + SpritePixels getSprite(); +} diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java index a7fcb7f709..fed35c6c11 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java @@ -41,12 +41,10 @@ public class WidgetID public static final int LOGOUT_PANEL_ID = 182; public static final int BANK_GROUP_ID = 12; public static final int BANK_INVENTORY_GROUP_ID = 15; - public static final int BANK_PIN_GROUP_ID = 213; public static final int GRAND_EXCHANGE_INVENTORY_GROUP_ID = 467; public static final int GRAND_EXCHANGE_GROUP_ID = 465; public static final int DEPOSIT_BOX_GROUP_ID = 192; public static final int INVENTORY_GROUP_ID = 149; - public static final int PLAYER_TRADE_CONFIRM_GROUP_ID = 334; public static final int PLAYER_TRADE_SCREEN_GROUP_ID = 335; public static final int PLAYER_TRADE_INVENTORY_GROUP_ID = 336; public static final int FRIENDS_LIST_GROUP_ID = 429; @@ -59,8 +57,6 @@ public class WidgetID public static final int ACHIEVEMENT_DIARY_GROUP_ID = 259; public static final int PEST_CONTROL_BOAT_GROUP_ID = 407; public static final int PEST_CONTROL_GROUP_ID = 408; - public static final int PEST_CONTROL_EXCHANGE_WINDOW_GROUP_ID = 243; - public static final int DIALOG_MINIGAME_GROUP_ID = 229; public static final int FRIENDS_CHAT_GROUP_ID = 7; public static final int MINIMAP_GROUP_ID = 160; public static final int LOGIN_CLICK_TO_PLAY_GROUP_ID = 378; @@ -87,7 +83,6 @@ public class WidgetID public static final int BA_DEFENDER_GROUP_ID = 487; public static final int BA_HEALER_GROUP_ID = 488; public static final int BA_REWARD_GROUP_ID = 497; - public static final int BA_HORN_OF_GLORY = 484; public static final int LEVEL_UP_GROUP_ID = 233; public static final int DIALOG_SPRITE_GROUP_ID = 193; public static final int QUEST_COMPLETED_GROUP_ID = 153; @@ -96,7 +91,6 @@ public class WidgetID public static final int RAIDS_GROUP_ID = 513; public static final int TOB_PARTY_GROUP_ID = 28; public static final int MOTHERLODE_MINE_GROUP_ID = 382; - public static final int MOTHERLODE_MINE_FULL_INVENTORY_GROUP_ID = 229; public static final int EXPERIENCE_DROP_GROUP_ID = 122; public static final int PUZZLE_BOX_GROUP_ID = 306; public static final int LIGHT_BOX_GROUP_ID = 322; @@ -121,19 +115,15 @@ public class WidgetID public static final int VARROCK_MUSEUM_QUIZ_GROUP_ID = 533; public static final int KILL_LOGS_GROUP_ID = 549; public static final int DIARY_QUEST_GROUP_ID = 119; - public static final int THEATRE_OF_BLOOD_GROUP_ID = 28; + public static final int THEATRE_OF_BLOOD_GROUP_ID = 23; public static final int WORLD_SWITCHER_GROUP_ID = 69; - public static final int DIALOG_PLAYER_GROUP_ID = 217; public static final int DIALOG_OPTION_GROUP_ID = 219; - public static final int DIALOG_NOTIFICATION_GROUP_ID = 229; - public static final int FOSSIL_ISLAND_MUSHROOM_TELE_GROUP_ID = 608; + 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 MINIGAME_TAB_ID = 76; public static final int SPELLBOOK_GROUP_ID = 218; public static final int PVP_GROUP_ID = 90; - public static final int PERFORMERS_FOR_THE_THEATRE_GROUPS_GROUP_ID = 364; - public static final int PERFORMERS_FOR_THE_THEATRE_PLAYERS_GROUP_ID = 50; public static final int FISHING_TRAWLER_GROUP_ID = 366; public static final int FISHING_TRAWLER_REWARD_GROUP_ID = 367; public static final int ZEAH_MESS_HALL_GROUP_ID = 235; @@ -141,14 +131,10 @@ public class WidgetID public static final int LOOTING_BAG_GROUP_ID = 81; public static final int SKOTIZO_GROUP_ID = 308; public static final int ENTERING_HOUSE_GROUP_ID = 71; - public static final int FULLSCREEN_CONTAINER_TLI = 165; + public static final int FULLSCREEN_CONTAINER_TLI = 165; public static final int QUESTLIST_GROUP_ID = 399; public static final int SKILLS_GROUP_ID = 320; - public static final int DIALOG_SPRITE2_ID = 11; - public static final int EQUIPMENT_PAGE_GROUP_ID = 84; - public static final int QUESTTAB_GROUP_ID = 629; public static final int MUSIC_GROUP_ID = 239; - public static final int MUSICTAB_GROUP_ID = 239; public static final int BARROWS_PUZZLE_GROUP_ID = 25; public static final int KEPT_ON_DEATH_GROUP_ID = 4; public static final int GUIDE_PRICE_GROUP_ID = 464; @@ -161,18 +147,16 @@ public class WidgetID public static final int SEED_BOX_GROUP_ID = 128; public static final int SEED_VAULT_GROUP_ID = 631; public static final int EXPLORERS_RING_ALCH_GROUP_ID = 483; + public static final int SETTINGS_SIDE_GROUP_ID = 116; + public static final int SETTINGS_GROUP_ID = 134; + public static final int GWD_KC_GROUP_ID = 406; public static final int LMS_GROUP_ID = 333; public static final int LMS_INGAME_GROUP_ID = 328; - public static final int JEWELLERY_BOX_GROUP_ID = 590; - public static final int OPTIONS_GROUP_ID = 261; - public static final int MULTISKILL_MENU_GROUP_ID = 270; - public static final int THEATRE_OF_BLOOD_PARTY_GROUP_ID = 28; - public static final int GWD_KC_GROUP_ID = 406; public static final int ADVENTURE_LOG_ID = 187; public static final int GENERIC_SCROLL_GROUP_ID = 625; public static final int GAUNTLET_TIMER_GROUP_ID = 637; - public static final int GAUNTLET_MAP_GROUP_ID = 638; public static final int HALLOWED_SEPULCHRE_TIMER_GROUP_ID = 668; + public static final int BANK_PIN_GROUP_ID = 213; public static final int HEALTH_OVERLAY_BAR_GROUP_ID = 303; public static final int CHAMBERS_OF_XERIC_STORAGE_UNIT_PRIVATE_GROUP_ID = 271; public static final int CHAMBERS_OF_XERIC_STORAGE_UNIT_SHARED_GROUP_ID = 550; @@ -180,22 +164,20 @@ public class WidgetID public static final int DUEL_INVENTORY_GROUP_ID = 421; public static final int DUEL_INVENTORY_OTHER_GROUP_ID = 481; public static final int TRAILBLAZER_AREAS_GROUP_ID = 512; - - public static final int SETTINGS_SIDE_GROUP_ID = 116; - public static final int SETTINGS_GROUP_ID = 134; - - static class SettingsSide - { - static final int CAMERA_ZOOM_SLIDER_TRACK = 59; - static final int MUSIC_SLIDER = 13; - static final int SOUND_EFFECT_SLIDER = 17; - static final int AREA_SOUND_SLIDER = 21; - } - - static class Settings - { - static final int INIT = 1; - } + public static final int DIALOG_MINIGAME_GROUP_ID = 229; + public static final int PEST_CONTROL_EXCHANGE_WINDOW_GROUP_ID = 243; + public static final int GAUNTLET_MAP_GROUP_ID = 638; + public static final int PLAYER_TRADE_CONFIRM_GROUP_ID = 334; + public static final int OPTIONS_GROUP_ID = 261; + public static final int JEWELLERY_BOX_GROUP_ID = 590; + public static final int EQUIPMENT_PAGE_GROUP_ID = 84; + public static final int QUESTTAB_GROUP_ID = 629; + public static final int MUSICTAB_GROUP_ID = 239; + public static final int FOSSIL_ISLAND_MUSHROOM_TELE_GROUP_ID = 608; + public static final int THEATRE_OF_BLOOD_PARTY_GROUP_ID = 28; + public static final int DIALOG_NOTIFICATION_GROUP_ID = 229; + public static final int DIALOG_SPRITE2_ID = 11; + public static final int MULTISKILL_MENU_GROUP_ID = 270; static class WorldMap { @@ -220,35 +202,10 @@ public class WidgetID static final int TEXT = 4; } - - static class DialogPlayer - { - static final int HEAD_MODEL = 1; - static final int NAME = 2; - static final int CONTINUE = 3; - static final int TEXT = 4; - } - - static class DialogNotification - { - static final int TEXT = 0; - static final int CONTINUE = 1; - } - - static class DialogOption - { - static final int TEXT = 0; - static final int OPTION1 = 1; - static final int OPTION2 = 2; - static final int OPTION3 = 3; - static final int OPTION4 = 4; - static final int OPTION5 = 5; - } - static class LogoutPanel { static final int WORLD_SWITCHER_BUTTON = 3; - static final int LOGOUT_BUTTON = 8; + static final int LOGOUT_BUTTON = 6; } static class PestControlBoat @@ -260,20 +217,6 @@ public class WidgetID static final int POINTS = 6; } - static class PestControlExchangeWindow - { - static final int ITEM_LIST = 2; - static final int BOTTOM = 5; - static final int POINTS = 8; - static final int CONFIRM_BUTTON = 6; - } - - static class MinigameDialog - { - static final int TEXT = 1; - static final int CONTINUE = 2; - } - static class PestControl { static final int INFO = 3; @@ -500,11 +443,11 @@ public class WidgetID static final int RESIZABLE_VIEWPORT_BOTTOM_LINE = 14; } - static class FixedViewport + public static class FixedViewport { static final int MINIMAP = 3; static final int MINIMAP_DRAW_AREA = 8; - static final int MULTICOMBAT_INDICATOR = 21; + public static final int MULTICOMBAT_INDICATOR = 21; static final int FRIENDS_CHAT_TAB = 34; static final int FRIENDS_TAB = 36; static final int IGNORES_TAB = 35; @@ -539,9 +482,9 @@ public class WidgetID static final int INVENTORY_CONTAINER = 72; } - static class ResizableViewport + public static class ResizableViewport { - static final int MULTICOMBAT_INDICATOR = 17; + public static final int MULTICOMBAT_INDICATOR = 18; static final int FRIENDS_CHAT_TAB = 38; static final int FRIENDS_TAB = 40; static final int IGNORES_TAB = 39; @@ -574,7 +517,7 @@ public class WidgetID static final int INVENTORY_CONTAINER = 74; } - static class ResizableViewportBottomLine + public static class ResizableViewportBottomLine { static final int LOGOUT_BUTTON_OVERLAY = 32; static final int CMB_TAB = 50; @@ -589,7 +532,7 @@ public class WidgetID static final int EQUIP_ICON = 64; static final int PRAYER_TAB = 58; static final int PRAYER_ICON = 65; - static final int SPELL_TAB = 56; + public static final int SPELL_TAB = 56; static final int SPELL_ICON = 53; static final int FC_TAB = 35; static final int FC_ICON = 44; @@ -742,19 +685,15 @@ public class WidgetID { static class ATK { - static final int LISTEN_TOP = 7; - static final int LISTEN_BOTTOM = 8; - static final int TO_CALL_WIDGET = 9; - static final int TO_CALL = 10; - static final int ROLE_SPRITE = 11; - static final int ROLE = 12; + static final int ROLE_SPRITE = 12; + static final int ROLE = 13; } static class HLR { - static final int TEAMMATE1 = 18; - static final int TEAMMATE2 = 22; - static final int TEAMMATE3 = 26; - static final int TEAMMATE4 = 30; + static final int TEAMMATE1 = 19; + static final int TEAMMATE2 = 23; + static final int TEAMMATE3 = 27; + static final int TEAMMATE4 = 31; } static class HORN_GLORY { @@ -782,16 +721,9 @@ public class WidgetID static final int BASE_POINTS = 33; static final int HONOUR_POINTS_REWARD = 49; } - static final int CORRECT_STYLE = 3; - static final int GAME_WIDGET = 3; - static final int CURRENT_WAVE_WIDGET = 4; - static final int CURRENT_WAVE = 5; - static final int LISTEN_WIDGET = 6; - static final int LISTEN = 7; - static final int TO_CALL_WIDGET = 8; - static final int TO_CALL = 9; - static final int ROLE_SPRITE = 10; - static final int ROLE = 11; + static final int ROLE_SPRITE = 11; + static final int ROLE = 12; + static final int REWARD_TEXT = 57; } @@ -809,7 +741,7 @@ public class WidgetID static class QuestCompleted { - static final int NAME_TEXT = 2; + static final int NAME_TEXT = 4; } static class Raids @@ -817,33 +749,21 @@ public class WidgetID static final int POINTS_INFOBOX = 7; } - static class TheatreOfBlood - { - static final int RAIDING_PARTY = 9; - static final int ORB_BOX = 10; - static final int BOSS_HEALTH_BAR = 35; - } - - static class TheatreOfBloodParty - { - static final int CONTAINER = 10; - } - static class Tob { static final int PARTY_INTERFACE = 6; static final int PARTY_STATS = 10; } - static class ExperienceDrop + public static class ExperienceDrop { - static final int DROP_1 = 15; - static final int DROP_2 = 16; - static final int DROP_3 = 17; - static final int DROP_4 = 18; - static final int DROP_5 = 19; - static final int DROP_6 = 20; - static final int DROP_7 = 21; + public static final int DROP_1 = 15; + public static final int DROP_2 = 16; + public static final int DROP_3 = 17; + public static final int DROP_4 = 18; + public static final int DROP_5 = 19; + public static final int DROP_6 = 20; + public static final int DROP_7 = 21; } static class PuzzleBox @@ -924,28 +844,6 @@ public class WidgetID static final int DESTROY_ITEM_NO = 3; } - static class EquipmentWidgetIdentifiers - { - static final int EQUIP_YOUR_CHARACTER = 3; - static final int STAB_ATTACK_BONUS = 24; - static final int SLASH_ATTACK_BONUS = 25; - static final int CRUSH_ATTACK_BONUS = 26; - static final int MAGIC_ATTACK_BONUS = 27; - static final int RANGED_ATTACK_BONUS = 28; - static final int STAB_DEFENCE_BONUS = 30; - static final int SLASH_DEFENCE_BONUS = 31; - static final int CRUSH_DEFENCE_BONUS = 32; - static final int MAGIC_DEFENCE_BONUS = 33; - static final int RANGED_DEFENCE_BONUS = 34; - static final int MELEE_STRENGTH = 36; - static final int RANGED_STRENGTH = 37; - static final int MAGIC_DAMAGE = 38; - static final int PRAYER_BONUS = 39; - static final int UNDEAD_DAMAGE_BONUS = 41; - static final int SLAYER_DAMAGE_BONUS = 42; - static final int WEIGHT = 49; - } - static class VarrockMuseum { static final int VARROCK_MUSEUM_QUESTION = 28; @@ -974,6 +872,282 @@ public class WidgetID static final int FOSSIL_ISLAND_OXYGEN_BAR = 4; } + static class Minigames + { + static final int TELEPORT_BUTTON = 26; + } + + public static class StandardSpellBook + { + static final int LUMBRIDGE_HOME_TELEPORT = 5; + public static final int KOUREND_HOME_TELEPORT = 4; + } + + static class AncientSpellBook + { + static final int EDGEVILLE_HOME_TELEPORT = 99; + } + + static class LunarSpellBook + { + static final int LUNAR_HOME_TELEPORT = 100; + } + + static class ArceuusSpellBook + { + static final int ARCEUUS_HOME_TELEPORT = 144; + } + + static class Pvp + { + static final int FOG_OVERLAY = 1; + static final int PVP_WIDGET_CONTAINER = 54; // OUTDATED? + static final int SKULL = 56; // OUTDATED? + static final int ATTACK_RANGE = 59; // OUTDATED? + static final int BOUNTY_HUNTER_INFO = 6; + static final int KILLDEATH_RATIO = 28; + static final int SKULL_CONTAINER = 48; + static final int SAFE_ZONE = 50; + static final int WILDERNESS_LEVEL = 53; // this can also be the Deadman Mode "Protection" text + } + + static class KourendFavour + { + static final int KOUREND_FAVOUR_OVERLAY = 1; + } + + static class Zeah + { + static final int MESS_HALL_COOKING_DISPLAY = 3; + } + + static class LootingBag + { + static final int LOOTING_BAG_INVENTORY = 5; + } + + static class Skotizo + { + static final int CONTAINER = 3; + } + + public static class FullScreenMap + { + public static final int ROOT = 27; + } + + static class QuestList + { + static final int BOX = 0; + static final int SCROLLBAR = 4; + static final int CONTAINER = 5; + static final int FREE_CONTAINER = 6; + static final int MEMBERS_CONTAINER = 7; + static final int MINIQUEST_CONTAINER = 8; + } + + static class Music + { + static final int CONTAINER = 0; + static final int LIST = 3; + static final int SCROLLBAR = 4; + } + + static class Barrows_Puzzle + { + static final int PARENT = 0; + static final int CONTAINER = 1; + static final int TOP_ROW_PUZZLE = 2; + static final int SEQUENCE_1 = 3; + static final int SEQUENCE_1_TEXT = 4; + static final int SEQUENCE_2 = 5; + static final int SEQUENCE_2_TEXT = 6; + static final int SEQUENCE_3 = 7; + static final int SEQUENCE_3_TEXT = 8; + static final int SEQUENCE_4 = 9; + static final int SEQUENCE_4_TEXT = 10; + static final int NEXT_SHAPE_TEXT = 11; + static final int ANSWER1_CONTAINER = 12; + static final int ANSWER1 = 13; + static final int ANSWER2_CONTAINER = 14; + static final int ANSWER2 = 15; + static final int ANSWER3_CONTAINER = 16; + static final int ANSWER3 = 17; + } + + static class SeedVault + { + static final int INVENTORY_ITEM_CONTAINER = 1; + static final int TITLE_CONTAINER = 2; + static final int ITEM_CONTAINER = 15; + static final int ITEM_TEXT = 16; + } + + static class ExplorersRing + { + static final int INVENTORY = 7; + } + + static class SettingsSide + { + static final int CAMERA_ZOOM_SLIDER_TRACK = 59; + static final int MUSIC_SLIDER = 13; + static final int SOUND_EFFECT_SLIDER = 17; + static final int AREA_SOUND_SLIDER = 21; + } + + static class Settings + { + static final int INIT = 1; + } + + static class AchievementDiary + { + static final int CONTAINER = 2; + } + + static class Skills + { + 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 GenericScroll + { + static final int TEXT = 7; + } + + static class GauntletTimer + { + static final int CONTAINER = 2; + } + + static class HallowedSepulchreTimer + { + static final int CONTAINER = 2; + } + + // Also used for many other interfaces! + static class BankPin + { + static final int CONTAINER = 0; + static final int TOP_LEFT_TEXT = 2; + static final int FIRST_ENTERED = 3; + static final int SECOND_ENTERED = 4; + static final int THIRD_ENTERED = 5; + static final int FOURTH_ENTERED = 6; + static final int INSTRUCTION_TEXT = 10; + static final int EXIT_BUTTON = 13; + static final int FORGOT_BUTTON = 15; + static final int BUTTON_1 = 16; + static final int BUTTON_2 = 18; + static final int BUTTON_3 = 20; + static final int BUTTON_4 = 22; + static final int BUTTON_5 = 24; + static final int BUTTON_6 = 26; + static final int BUTTON_7 = 28; + static final int BUTTON_8 = 30; + static final int BUTTON_9 = 32; + static final int BUTTON_10 = 34; + } + + static class EncounterHealthBar + { + static final int CONTAINER = 6; + } + + static class TrailblazerAreas + { + static final int TELEPORT = 59; + } + + + static class DialogPlayer + { + static final int HEAD_MODEL = 1; + static final int NAME = 2; + static final int CONTINUE = 3; + static final int TEXT = 4; + } + + static class DialogNotification + { + static final int TEXT = 0; + static final int CONTINUE = 1; + } + + static class DialogOption + { + static final int TEXT = 0; + static final int OPTION1 = 1; + static final int OPTION2 = 2; + static final int OPTION3 = 3; + static final int OPTION4 = 4; + static final int OPTION5 = 5; + } + + static class PestControlExchangeWindow + { + static final int ITEM_LIST = 2; + static final int BOTTOM = 5; + static final int POINTS = 8; + static final int CONFIRM_BUTTON = 6; + } + + static class MinigameDialog + { + static final int TEXT = 1; + static final int CONTINUE = 2; + } + + static class TheatreOfBlood + { + static final int RAIDING_PARTY = 9; + static final int ORB_BOX = 10; + static final int BOSS_HEALTH_BAR = 35; + } + + static class TheatreOfBloodParty + { + static final int CONTAINER = 10; + } + + static class EquipmentWidgetIdentifiers + { + static final int EQUIP_YOUR_CHARACTER = 3; + static final int STAB_ATTACK_BONUS = 24; + static final int SLASH_ATTACK_BONUS = 25; + static final int CRUSH_ATTACK_BONUS = 26; + static final int MAGIC_ATTACK_BONUS = 27; + static final int RANGED_ATTACK_BONUS = 28; + static final int STAB_DEFENCE_BONUS = 30; + static final int SLASH_DEFENCE_BONUS = 31; + static final int CRUSH_DEFENCE_BONUS = 32; + static final int MAGIC_DEFENCE_BONUS = 33; + static final int RANGED_DEFENCE_BONUS = 34; + static final int MELEE_STRENGTH = 36; + static final int RANGED_STRENGTH = 37; + static final int MAGIC_DAMAGE = 38; + static final int PRAYER_BONUS = 39; + static final int UNDEAD_DAMAGE_BONUS = 41; + static final int SLAYER_DAMAGE_BONUS = 42; + static final int WEIGHT = 49; + } + static class FossilMushroomTeleport { static final int ROOT = 2; @@ -983,11 +1157,6 @@ public class WidgetID static final int MUSHROOM_MEADOW = 16; } - static class Minigames - { - static final int TELEPORT_BUTTON = 26; - } - static class SpellBook { static final int FILTERED_SPELLS_BOUNDS = 3; @@ -1167,75 +1336,6 @@ public class WidgetID } - static class StandardSpellBook - { - static final int LUMBRIDGE_HOME_TELEPORT = 5; - static final int KOUREND_HOME_TELEPORT = 4; - } - - static class AncientSpellBook - { - static final int EDGEVILLE_HOME_TELEPORT = 99; - } - - static class LunarSpellBook - { - static final int LUNAR_HOME_TELEPORT = 100; - } - - static class ArceuusSpellBook - { - static final int ARCEUUS_HOME_TELEPORT = 144; - } - - static class Pvp - { - static final int FOG_OVERLAY = 1; - static final int PVP_WIDGET_CONTAINER = 54; // OUTDATED? - static final int SKULL = 56; // OUTDATED? - static final int ATTACK_RANGE = 59; // OUTDATED? - static final int BOUNTY_HUNTER_INFO = 6; - static final int KILLDEATH_RATIO = 28; - static final int SKULL_CONTAINER = 48; - static final int SAFE_ZONE = 50; - static final int WILDERNESS_LEVEL = 53; // this can also be the Deadman Mode "Protection" text - } - - static class KourendFavour - { - static final int KOUREND_FAVOUR_OVERLAY = 1; - } - - static class Zeah - { - static final int MESS_HALL_COOKING_DISPLAY = 3; - } - - static class LootingBag - { - static final int LOOTING_BAG_INVENTORY = 5; - } - - static class Skotizo - { - static final int CONTAINER = 3; - } - - static class FullScreenMap - { - static final int ROOT = 27; - } - - static class QuestList - { - static final int BOX = 0; - static final int SCROLLBAR = 4; - static final int CONTAINER = 5; - static final int FREE_CONTAINER = 6; - static final int MEMBERS_CONTAINER = 7; - static final int MINIQUEST_CONTAINER = 8; - } - static class DialogSprite2 { static final int SPRITE1 = 1; @@ -1249,35 +1349,6 @@ public class WidgetID static final int QUEST_TAB = 3; } - static class Music - { - static final int CONTAINER = 0; - static final int LIST = 3; - static final int SCROLLBAR = 4; - } - - static class Barrows_Puzzle - { - static final int PARENT = 0; - static final int CONTAINER = 1; - static final int TOP_ROW_PUZZLE = 2; - static final int SEQUENCE_1 = 3; - static final int SEQUENCE_1_TEXT = 4; - static final int SEQUENCE_2 = 5; - static final int SEQUENCE_2_TEXT = 6; - static final int SEQUENCE_3 = 7; - static final int SEQUENCE_3_TEXT = 8; - static final int SEQUENCE_4 = 9; - static final int SEQUENCE_4_TEXT = 10; - static final int NEXT_SHAPE_TEXT = 11; - static final int ANSWER1_CONTAINER = 12; - static final int ANSWER1 = 13; - static final int ANSWER2_CONTAINER = 14; - static final int ANSWER2 = 15; - static final int ANSWER3_CONTAINER = 16; - static final int ANSWER3 = 17; - } - public static class TradeScreen { public static final int FIRST_TRADING_WITH = 31; @@ -1311,44 +1382,6 @@ public class WidgetID public static final int WINNINGS = 40; } - // Also used for many other interfaces! - static class BankPin - { - static final int CONTAINER = 0; - static final int TOP_LEFT_TEXT = 2; - static final int FIRST_ENTERED = 3; - static final int SECOND_ENTERED = 4; - static final int THIRD_ENTERED = 5; - static final int FOURTH_ENTERED = 6; - static final int INSTRUCTION_TEXT = 10; - static final int EXIT_BUTTON = 13; - static final int FORGOT_BUTTON = 15; - static final int BUTTON_1 = 16; - static final int BUTTON_2 = 18; - static final int BUTTON_3 = 20; - static final int BUTTON_4 = 22; - static final int BUTTON_5 = 24; - static final int BUTTON_6 = 26; - static final int BUTTON_7 = 28; - static final int BUTTON_8 = 30; - static final int BUTTON_9 = 32; - static final int BUTTON_10 = 34; - } - - static class SeedVault - { - static final int INVENTORY_ITEM_CONTAINER = 1; - static final int TITLE_CONTAINER = 2; - static final int ITEM_CONTAINER = 15; - static final int ITEM_TEXT = 16; - } - - static class ExplorersRing - { - static final int INVENTORY = 7; - } - - static class JewelBox { static final int DUEL_RING = 2; @@ -1367,58 +1400,8 @@ public class WidgetID static final int AREA_SOUND_SLIDER = 49; } - static class AchievementDiary - { - static final int CONTAINER = 2; - } - - static class Skills - { - 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 GenericScroll - { - static final int TEXT = 7; - } - - static class GauntletTimer - { - static final int CONTAINER = 2; - } - static class GauntletMap { static final int CONTAINER = 4; } - - static class HallowedSepulchreTimer - { - static final int CONTAINER = 2; - } - - static class EncounterHealthBar - { - static final int CONTAINER = 6; - } - - static class TrailblazerAreas - { - static final int TELEPORT = 59; - } } diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java index d074b92c07..34ef03e1bb 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java @@ -55,7 +55,6 @@ public enum WidgetInfo WORLD_MAP_SURFACE_SELECTOR(WidgetID.WORLD_MAP_GROUP_ID, WidgetID.WorldMap.SURFACE_SELECTOR), WORLD_MAP_TOOLTIP(WidgetID.WORLD_MAP_GROUP_ID, WidgetID.WorldMap.TOOLTIP), WORLD_MAP_OPTION(WidgetID.WORLD_MAP_MENU_GROUP_ID, WidgetID.WorldMap.OPTION), - WORLD_MAP_BUTTON_BORDER(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.WORLDMAP_ORB), CLUE_SCROLL_TEXT(WidgetID.CLUE_SCROLL_GROUP_ID, WidgetID.Cluescroll.CLUE_TEXT), CLUE_SCROLL_REWARD_ITEM_CONTAINER(WidgetID.CLUE_SCROLL_REWARD_GROUP_ID, WidgetID.Cluescroll.CLUE_SCROLL_ITEM_CONTAINER), @@ -63,18 +62,6 @@ public enum WidgetInfo EQUIPMENT(WidgetID.EQUIPMENT_GROUP_ID, 0), EQUIPMENT_INVENTORY_ITEMS_CONTAINER(WidgetID.EQUIPMENT_INVENTORY_GROUP_ID, WidgetID.Equipment.INVENTORY_ITEM_CONTAINER), - EQUIPMENT_HELMET(WidgetID.EQUIPMENT_GROUP_ID, WidgetID.Equipment.HELMET), - EQUIPMENT_CAPE(WidgetID.EQUIPMENT_GROUP_ID, WidgetID.Equipment.CAPE), - EQUIPMENT_AMULET(WidgetID.EQUIPMENT_GROUP_ID, WidgetID.Equipment.AMULET), - EQUIPMENT_WEAPON(WidgetID.EQUIPMENT_GROUP_ID, WidgetID.Equipment.WEAPON), - EQUIPMENT_BODY(WidgetID.EQUIPMENT_GROUP_ID, WidgetID.Equipment.BODY), - EQUIPMENT_SHIELD(WidgetID.EQUIPMENT_GROUP_ID, WidgetID.Equipment.SHIELD), - EQUIPMENT_LEGS(WidgetID.EQUIPMENT_GROUP_ID, WidgetID.Equipment.LEGS), - EQUIPMENT_GLOVES(WidgetID.EQUIPMENT_GROUP_ID, WidgetID.Equipment.GLOVES), - EQUIPMENT_BOOTS(WidgetID.EQUIPMENT_GROUP_ID, WidgetID.Equipment.BOOTS), - EQUIPMENT_RING(WidgetID.EQUIPMENT_GROUP_ID, WidgetID.Equipment.RING), - EQUIPMENT_AMMO(WidgetID.EQUIPMENT_GROUP_ID, WidgetID.Equipment.AMMO), - EMOTE_WINDOW(WidgetID.EMOTES_GROUP_ID, WidgetID.Emotes.EMOTE_WINDOW), EMOTE_CONTAINER(WidgetID.EMOTES_GROUP_ID, WidgetID.Emotes.EMOTE_CONTAINER), EMOTE_SCROLLBAR(WidgetID.EMOTES_GROUP_ID, WidgetID.Emotes.EMOTE_SCROLLBAR), @@ -86,15 +73,8 @@ public enum WidgetInfo DIARY_QUEST_WIDGET_TITLE(WidgetID.DIARY_QUEST_GROUP_ID, WidgetID.Diary.DIARY_TITLE), DIARY_QUEST_WIDGET_TEXT(WidgetID.DIARY_QUEST_GROUP_ID, WidgetID.Diary.DIARY_TEXT), - MINIGAME_DIALOG(WidgetID.DIALOG_MINIGAME_GROUP_ID, 0), - MINIGAME_DIALOG_TEXT(WidgetID.DIALOG_MINIGAME_GROUP_ID, WidgetID.MinigameDialog.TEXT), - MINIGAME_DIALOG_CONTINUE(WidgetID.DIALOG_MINIGAME_GROUP_ID, WidgetID.MinigameDialog.CONTINUE), - PEST_CONTROL_EXCHANGE_WINDOW(WidgetID.PEST_CONTROL_EXCHANGE_WINDOW_GROUP_ID, 0), - PEST_CONTROL_EXCHANGE_WINDOW_POINTS(WidgetID.PEST_CONTROL_EXCHANGE_WINDOW_GROUP_ID, WidgetID.PestControlExchangeWindow.POINTS), PEST_CONTROL_BOAT_INFO(WidgetID.PEST_CONTROL_BOAT_GROUP_ID, WidgetID.PestControlBoat.INFO), - PEST_CONTROL_BOAT_INFO_POINTS(WidgetID.PEST_CONTROL_BOAT_GROUP_ID, WidgetID.PestControlBoat.POINTS), PEST_CONTROL_INFO(WidgetID.PEST_CONTROL_GROUP_ID, WidgetID.PestControl.INFO), - PEST_CONTROL_INFO_TIME(WidgetID.PEST_CONTROL_GROUP_ID, WidgetID.PestControl.TIME), PEST_CONTROL_PURPLE_SHIELD(WidgetID.PEST_CONTROL_GROUP_ID, WidgetID.PestControl.PURPLE_SHIELD), PEST_CONTROL_BLUE_SHIELD(WidgetID.PEST_CONTROL_GROUP_ID, WidgetID.PestControl.BLUE_SHIELD), PEST_CONTROL_YELLOW_SHIELD(WidgetID.PEST_CONTROL_GROUP_ID, WidgetID.PestControl.YELLOW_SHIELD), @@ -154,8 +134,6 @@ public enum WidgetInfo BANK_CONTAINER(WidgetID.BANK_GROUP_ID, WidgetID.Bank.BANK_CONTAINER), BANK_SEARCH_BUTTON_BACKGROUND(WidgetID.BANK_GROUP_ID, WidgetID.Bank.SEARCH_BUTTON_BACKGROUND), BANK_ITEM_CONTAINER(WidgetID.BANK_GROUP_ID, WidgetID.Bank.ITEM_CONTAINER), - BANK_UNNOTED_BUTTON(WidgetID.BANK_GROUP_ID, WidgetID.Bank.UNNOTED_BUTTON), - BANK_NOTED_BUTTON(WidgetID.BANK_GROUP_ID, WidgetID.Bank.NOTED_BUTTON), BANK_INVENTORY_ITEMS_CONTAINER(WidgetID.BANK_INVENTORY_GROUP_ID, WidgetID.Bank.INVENTORY_ITEM_CONTAINER), BANK_TITLE_BAR(WidgetID.BANK_GROUP_ID, WidgetID.Bank.BANK_TITLE_BAR), BANK_INCINERATOR(WidgetID.BANK_GROUP_ID, WidgetID.Bank.INCINERATOR), @@ -175,57 +153,17 @@ public enum WidgetInfo BANK_TUTORIAL_BUTTON(WidgetID.BANK_GROUP_ID, WidgetID.Bank.TUTORIAL_BUTTON), GRAND_EXCHANGE_WINDOW_CONTAINER(WidgetID.GRAND_EXCHANGE_GROUP_ID, WidgetID.GrandExchange.WINDOW_CONTAINER), - GRAND_EXCHANGE_HISTORY_BUTTON(WidgetID.GRAND_EXCHANGE_GROUP_ID, WidgetID.GrandExchange.HISTORY_BUTTON), - GRAND_EXCHANGE_BACK_BUTTON(WidgetID.GRAND_EXCHANGE_GROUP_ID, WidgetID.GrandExchange.BACK_BUTTON), - GRAND_EXCHANGE_OFFER1(WidgetID.GRAND_EXCHANGE_GROUP_ID, WidgetID.GrandExchange.OFFER1), - GRAND_EXCHANGE_OFFER2(WidgetID.GRAND_EXCHANGE_GROUP_ID, WidgetID.GrandExchange.OFFER2), - GRAND_EXCHANGE_OFFER3(WidgetID.GRAND_EXCHANGE_GROUP_ID, WidgetID.GrandExchange.OFFER3), - GRAND_EXCHANGE_OFFER4(WidgetID.GRAND_EXCHANGE_GROUP_ID, WidgetID.GrandExchange.OFFER4), - GRAND_EXCHANGE_OFFER5(WidgetID.GRAND_EXCHANGE_GROUP_ID, WidgetID.GrandExchange.OFFER5), - GRAND_EXCHANGE_OFFER6(WidgetID.GRAND_EXCHANGE_GROUP_ID, WidgetID.GrandExchange.OFFER6), - GRAND_EXCHANGE_OFFER7(WidgetID.GRAND_EXCHANGE_GROUP_ID, WidgetID.GrandExchange.OFFER7), - GRAND_EXCHANGE_OFFER8(WidgetID.GRAND_EXCHANGE_GROUP_ID, WidgetID.GrandExchange.OFFER8), GRAND_EXCHANGE_OFFER_CONTAINER(WidgetID.GRAND_EXCHANGE_GROUP_ID, WidgetID.GrandExchange.OFFER_CONTAINER), GRAND_EXCHANGE_OFFER_TEXT(WidgetID.GRAND_EXCHANGE_GROUP_ID, WidgetID.GrandExchange.OFFER_DESCRIPTION), GRAND_EXCHANGE_OFFER_PRICE(WidgetID.GRAND_EXCHANGE_GROUP_ID, WidgetID.GrandExchange.OFFER_PRICE), - GRAND_EXCHANGE_OFFER_CONFIRM_BUTTON(WidgetID.GRAND_EXCHANGE_GROUP_ID, WidgetID.GrandExchange.OFFER_CONFIRM_BUTTON), GRAND_EXCHANGE_INVENTORY_ITEMS_CONTAINER(WidgetID.GRAND_EXCHANGE_INVENTORY_GROUP_ID, WidgetID.GrandExchangeInventory.INVENTORY_ITEM_CONTAINER), DEPOSIT_BOX_INVENTORY_ITEMS_CONTAINER(WidgetID.DEPOSIT_BOX_GROUP_ID, WidgetID.DepositBox.INVENTORY_ITEM_CONTAINER), - SHOP_ITEMS_CONTAINER(WidgetID.SHOP_GROUP_ID, WidgetID.Shop.ITEMS_CONTAINER), SHOP_INVENTORY_ITEMS_CONTAINER(WidgetID.SHOP_INVENTORY_GROUP_ID, WidgetID.Shop.INVENTORY_ITEM_CONTAINER), SMITHING_INVENTORY_ITEMS_CONTAINER(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.INVENTORY_ITEM_CONTAINER), - SMITHING_ANVIL_DAGGER(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.DAGGER), - SMITHING_ANVIL_SWORD(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.SWORD), - SMITHING_ANVIL_SCIMITAR(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.SCIMITAR), - SMITHING_ANVIL_LONG_SWORD(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.LONG_SWORD), - SMITHING_ANVIL_TWO_H_SWORD(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.TWO_H_SWORD), - SMITHING_ANVIL_AXE(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.AXE), - SMITHING_ANVIL_MACE(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.MACE), - SMITHING_ANVIL_WARHAMMER(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.WARHAMMER), - SMITHING_ANVIL_BATTLE_AXE(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.BATTLE_AXE), - SMITHING_ANVIL_CLAWS(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.CLAWS), - SMITHING_ANVIL_CHAIN_BODY(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.CHAIN_BODY), - SMITHING_ANVIL_PLATE_LEGS(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.PLATE_LEGS), - SMITHING_ANVIL_PLATE_SKIRT(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.PLATE_SKIRT), - SMITHING_ANVIL_PLATE_BODY(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.PLATE_BODY), - SMITHING_ANVIL_NAILS(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.NAILS), - SMITHING_ANVIL_MED_HELM(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.MED_HELM), - SMITHING_ANVIL_FULL_HELM(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.FULL_HELM), - SMITHING_ANVIL_SQ_SHIELD(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.SQ_SHIELD), - SMITHING_ANVIL_KITE_SHIELD(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.KITE_SHIELD), - SMITHING_ANVIL_DART_TIPS(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.DART_TIPS), - SMITHING_ANVIL_ARROW_HEADS(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.ARROW_HEADS), - SMITHING_ANVIL_KNIVES(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.KNIVES), - SMITHING_ANVIL_JAVELIN_HEADS(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.JAVELIN_HEADS), - SMITHING_ANVIL_BOLTS(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.BOLTS), - SMITHING_ANVIL_LIMBS(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.LIMBS), - SMITHING_ANVIL_EXCLUSIVE1(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.EXCLUSIVE1), - SMITHING_ANVIL_EXCLUSIVE2(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.EXCLUSIVE2), - GUIDE_PRICES_ITEMS_CONTAINER(WidgetID.GUIDE_PRICES_GROUP_ID, WidgetID.GuidePrices.ITEM_CONTAINER), GUIDE_PRICES_INVENTORY_ITEMS_CONTAINER(WidgetID.GUIDE_PRICES_INVENTORY_GROUP_ID, WidgetID.GuidePrices.INVENTORY_ITEM_CONTAINER), @@ -242,9 +180,7 @@ public enum WidgetInfo MINIMAP_RUN_ORB_TEXT(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.RUN_ORB_TEXT), MINIMAP_HEALTH_ORB(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.HEALTH_ORB), MINIMAP_SPEC_ORB(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.SPEC_ORB), - MINIMAP_SPEC_CLICKBOX(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.SPEC_CLICKBOX), MINIMAP_WORLDMAP_ORB(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.WORLDMAP_ORB), - MINIMAP_WORLD_ORB(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.WORLDMAP_ORB), MINIMAP_WIKI_BANNER(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.WIKI_BANNER), LMS_INFO(WidgetID.LMS_GROUP_ID, WidgetID.Lms.INFO), @@ -338,7 +274,6 @@ public enum WidgetInfo RESIZABLE_VIEWPORT_BOTTOM_LINE_EQUIPMENT_ICON(WidgetID.RESIZABLE_VIEWPORT_BOTTOM_LINE_GROUP_ID, WidgetID.ResizableViewportBottomLine.EQUIP_ICON), RESIZABLE_VIEWPORT_BOTTOM_LINE_COMBAT_ICON(WidgetID.RESIZABLE_VIEWPORT_BOTTOM_LINE_GROUP_ID, WidgetID.ResizableViewportBottomLine.CMB_ICON), RESIZABLE_VIEWPORT_BOTTOM_LINE_STATS_ICON(WidgetID.RESIZABLE_VIEWPORT_BOTTOM_LINE_GROUP_ID, WidgetID.ResizableViewportBottomLine.SKILLS_ICON), - RESIZABLE_VIEWPORT_BOTTOM_LINE_MAGIC_TAB(WidgetID.RESIZABLE_VIEWPORT_BOTTOM_LINE_GROUP_ID, WidgetID.ResizableViewportBottomLine.SPELL_TAB), RESIZABLE_VIEWPORT_BOTTOM_LINE_MAGIC_ICON(WidgetID.RESIZABLE_VIEWPORT_BOTTOM_LINE_GROUP_ID, WidgetID.ResizableViewportBottomLine.MAGIC_ICON), RESIZABLE_VIEWPORT_BOTTOM_LINE_FRIEND_ICON(WidgetID.RESIZABLE_VIEWPORT_BOTTOM_LINE_GROUP_ID, WidgetID.ResizableViewportBottomLine.FRIEND_ICON), RESIZABLE_VIEWPORT_BOTTOM_LINE_FRIEND_CHAT_ICON(WidgetID.RESIZABLE_VIEWPORT_BOTTOM_LINE_GROUP_ID, WidgetID.ResizableViewportBottomLine.FC_ICON), @@ -383,7 +318,6 @@ public enum WidgetInfo QUICK_PRAYER_PRAYERS(WidgetID.QUICK_PRAYERS_GROUP_ID, WidgetID.QuickPrayer.PRAYERS), COMBAT_LEVEL(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.LEVEL), - COMBAT_WEAPON(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.WEAPON_NAME), COMBAT_STYLE_ONE(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.STYLE_ONE), COMBAT_STYLE_TWO(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.STYLE_TWO), COMBAT_STYLE_THREE(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.STYLE_THREE), @@ -397,21 +331,12 @@ public enum WidgetInfo COMBAT_SPELL_ICON(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.SPELL_ICON), COMBAT_SPELL_TEXT(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.SPELL_TEXT), COMBAT_AUTO_RETALIATE(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.AUTO_RETALIATE), - COMBAT_SPECIAL_ATTACK(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.SPECIAL_ATTACK_BAR), - COMBAT_SPECIAL_ATTACK_CLICKBOX(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.SPECIAL_ATTACK_CLICKBOX), - COMBAT_TOOLTIP(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.TOOLTIP), DIALOG_OPTION(WidgetID.DIALOG_OPTION_GROUP_ID, 0), - MULTI_SKILL_MENU(WidgetID.MULTISKILL_MENU_GROUP_ID, 0), DIALOG_SPRITE(WidgetID.DIALOG_SPRITE_GROUP_ID, 0), DIALOG_SPRITE_SPRITE(WidgetID.DIALOG_SPRITE_GROUP_ID, WidgetID.DialogSprite.SPRITE), DIALOG_SPRITE_TEXT(WidgetID.DIALOG_SPRITE_GROUP_ID, WidgetID.DialogSprite.TEXT), - DIALOG2_SPRITE(WidgetID.DIALOG_SPRITE2_ID, 0), - DIALOG2_SPRITE_SPRITE1(WidgetID.DIALOG_SPRITE2_ID, WidgetID.DialogSprite2.SPRITE1), - DIALOG2_SPRITE_SPRITE2(WidgetID.DIALOG_SPRITE2_ID, WidgetID.DialogSprite2.SPRITE2), - DIALOG2_SPRITE_TEXT(WidgetID.DIALOG_SPRITE2_ID, WidgetID.DialogSprite2.TEXT), - DIALOG2_SPRITE_CONTINUE(WidgetID.DIALOG_SPRITE2_ID, WidgetID.DialogSprite2.CONTINUE), DIALOG_NPC(WidgetID.DIALOG_NPC_GROUP_ID, 0), DIALOG_NPC_NAME(WidgetID.DIALOG_NPC_GROUP_ID, WidgetID.DialogNPC.NAME), @@ -419,21 +344,6 @@ public enum WidgetInfo DIALOG_NPC_HEAD_MODEL(WidgetID.DIALOG_NPC_GROUP_ID, WidgetID.DialogNPC.HEAD_MODEL), DIALOG_NPC_CONTINUE(WidgetID.DIALOG_NPC_GROUP_ID, WidgetID.DialogNPC.CONTINUE), - DIALOG_PLAYER_NAME(WidgetID.DIALOG_PLAYER_GROUP_ID, WidgetID.DialogPlayer.NAME), - DIALOG_PLAYER_TEXT(WidgetID.DIALOG_PLAYER_GROUP_ID, WidgetID.DialogPlayer.TEXT), - DIALOG_PLAYER_HEAD_MODEL(WidgetID.DIALOG_PLAYER_GROUP_ID, WidgetID.DialogPlayer.HEAD_MODEL), - DIALOG_PLAYER_CONTINUE(WidgetID.DIALOG_PLAYER_GROUP_ID, WidgetID.DialogPlayer.CONTINUE), - - DIALOG_NOTIFICATION_TEXT(WidgetID.DIALOG_NOTIFICATION_GROUP_ID, WidgetID.DialogNotification.TEXT), - DIALOG_NOTIFICATION_CONTINUE(WidgetID.DIALOG_NOTIFICATION_GROUP_ID, WidgetID.DialogNotification.CONTINUE), - - DIALOG_OPTION_TEXT(WidgetID.DIALOG_OPTION_GROUP_ID, WidgetID.DialogOption.TEXT), - DIALOG_OPTION_OPTION1(WidgetID.DIALOG_OPTION_GROUP_ID, WidgetID.DialogOption.OPTION1), - DIALOG_OPTION_OPTION2(WidgetID.DIALOG_OPTION_GROUP_ID, WidgetID.DialogOption.OPTION2), - DIALOG_OPTION_OPTION3(WidgetID.DIALOG_OPTION_GROUP_ID, WidgetID.DialogOption.OPTION3), - DIALOG_OPTION_OPTION4(WidgetID.DIALOG_OPTION_GROUP_ID, WidgetID.DialogOption.OPTION4), - DIALOG_OPTION_OPTION5(WidgetID.DIALOG_OPTION_GROUP_ID, WidgetID.DialogOption.OPTION5), - DIALOG_PLAYER(WidgetID.DIALOG_PLAYER_GROUP_ID, 0), PRIVATE_CHAT_MESSAGE(WidgetID.PRIVATE_CHAT, 0), @@ -461,10 +371,6 @@ public enum WidgetInfo CHATBOX_TAB_CLAN(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.TAB_CLAN), CHATBOX_TAB_TRADE(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.TAB_TRADE), - BA_HEAL_WAVE_TEXT(WidgetID.BA_HEALER_GROUP_ID, WidgetID.BarbarianAssault.CURRENT_WAVE), - BA_HEAL_CALL_TEXT(WidgetID.BA_HEALER_GROUP_ID, WidgetID.BarbarianAssault.TO_CALL), - BA_HEAL_LISTEN_TEXT(WidgetID.BA_HEALER_GROUP_ID, WidgetID.BarbarianAssault.LISTEN), - BA_HEAL_HORN_LISTEN_TEXT(WidgetID.BA_HORN_OF_GLORY, WidgetID.BarbarianAssault.HORN_GLORY.HEALER), BA_HEAL_ROLE_TEXT(WidgetID.BA_HEALER_GROUP_ID, WidgetID.BarbarianAssault.ROLE), BA_HEAL_ROLE_SPRITE(WidgetID.BA_HEALER_GROUP_ID, WidgetID.BarbarianAssault.ROLE_SPRITE), @@ -473,66 +379,32 @@ public enum WidgetInfo BA_HEAL_TEAMMATE3(WidgetID.BA_HEALER_GROUP_ID, WidgetID.BarbarianAssault.HLR.TEAMMATE3), BA_HEAL_TEAMMATE4(WidgetID.BA_HEALER_GROUP_ID, WidgetID.BarbarianAssault.HLR.TEAMMATE4), - BA_COLL_WAVE_TEXT(WidgetID.BA_COLLECTOR_GROUP_ID, WidgetID.BarbarianAssault.CURRENT_WAVE), - BA_COLL_CALL_TEXT(WidgetID.BA_COLLECTOR_GROUP_ID, WidgetID.BarbarianAssault.TO_CALL), - BA_COLL_LISTEN_TEXT(WidgetID.BA_COLLECTOR_GROUP_ID, WidgetID.BarbarianAssault.LISTEN), - BA_COLL_HORN_LISTEN_TEXT(WidgetID.BA_HORN_OF_GLORY, WidgetID.BarbarianAssault.HORN_GLORY.COLLECTOR), BA_COLL_ROLE_TEXT(WidgetID.BA_COLLECTOR_GROUP_ID, WidgetID.BarbarianAssault.ROLE), BA_COLL_ROLE_SPRITE(WidgetID.BA_COLLECTOR_GROUP_ID, WidgetID.BarbarianAssault.ROLE_SPRITE), - BA_ATK_LISTEN_TEXT(WidgetID.BA_ATTACKER_GROUP_ID, WidgetID.BarbarianAssault.CORRECT_STYLE), - BA_ATK_WAVE_TEXT(WidgetID.BA_ATTACKER_GROUP_ID, WidgetID.BarbarianAssault.CURRENT_WAVE), - BA_ATK_CALL_TEXT(WidgetID.BA_ATTACKER_GROUP_ID, WidgetID.BarbarianAssault.ATK.TO_CALL), - BA_ATK_LISTEN_TOP_TEXT(WidgetID.BA_ATTACKER_GROUP_ID, WidgetID.BarbarianAssault.ATK.LISTEN_TOP), - BA_ATK_LISTEN_BOTTOM_TEXT(WidgetID.BA_ATTACKER_GROUP_ID, WidgetID.BarbarianAssault.ATK.LISTEN_BOTTOM), - BA_ATK_HORN_LISTEN_TEXT(WidgetID.BA_HORN_OF_GLORY, WidgetID.BarbarianAssault.HORN_GLORY.ATTACKER), BA_ATK_ROLE_TEXT(WidgetID.BA_ATTACKER_GROUP_ID, WidgetID.BarbarianAssault.ATK.ROLE), BA_ATK_ROLE_SPRITE(WidgetID.BA_ATTACKER_GROUP_ID, WidgetID.BarbarianAssault.ATK.ROLE_SPRITE), - BA_DEF_WAVE_TEXT(WidgetID.BA_DEFENDER_GROUP_ID, WidgetID.BarbarianAssault.CURRENT_WAVE), - BA_DEF_CALL_TEXT(WidgetID.BA_DEFENDER_GROUP_ID, WidgetID.BarbarianAssault.TO_CALL), - BA_DEF_LISTEN_TEXT(WidgetID.BA_DEFENDER_GROUP_ID, WidgetID.BarbarianAssault.LISTEN), - BA_DEF_HORN_LISTEN_TEXT(WidgetID.BA_HORN_OF_GLORY, WidgetID.BarbarianAssault.HORN_GLORY.DEFENDER), BA_DEF_ROLE_TEXT(WidgetID.BA_DEFENDER_GROUP_ID, WidgetID.BarbarianAssault.ROLE), BA_DEF_ROLE_SPRITE(WidgetID.BA_DEFENDER_GROUP_ID, WidgetID.BarbarianAssault.ROLE_SPRITE), BA_REWARD_TEXT(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_TEXT), - BA_RUNNERS_PASSED(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.RUNNERS_PASSED), - BA_HITPOINTS_REPLENISHED(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.HITPOINTS_REPLENISHED), - BA_WRONG_POISON_PACKS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.WRONG_POISON_PACKS_USED), - BA_EGGS_COLLECTED(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.EGGS_COLLECTED), - BA_FAILED_ATTACKER_ATTACKS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.FAILED_ATTACKER_ATTACKS), - BA_RUNNERS_PASSED_POINTS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.RUNNERS_PASSED_POINTS), - BA_RANGERS_KILLED(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.RANGERS_KILLED), - BA_FIGHTERS_KILLED(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.FIGHTERS_KILLED), - BA_HEALERS_KILLED(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.HEALERS_KILLED), - BA_RUNNERS_KILLED(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.RUNNERS_KILLED), - BA_HITPOINTS_REPLENISHED_POINTS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.HITPOINTS_REPLENISHED_POINTS), - BA_WRONG_POISON_PACKS_POINTS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.WRONG_POISON_PACKS_USED_POINTS), - BA_EGGS_COLLECTED_POINTS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.EGGS_COLLECTED_POINTS), - BA_FAILED_ATTACKER_ATTACKS_POINTS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.FAILED_ATTACKER_ATTACKS_POINTS), - BA_HONOUR_POINTS_REWARD(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.HONOUR_POINTS_REWARD), - BA_BASE_POINTS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.BASE_POINTS), LEVEL_UP(WidgetID.LEVEL_UP_GROUP_ID, 0), LEVEL_UP_SKILL(WidgetID.LEVEL_UP_GROUP_ID, WidgetID.LevelUp.SKILL), LEVEL_UP_LEVEL(WidgetID.LEVEL_UP_GROUP_ID, WidgetID.LevelUp.LEVEL), - LEVEL_UP_CONTINUE(WidgetID.LEVEL_UP_GROUP_ID, WidgetID.LevelUp.CONTINUE), QUEST_COMPLETED(WidgetID.QUEST_COMPLETED_GROUP_ID, 0), QUEST_COMPLETED_NAME_TEXT(WidgetID.QUEST_COMPLETED_GROUP_ID, WidgetID.QuestCompleted.NAME_TEXT), MOTHERLODE_MINE(WidgetID.MOTHERLODE_MINE_GROUP_ID, 0), - THEATRE_OF_BLOOD_PARTY(WidgetID.THEATRE_OF_BLOOD_PARTY_GROUP_ID, WidgetID.TheatreOfBloodParty.CONTAINER), - GWD_KC(WidgetID.GWD_KC_GROUP_ID, WidgetID.GWD.CONTAINER), PUZZLE_BOX(WidgetID.PUZZLE_BOX_GROUP_ID, WidgetID.PuzzleBox.VISIBLE_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_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_B(WidgetID.LIGHT_BOX_GROUP_ID, WidgetID.LightBox.BUTTON_B), LIGHT_BOX_BUTTON_C(WidgetID.LIGHT_BOX_GROUP_ID, WidgetID.LightBox.BUTTON_C), @@ -550,10 +422,6 @@ public enum WidgetInfo RAIDS_POINTS_INFOBOX(WidgetID.RAIDS_GROUP_ID, WidgetID.Raids.POINTS_INFOBOX), - THEATRE_OF_BLOOD_HEALTH_ORBS(WidgetID.THEATRE_OF_BLOOD_GROUP_ID, WidgetID.TheatreOfBlood.ORB_BOX), - THEATRE_OF_BLOOD_BOSS_HEALTH(WidgetID.THEATRE_OF_BLOOD_GROUP_ID, WidgetID.TheatreOfBlood.BOSS_HEALTH_BAR), - THEATRE_OF_BLOOD_RAIDING_PARTY(WidgetID.THEATRE_OF_BLOOD_GROUP_ID, WidgetID.TheatreOfBlood.RAIDING_PARTY), - TOB_PARTY_INTERFACE(WidgetID.TOB_PARTY_GROUP_ID, WidgetID.Tob.PARTY_INTERFACE), TOB_PARTY_STATS(WidgetID.TOB_PARTY_GROUP_ID, WidgetID.Tob.PARTY_STATS), @@ -611,36 +479,213 @@ public enum WidgetInfo GENERIC_SCROLL_TEXT(WidgetID.GENERIC_SCROLL_GROUP_ID, WidgetID.GenericScroll.TEXT), - WORLD_SWITCHER_CONTAINER(WidgetID.WORLD_SWITCHER_GROUP_ID, WidgetID.WorldSwitcher.CONTAINER), WORLD_SWITCHER_LIST(WidgetID.WORLD_SWITCHER_GROUP_ID, WidgetID.WorldSwitcher.WORLD_LIST), - WORLD_SWITCHER_LOGOUT_BUTTON(WidgetID.WORLD_SWITCHER_GROUP_ID, WidgetID.WorldSwitcher.LOGOUT_BUTTON), FOSSIL_ISLAND_OXYGENBAR(WidgetID.FOSSIL_ISLAND_OXYGENBAR_ID, WidgetID.FossilOxygen.FOSSIL_ISLAND_OXYGEN_BAR), + + MINIGAME_TELEPORT_BUTTON(WidgetID.MINIGAME_TAB_ID, WidgetID.Minigames.TELEPORT_BUTTON), + + SPELL_LUMBRIDGE_HOME_TELEPORT(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.StandardSpellBook.LUMBRIDGE_HOME_TELEPORT), + SPELL_EDGEVILLE_HOME_TELEPORT(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.AncientSpellBook.EDGEVILLE_HOME_TELEPORT), + SPELL_LUNAR_HOME_TELEPORT(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.LunarSpellBook.LUNAR_HOME_TELEPORT), + SPELL_ARCEUUS_HOME_TELEPORT(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.ArceuusSpellBook.ARCEUUS_HOME_TELEPORT), + SPELL_KOUREND_HOME_TELEPORT(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.StandardSpellBook.KOUREND_HOME_TELEPORT), + + PVP_SKULL_CONTAINER(WidgetID.PVP_GROUP_ID, WidgetID.Pvp.SKULL_CONTAINER), + PVP_WORLD_SAFE_ZONE(WidgetID.PVP_GROUP_ID, WidgetID.Pvp.SAFE_ZONE), + + PVP_WILDERNESS_LEVEL(WidgetID.PVP_GROUP_ID, WidgetID.Pvp.WILDERNESS_LEVEL), + PVP_BOUNTY_HUNTER_INFO(WidgetID.PVP_GROUP_ID, WidgetID.Pvp.BOUNTY_HUNTER_INFO), + PVP_KILLDEATH_COUNTER(WidgetID.PVP_GROUP_ID, WidgetID.Pvp.KILLDEATH_RATIO), + + KOUREND_FAVOUR_OVERLAY(WidgetID.KOUREND_FAVOUR_GROUP_ID, WidgetID.KourendFavour.KOUREND_FAVOUR_OVERLAY), + ZEAH_MESS_HALL_COOKING_DISPLAY(WidgetID.ZEAH_MESS_HALL_GROUP_ID, WidgetID.Zeah.MESS_HALL_COOKING_DISPLAY), + + LOOTING_BAG_CONTAINER(WidgetID.LOOTING_BAG_GROUP_ID, WidgetID.LootingBag.LOOTING_BAG_INVENTORY), + + SKOTIZO_CONTAINER(WidgetID.SKOTIZO_GROUP_ID, WidgetID.Skotizo.CONTAINER), + + QUESTLIST_BOX(WidgetID.QUESTLIST_GROUP_ID, WidgetID.QuestList.BOX), + QUESTLIST_CONTAINER(WidgetID.QUESTLIST_GROUP_ID, WidgetID.QuestList.CONTAINER), + QUESTLIST_SCROLLBAR(WidgetID.QUESTLIST_GROUP_ID, WidgetID.QuestList.SCROLLBAR), + QUESTLIST_FREE_CONTAINER(WidgetID.QUESTLIST_GROUP_ID, WidgetID.QuestList.FREE_CONTAINER), + QUESTLIST_MEMBERS_CONTAINER(WidgetID.QUESTLIST_GROUP_ID, WidgetID.QuestList.MEMBERS_CONTAINER), + QUESTLIST_MINIQUEST_CONTAINER(WidgetID.QUESTLIST_GROUP_ID, WidgetID.QuestList.MINIQUEST_CONTAINER), + + SEED_VAULT_TITLE_CONTAINER(WidgetID.SEED_VAULT_GROUP_ID, WidgetID.SeedVault.TITLE_CONTAINER), + SEED_VAULT_ITEM_CONTAINER(WidgetID.SEED_VAULT_GROUP_ID, WidgetID.SeedVault.ITEM_CONTAINER), + SEED_VAULT_ITEM_TEXT(WidgetID.SEED_VAULT_GROUP_ID, WidgetID.SeedVault.ITEM_TEXT), + SEED_VAULT_INVENTORY_ITEMS_CONTAINER(WidgetID.SEED_VAULT_INVENTORY_GROUP_ID, WidgetID.SeedVault.INVENTORY_ITEM_CONTAINER), + + SETTINGS_SIDE_CAMERA_ZOOM_SLIDER_TRACK(WidgetID.SETTINGS_SIDE_GROUP_ID, WidgetID.SettingsSide.CAMERA_ZOOM_SLIDER_TRACK), + SETTINGS_SIDE_MUSIC_SLIDER(WidgetID.SETTINGS_SIDE_GROUP_ID, WidgetID.SettingsSide.MUSIC_SLIDER), + SETTINGS_SIDE_SOUND_EFFECT_SLIDER(WidgetID.SETTINGS_SIDE_GROUP_ID, WidgetID.SettingsSide.SOUND_EFFECT_SLIDER), + SETTINGS_SIDE_AREA_SOUND_SLIDER(WidgetID.SETTINGS_SIDE_GROUP_ID, WidgetID.SettingsSide.AREA_SOUND_SLIDER), + + SETTINGS_INIT(WidgetID.SETTINGS_GROUP_ID, WidgetID.Settings.INIT), + + ACHIEVEMENT_DIARY_CONTAINER(WidgetID.ACHIEVEMENT_DIARY_GROUP_ID, WidgetID.AchievementDiary.CONTAINER), + + SKILLS_CONTAINER(WidgetID.SKILLS_GROUP_ID, WidgetID.Skills.CONTAINER), + + GAUNTLET_TIMER_CONTAINER(WidgetID.GAUNTLET_TIMER_GROUP_ID, WidgetID.GauntletTimer.CONTAINER), + HALLOWED_SEPULCHRE_TIMER_CONTAINER(WidgetID.HALLOWED_SEPULCHRE_TIMER_GROUP_ID, WidgetID.HallowedSepulchreTimer.CONTAINER), + + HEALTH_OVERLAY_BAR(WidgetID.HEALTH_OVERLAY_BAR_GROUP_ID, WidgetID.EncounterHealthBar.CONTAINER), + + TRAILBLAZER_AREA_TELEPORT(WidgetID.TRAILBLAZER_AREAS_GROUP_ID, WidgetID.TrailblazerAreas.TELEPORT), + + MULTICOMBAT_FIXED(WidgetID.FIXED_VIEWPORT_GROUP_ID, WidgetID.FixedViewport.MULTICOMBAT_INDICATOR), + MULTICOMBAT_RESIZEABLE_MODERN(WidgetID.RESIZABLE_VIEWPORT_BOTTOM_LINE_GROUP_ID, WidgetID.ResizableViewport.MULTICOMBAT_INDICATOR), + MULTICOMBAT_RESIZEABLE_CLASSIC(WidgetID.RESIZABLE_VIEWPORT_OLD_SCHOOL_BOX_GROUP_ID, WidgetID.ResizableViewport.MULTICOMBAT_INDICATOR), + + //OpenOSRS + WORLD_MAP_BUTTON_BORDER(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.WORLDMAP_ORB), + + EQUIPMENT_HELMET(WidgetID.EQUIPMENT_GROUP_ID, WidgetID.Equipment.HELMET), + EQUIPMENT_CAPE(WidgetID.EQUIPMENT_GROUP_ID, WidgetID.Equipment.CAPE), + EQUIPMENT_AMULET(WidgetID.EQUIPMENT_GROUP_ID, WidgetID.Equipment.AMULET), + EQUIPMENT_WEAPON(WidgetID.EQUIPMENT_GROUP_ID, WidgetID.Equipment.WEAPON), + EQUIPMENT_BODY(WidgetID.EQUIPMENT_GROUP_ID, WidgetID.Equipment.BODY), + EQUIPMENT_SHIELD(WidgetID.EQUIPMENT_GROUP_ID, WidgetID.Equipment.SHIELD), + EQUIPMENT_LEGS(WidgetID.EQUIPMENT_GROUP_ID, WidgetID.Equipment.LEGS), + EQUIPMENT_GLOVES(WidgetID.EQUIPMENT_GROUP_ID, WidgetID.Equipment.GLOVES), + EQUIPMENT_BOOTS(WidgetID.EQUIPMENT_GROUP_ID, WidgetID.Equipment.BOOTS), + EQUIPMENT_RING(WidgetID.EQUIPMENT_GROUP_ID, WidgetID.Equipment.RING), + EQUIPMENT_AMMO(WidgetID.EQUIPMENT_GROUP_ID, WidgetID.Equipment.AMMO), + + MINIGAME_DIALOG(WidgetID.DIALOG_MINIGAME_GROUP_ID, 0), + MINIGAME_DIALOG_TEXT(WidgetID.DIALOG_MINIGAME_GROUP_ID, WidgetID.MinigameDialog.TEXT), + MINIGAME_DIALOG_CONTINUE(WidgetID.DIALOG_MINIGAME_GROUP_ID, WidgetID.MinigameDialog.CONTINUE), + PEST_CONTROL_EXCHANGE_WINDOW(WidgetID.PEST_CONTROL_EXCHANGE_WINDOW_GROUP_ID, 0), + PEST_CONTROL_EXCHANGE_WINDOW_POINTS(WidgetID.PEST_CONTROL_EXCHANGE_WINDOW_GROUP_ID, WidgetID.PestControlExchangeWindow.POINTS), + + PEST_CONTROL_BOAT_INFO_POINTS(WidgetID.PEST_CONTROL_BOAT_GROUP_ID, WidgetID.PestControlBoat.POINTS), + PEST_CONTROL_INFO_TIME(WidgetID.PEST_CONTROL_GROUP_ID, WidgetID.PestControl.TIME), + + BANK_UNNOTED_BUTTON(WidgetID.BANK_GROUP_ID, WidgetID.Bank.UNNOTED_BUTTON), + BANK_NOTED_BUTTON(WidgetID.BANK_GROUP_ID, WidgetID.Bank.NOTED_BUTTON), + + GRAND_EXCHANGE_HISTORY_BUTTON(WidgetID.GRAND_EXCHANGE_GROUP_ID, WidgetID.GrandExchange.HISTORY_BUTTON), + GRAND_EXCHANGE_BACK_BUTTON(WidgetID.GRAND_EXCHANGE_GROUP_ID, WidgetID.GrandExchange.BACK_BUTTON), + GRAND_EXCHANGE_OFFER1(WidgetID.GRAND_EXCHANGE_GROUP_ID, WidgetID.GrandExchange.OFFER1), + GRAND_EXCHANGE_OFFER2(WidgetID.GRAND_EXCHANGE_GROUP_ID, WidgetID.GrandExchange.OFFER2), + GRAND_EXCHANGE_OFFER3(WidgetID.GRAND_EXCHANGE_GROUP_ID, WidgetID.GrandExchange.OFFER3), + GRAND_EXCHANGE_OFFER4(WidgetID.GRAND_EXCHANGE_GROUP_ID, WidgetID.GrandExchange.OFFER4), + GRAND_EXCHANGE_OFFER5(WidgetID.GRAND_EXCHANGE_GROUP_ID, WidgetID.GrandExchange.OFFER5), + GRAND_EXCHANGE_OFFER6(WidgetID.GRAND_EXCHANGE_GROUP_ID, WidgetID.GrandExchange.OFFER6), + GRAND_EXCHANGE_OFFER7(WidgetID.GRAND_EXCHANGE_GROUP_ID, WidgetID.GrandExchange.OFFER7), + GRAND_EXCHANGE_OFFER8(WidgetID.GRAND_EXCHANGE_GROUP_ID, WidgetID.GrandExchange.OFFER8), + + GRAND_EXCHANGE_OFFER_CONFIRM_BUTTON(WidgetID.GRAND_EXCHANGE_GROUP_ID, WidgetID.GrandExchange.OFFER_CONFIRM_BUTTON), + + SMITHING_ANVIL_DAGGER(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.DAGGER), + SMITHING_ANVIL_SWORD(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.SWORD), + SMITHING_ANVIL_SCIMITAR(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.SCIMITAR), + SMITHING_ANVIL_LONG_SWORD(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.LONG_SWORD), + SMITHING_ANVIL_TWO_H_SWORD(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.TWO_H_SWORD), + SMITHING_ANVIL_AXE(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.AXE), + SMITHING_ANVIL_MACE(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.MACE), + SMITHING_ANVIL_WARHAMMER(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.WARHAMMER), + SMITHING_ANVIL_BATTLE_AXE(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.BATTLE_AXE), + SMITHING_ANVIL_CLAWS(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.CLAWS), + SMITHING_ANVIL_CHAIN_BODY(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.CHAIN_BODY), + SMITHING_ANVIL_PLATE_LEGS(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.PLATE_LEGS), + SMITHING_ANVIL_PLATE_SKIRT(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.PLATE_SKIRT), + SMITHING_ANVIL_PLATE_BODY(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.PLATE_BODY), + SMITHING_ANVIL_NAILS(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.NAILS), + SMITHING_ANVIL_MED_HELM(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.MED_HELM), + SMITHING_ANVIL_FULL_HELM(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.FULL_HELM), + SMITHING_ANVIL_SQ_SHIELD(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.SQ_SHIELD), + SMITHING_ANVIL_KITE_SHIELD(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.KITE_SHIELD), + SMITHING_ANVIL_DART_TIPS(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.DART_TIPS), + SMITHING_ANVIL_ARROW_HEADS(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.ARROW_HEADS), + SMITHING_ANVIL_KNIVES(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.KNIVES), + SMITHING_ANVIL_JAVELIN_HEADS(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.JAVELIN_HEADS), + SMITHING_ANVIL_BOLTS(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.BOLTS), + SMITHING_ANVIL_LIMBS(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.LIMBS), + SMITHING_ANVIL_EXCLUSIVE1(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.EXCLUSIVE1), + SMITHING_ANVIL_EXCLUSIVE2(WidgetID.SMITHING_GROUP_ID, WidgetID.Smithing.EXCLUSIVE2), + + MINIMAP_SPEC_CLICKBOX(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.SPEC_CLICKBOX), + + MINIMAP_WORLD_ORB(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.WORLDMAP_ORB), + + RESIZABLE_VIEWPORT_BOTTOM_LINE_MAGIC_TAB(WidgetID.RESIZABLE_VIEWPORT_BOTTOM_LINE_GROUP_ID, WidgetID.ResizableViewportBottomLine.SPELL_TAB), + + COMBAT_WEAPON(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.WEAPON_NAME), + + COMBAT_SPECIAL_ATTACK(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.SPECIAL_ATTACK_BAR), + COMBAT_SPECIAL_ATTACK_CLICKBOX(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.SPECIAL_ATTACK_CLICKBOX), + COMBAT_TOOLTIP(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.TOOLTIP), + + MULTI_SKILL_MENU(WidgetID.MULTISKILL_MENU_GROUP_ID, 0), + + DIALOG2_SPRITE(WidgetID.DIALOG_SPRITE2_ID, 0), + DIALOG2_SPRITE_SPRITE1(WidgetID.DIALOG_SPRITE2_ID, WidgetID.DialogSprite2.SPRITE1), + DIALOG2_SPRITE_SPRITE2(WidgetID.DIALOG_SPRITE2_ID, WidgetID.DialogSprite2.SPRITE2), + DIALOG2_SPRITE_TEXT(WidgetID.DIALOG_SPRITE2_ID, WidgetID.DialogSprite2.TEXT), + DIALOG2_SPRITE_CONTINUE(WidgetID.DIALOG_SPRITE2_ID, WidgetID.DialogSprite2.CONTINUE), + + DIALOG_PLAYER_NAME(WidgetID.DIALOG_PLAYER_GROUP_ID, WidgetID.DialogPlayer.NAME), + DIALOG_PLAYER_TEXT(WidgetID.DIALOG_PLAYER_GROUP_ID, WidgetID.DialogPlayer.TEXT), + DIALOG_PLAYER_HEAD_MODEL(WidgetID.DIALOG_PLAYER_GROUP_ID, WidgetID.DialogPlayer.HEAD_MODEL), + DIALOG_PLAYER_CONTINUE(WidgetID.DIALOG_PLAYER_GROUP_ID, WidgetID.DialogPlayer.CONTINUE), + + DIALOG_NOTIFICATION_TEXT(WidgetID.DIALOG_NOTIFICATION_GROUP_ID, WidgetID.DialogNotification.TEXT), + DIALOG_NOTIFICATION_CONTINUE(WidgetID.DIALOG_NOTIFICATION_GROUP_ID, WidgetID.DialogNotification.CONTINUE), + + DIALOG_OPTION_TEXT(WidgetID.DIALOG_OPTION_GROUP_ID, WidgetID.DialogOption.TEXT), + DIALOG_OPTION_OPTION1(WidgetID.DIALOG_OPTION_GROUP_ID, WidgetID.DialogOption.OPTION1), + DIALOG_OPTION_OPTION2(WidgetID.DIALOG_OPTION_GROUP_ID, WidgetID.DialogOption.OPTION2), + DIALOG_OPTION_OPTION3(WidgetID.DIALOG_OPTION_GROUP_ID, WidgetID.DialogOption.OPTION3), + DIALOG_OPTION_OPTION4(WidgetID.DIALOG_OPTION_GROUP_ID, WidgetID.DialogOption.OPTION4), + DIALOG_OPTION_OPTION5(WidgetID.DIALOG_OPTION_GROUP_ID, WidgetID.DialogOption.OPTION5), + + BA_RUNNERS_PASSED(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.RUNNERS_PASSED), + BA_HITPOINTS_REPLENISHED(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.HITPOINTS_REPLENISHED), + BA_WRONG_POISON_PACKS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.WRONG_POISON_PACKS_USED), + BA_EGGS_COLLECTED(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.EGGS_COLLECTED), + BA_FAILED_ATTACKER_ATTACKS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.FAILED_ATTACKER_ATTACKS), + BA_RUNNERS_PASSED_POINTS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.RUNNERS_PASSED_POINTS), + BA_RANGERS_KILLED(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.RANGERS_KILLED), + BA_FIGHTERS_KILLED(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.FIGHTERS_KILLED), + BA_HEALERS_KILLED(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.HEALERS_KILLED), + BA_RUNNERS_KILLED(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.RUNNERS_KILLED), + BA_HITPOINTS_REPLENISHED_POINTS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.HITPOINTS_REPLENISHED_POINTS), + BA_WRONG_POISON_PACKS_POINTS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.WRONG_POISON_PACKS_USED_POINTS), + BA_EGGS_COLLECTED_POINTS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.EGGS_COLLECTED_POINTS), + BA_FAILED_ATTACKER_ATTACKS_POINTS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.FAILED_ATTACKER_ATTACKS_POINTS), + BA_HONOUR_POINTS_REWARD(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.HONOUR_POINTS_REWARD), + BA_BASE_POINTS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.BASE_POINTS), + + LEVEL_UP_CONTINUE(WidgetID.LEVEL_UP_GROUP_ID, WidgetID.LevelUp.CONTINUE), + + THEATRE_OF_BLOOD_PARTY(WidgetID.THEATRE_OF_BLOOD_PARTY_GROUP_ID, WidgetID.TheatreOfBloodParty.CONTAINER), + + LIGHT_BOX_BUTTON_CONTAINER(WidgetID.LIGHT_BOX_GROUP_ID, WidgetID.LightBox.LIGHT_BOX_BUTTON_CONTAINER), + + THEATRE_OF_BLOOD_HEALTH_ORBS(WidgetID.THEATRE_OF_BLOOD_GROUP_ID, WidgetID.TheatreOfBlood.ORB_BOX), + THEATRE_OF_BLOOD_BOSS_HEALTH(WidgetID.THEATRE_OF_BLOOD_GROUP_ID, WidgetID.TheatreOfBlood.BOSS_HEALTH_BAR), + THEATRE_OF_BLOOD_RAIDING_PARTY(WidgetID.THEATRE_OF_BLOOD_GROUP_ID, WidgetID.TheatreOfBlood.RAIDING_PARTY), + + WORLD_SWITCHER_CONTAINER(WidgetID.WORLD_SWITCHER_GROUP_ID, WidgetID.WorldSwitcher.CONTAINER), + + WORLD_SWITCHER_LOGOUT_BUTTON(WidgetID.WORLD_SWITCHER_GROUP_ID, WidgetID.WorldSwitcher.LOGOUT_BUTTON), + FOSSIL_MUSHROOM_TELEPORT(WidgetID.FOSSIL_ISLAND_MUSHROOM_TELE_GROUP_ID, WidgetID.FossilMushroomTeleport.ROOT), FOSSIL_MUSHROOM_HOUSE(WidgetID.FOSSIL_ISLAND_MUSHROOM_TELE_GROUP_ID, WidgetID.FossilMushroomTeleport.HOUSE_ON_HILL), FOSSIL_MUSHROOM_VALLEY(WidgetID.FOSSIL_ISLAND_MUSHROOM_TELE_GROUP_ID, WidgetID.FossilMushroomTeleport.VERDANT_VALLEY), FOSSIL_MUSHROOM_SWAMP(WidgetID.FOSSIL_ISLAND_MUSHROOM_TELE_GROUP_ID, WidgetID.FossilMushroomTeleport.SWAMP), FOSSIL_MUSHROOM_MEADOW(WidgetID.FOSSIL_ISLAND_MUSHROOM_TELE_GROUP_ID, WidgetID.FossilMushroomTeleport.MUSHROOM_MEADOW), - MINIGAME_TELEPORT_BUTTON(WidgetID.MINIGAME_TAB_ID, WidgetID.Minigames.TELEPORT_BUTTON), - PVP_FOG_OVERLAY(WidgetID.PVP_GROUP_ID, WidgetID.Pvp.FOG_OVERLAY), - PVP_CONTAINER(WidgetID.PVP_GROUP_ID, WidgetID.Pvp.PVP_WIDGET_CONTAINER), - - PVP_SKULL_CONTAINER(WidgetID.PVP_GROUP_ID, WidgetID.Pvp.SKULL_CONTAINER), PVP_SKULL(WidgetID.PVP_GROUP_ID, WidgetID.Pvp.SKULL), PVP_ATTACK_RANGE(WidgetID.PVP_GROUP_ID, WidgetID.Pvp.ATTACK_RANGE), - PVP_WORLD_SAFE_ZONE(WidgetID.PVP_GROUP_ID, WidgetID.Pvp.SAFE_ZONE), - - PVP_WILDERNESS_LEVEL(WidgetID.PVP_GROUP_ID, WidgetID.Pvp.WILDERNESS_LEVEL), - - PVP_BOUNTY_HUNTER_INFO(WidgetID.PVP_GROUP_ID, WidgetID.Pvp.BOUNTY_HUNTER_INFO), - PVP_KILLDEATH_COUNTER(WidgetID.PVP_GROUP_ID, WidgetID.Pvp.KILLDEATH_RATIO), SPELLBOOK(WidgetID.SPELLBOOK_GROUP_ID, 0), SPELLBOOK_FILTERED_BOUNDS(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.SpellBook.FILTERED_SPELLS_BOUNDS), /* STANDARD SPELL BOOK WIDGETS*/ - SPELL_LUMBRIDGE_HOME_TELEPORT(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.SpellBook.LUMBRIDGE_HOME_TELEPORT), SPELL_WIND_STRIKE(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.SpellBook.WIND_STRIKE), SPELL_CONFUSE(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.SpellBook.CONFUSE), SPELL_ENCHANT_CROSSBOW_BOLT(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.SpellBook.ENCHANT_CROSSBOW_BOLT), @@ -737,12 +782,10 @@ public enum WidgetInfo SPELL_CARRALLANGER_TELEPORT(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.SpellBook.CARRALLANGER_TELEPORT), SPELL_ANNAKARL_TELEPORT(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.SpellBook.ANNAKARL_TELEPORT), SPELL_GHORROCK_TELEPORT(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.SpellBook.GHORROCK_TELEPORT), - SPELL_EDGEVILLE_HOME_TELEPORT(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.SpellBook.EDGEVILLE_HOME_TELEPORT), SPELL_BOUNTY_TARGET_TELEPORT(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.SpellBook.BOUNTY_TARGET_TELEPORT), /* END OF ANCIENT SPELL BOOK WIDGETS*/ /* LUNAR SPELL BOOK WIDGETS*/ - SPELL_LUNAR_HOME_TELEPORT(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.SpellBook.LUNAR_HOME_TELEPORT), SPELL_VENGEANCE_OTHER(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.SpellBook.VENGEANCE_OTHER), SPELL_VENGEANCE(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.SpellBook.VENGEANCE), SPELL_BOUNTY_TARGET_TELEPORT3(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.SpellBook.BOUNTY_TARGET_TELEPORT), @@ -790,8 +833,6 @@ public enum WidgetInfo /* END OF LUNAR SPELL BOOK WIDGETS*/ SPELL_TOOLTIP(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.SpellBook.TOOLTIP), /* ARCEUUS SPELL BOOK WIDGETS*/ - SPELL_KOUREND_HOME_TELEPORT(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.StandardSpellBook.KOUREND_HOME_TELEPORT), - SPELL_ARCEUUS_HOME_TELEPORT(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.SpellBook.ARCEUUS_HOME_TELEPORT), SPELL_BATTLEFRONT_TELEPORT(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.SpellBook.BATTLEFRONT_TELEPORT), SPELL_REANIMATE_GOBLIN(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.SpellBook.REANIMATE_GOBLIN), SPELL_REANIMATE_MONKEY(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.SpellBook.REANIMATE_MONKEY), @@ -817,25 +858,10 @@ public enum WidgetInfo SPELL_REANIMATE_DRAGON(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.SpellBook.REANIMATE_DRAGON), /* END OF ARCEUUS SPELL BOOK WIDGETS*/ - KOUREND_FAVOUR_OVERLAY(WidgetID.KOUREND_FAVOUR_GROUP_ID, WidgetID.KourendFavour.KOUREND_FAVOUR_OVERLAY), - ZEAH_MESS_HALL_COOKING_DISPLAY(WidgetID.ZEAH_MESS_HALL_GROUP_ID, WidgetID.Zeah.MESS_HALL_COOKING_DISPLAY), - - LOOTING_BAG_CONTAINER(WidgetID.LOOTING_BAG_GROUP_ID, WidgetID.LootingBag.LOOTING_BAG_INVENTORY), - - SKOTIZO_CONTAINER(WidgetID.SKOTIZO_GROUP_ID, WidgetID.Skotizo.CONTAINER), - - MULTICOMBAT_FIXED(WidgetID.FIXED_VIEWPORT_GROUP_ID, WidgetID.FixedViewport.MULTICOMBAT_INDICATOR), MULTICOMBAT_RESIZEABLE(WidgetID.RESIZABLE_VIEWPORT_BOTTOM_LINE_GROUP_ID, WidgetID.ResizableViewport.MULTICOMBAT_INDICATOR), FULLSCREEN_MAP_ROOT(WidgetID.FULLSCREEN_CONTAINER_TLI, WidgetID.FullScreenMap.ROOT), - QUESTLIST_BOX(WidgetID.QUESTLIST_GROUP_ID, WidgetID.QuestList.BOX), - QUESTLIST_CONTAINER(WidgetID.QUESTLIST_GROUP_ID, WidgetID.QuestList.CONTAINER), - QUESTLIST_SCROLLBAR(WidgetID.QUESTLIST_GROUP_ID, WidgetID.QuestList.SCROLLBAR), - QUESTLIST_FREE_CONTAINER(WidgetID.QUESTLIST_GROUP_ID, WidgetID.QuestList.FREE_CONTAINER), - QUESTLIST_MEMBERS_CONTAINER(WidgetID.QUESTLIST_GROUP_ID, WidgetID.QuestList.MEMBERS_CONTAINER), - QUESTLIST_MINIQUEST_CONTAINER(WidgetID.QUESTLIST_GROUP_ID, WidgetID.QuestList.MINIQUEST_CONTAINER), - MUSICTAB_INTERFACE(WidgetID.MUSICTAB_GROUP_ID, 1), MUSICTAB_SONG_BOX(WidgetID.MUSICTAB_GROUP_ID, 2), MUSICTAB_ALL_SONGS(WidgetID.MUSICTAB_GROUP_ID, 3), @@ -884,16 +910,6 @@ public enum WidgetInfo XP_DROP_6(WidgetID.EXPERIENCE_DROP_GROUP_ID, WidgetID.ExperienceDrop.DROP_6), XP_DROP_7(WidgetID.EXPERIENCE_DROP_GROUP_ID, WidgetID.ExperienceDrop.DROP_7), - SEED_VAULT_TITLE_CONTAINER(WidgetID.SEED_VAULT_GROUP_ID, WidgetID.SeedVault.TITLE_CONTAINER), - SEED_VAULT_ITEM_CONTAINER(WidgetID.SEED_VAULT_GROUP_ID, WidgetID.SeedVault.ITEM_CONTAINER), - SEED_VAULT_ITEM_TEXT(WidgetID.SEED_VAULT_GROUP_ID, WidgetID.SeedVault.ITEM_TEXT), - SEED_VAULT_INVENTORY_ITEMS_CONTAINER(WidgetID.SEED_VAULT_INVENTORY_GROUP_ID, WidgetID.SeedVault.INVENTORY_ITEM_CONTAINER), - - SETTINGS_SIDE_CAMERA_ZOOM_SLIDER_TRACK(WidgetID.SETTINGS_SIDE_GROUP_ID, WidgetID.SettingsSide.CAMERA_ZOOM_SLIDER_TRACK), - SETTINGS_SIDE_MUSIC_SLIDER(WidgetID.SETTINGS_SIDE_GROUP_ID, WidgetID.SettingsSide.MUSIC_SLIDER), - SETTINGS_SIDE_SOUND_EFFECT_SLIDER(WidgetID.SETTINGS_SIDE_GROUP_ID, WidgetID.SettingsSide.SOUND_EFFECT_SLIDER), - SETTINGS_SIDE_AREA_SOUND_SLIDER(WidgetID.SETTINGS_SIDE_GROUP_ID, WidgetID.SettingsSide.AREA_SOUND_SLIDER), - JEWELLERY_BOX_DUEL_RING(WidgetID.JEWELLERY_BOX_GROUP_ID, WidgetID.JewelBox.DUEL_RING), JEWELLERY_BOX_GAME_NECK(WidgetID.JEWELLERY_BOX_GROUP_ID, WidgetID.JewelBox.GAME_NECK), JEWELLERY_BOX_COMB_BRAC(WidgetID.JEWELLERY_BOX_GROUP_ID, WidgetID.JewelBox.COMB_BRAC), @@ -905,10 +921,6 @@ public enum WidgetInfo OPTIONS_SOUND_EFFECT_SLIDER(WidgetID.OPTIONS_GROUP_ID, WidgetID.Options.SOUND_EFFECT_SLIDER), OPTIONS_AREA_SOUND_SLIDER(WidgetID.OPTIONS_GROUP_ID, WidgetID.Options.AREA_SOUND_SLIDER), - ACHIEVEMENT_DIARY_CONTAINER(WidgetID.ACHIEVEMENT_DIARY_GROUP_ID, WidgetID.AchievementDiary.CONTAINER), - - SKILLS_CONTAINER(WidgetID.SKILLS_GROUP_ID, WidgetID.Skills.CONTAINER), - TRADING_WITH(WidgetID.PLAYER_TRADE_SCREEN_GROUP_ID, WidgetID.TradeScreen.FIRST_TRADING_WITH), SECOND_TRADING_WITH(WidgetID.PLAYER_TRADE_CONFIRM_GROUP_ID, WidgetID.TradeScreen.SECOND_TRADING_WITH), SECOND_TRADING_WITH_ACCEPT_BUTTON(WidgetID.PLAYER_TRADE_CONFIRM_GROUP_ID, WidgetID.TradeScreen.SECOND_ACCEPT_FUNC), @@ -920,14 +932,9 @@ public enum WidgetInfo SECOND_TRADING_WITH_MY_ITEMS(WidgetID.PLAYER_TRADE_CONFIRM_GROUP_ID, WidgetID.TradeScreen.SECOND_MY_ITEMS), SECOND_TRADING_WITH_THEIR_ITEMS(WidgetID.PLAYER_TRADE_CONFIRM_GROUP_ID, WidgetID.TradeScreen.SECOND_THEIR_ITEMS), - GAUNTLET_TIMER_CONTAINER(WidgetID.GAUNTLET_TIMER_GROUP_ID, WidgetID.GauntletTimer.CONTAINER), GAUNTLET_MAP(WidgetID.GAUNTLET_MAP_GROUP_ID, WidgetID.GauntletMap.CONTAINER), - HALLOWED_SEPULCHRE_TIMER_CONTAINER(WidgetID.HALLOWED_SEPULCHRE_TIMER_GROUP_ID, WidgetID.HallowedSepulchreTimer.CONTAINER), - - HEALTH_OVERLAY_BAR(WidgetID.HEALTH_OVERLAY_BAR_GROUP_ID, WidgetID.EncounterHealthBar.CONTAINER), - SETTINGS_INIT(WidgetID.SETTINGS_GROUP_ID, WidgetID.Settings.INIT), - TRAILBLAZER_AREA_TELEPORT(WidgetID.TRAILBLAZER_AREAS_GROUP_ID, WidgetID.TrailblazerAreas.TELEPORT), + SHOP_ITEMS_CONTAINER(WidgetID.SHOP_GROUP_ID, WidgetID.Shop.ITEMS_CONTAINER), ; private final int groupId; @@ -979,11 +986,6 @@ public enum WidgetInfo return groupId << 16 | childId; } - public static int PACK(int groupId, int childId) - { - return groupId << 16 | childId; - } - /** * Utility method that converts an ID returned by {@link #getId()} back * to its group ID. @@ -1007,4 +1009,17 @@ public enum WidgetInfo { return id & 0xFFFF; } + + /** + * Packs the group and child IDs into a single integer. + * + * @param groupId the group ID + * @param childId the child ID + * @return the packed ID + */ + public static int PACK(int groupId, int childId) + { + return groupId << 16 | childId; + } + } diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetModalMode.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetModalMode.java index 30a8d875ae..9c875fa3fd 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetModalMode.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetModalMode.java @@ -29,4 +29,4 @@ public class WidgetModalMode public static final int MODAL_NOCLICKTHROUGH = 0; public static final int NON_MODAL = 1; public static final int MODAL_CLICKTHROUGH = 3; -} \ No newline at end of file +} diff --git a/runelite-client/runelite-client.gradle.kts b/runelite-client/runelite-client.gradle.kts index deccc7b0f3..cfc8667c28 100644 --- a/runelite-client/runelite-client.gradle.kts +++ b/runelite-client/runelite-client.gradle.kts @@ -83,6 +83,7 @@ dependencies { implementation(project(":http-api")) implementation(group = "net.runelite.gluegen", name = "gluegen-rt", version = "2.4.0-rc-20200429") implementation(group = "net.runelite.jogl", name = "jogl-all", version = "2.4.0-rc-20200429") + implementation(group = "net.runelite.jocl", name = "jocl", version = "1.0") runtimeOnly(group = "org.pushing-pixels", name = "radiance-trident", version = "2.5.1") runtimeOnly(project(":runescape-api")) @@ -94,6 +95,8 @@ dependencies { runtimeOnly(group = "net.runelite.jogl", name = "jogl-all", version = "2.4.0-rc-20200429", classifier = "natives-windows-amd64") runtimeOnly(group = "net.runelite.jogl", name = "jogl-all", version = "2.4.0-rc-20200429", classifier = "natives-windows-i586") runtimeOnly(group = "net.runelite.jogl", name = "jogl-all", version = "2.4.0-rc-20200429", classifier = "natives-macosx-universal") + runtimeOnly(group = "net.runelite.jocl", name = "jocl", version = "1.0", classifier = "macos-x64") + runtimeOnly(group = "net.runelite.jocl", name = "jocl", version = "1.0", classifier = "macos-arm64") testAnnotationProcessor(group = "org.projectlombok", name = "lombok", version = "1.18.16") diff --git a/runelite-client/src/main/java/com/openosrs/client/OpenOSRS.java b/runelite-client/src/main/java/com/openosrs/client/OpenOSRS.java index e2e0d25071..8430967ed5 100644 --- a/runelite-client/src/main/java/com/openosrs/client/OpenOSRS.java +++ b/runelite-client/src/main/java/com/openosrs/client/OpenOSRS.java @@ -1,13 +1,33 @@ package com.openosrs.client; import java.io.File; +import java.io.IOException; +import java.util.Properties; import java.util.UUID; public class OpenOSRS { public static final File OPENOSRS_DIR = new File(System.getProperty("user.home"), ".openosrs"); public static final File EXTERNALPLUGIN_DIR = new File(OPENOSRS_DIR, "plugins"); - public static final String SYSTEM_VERSION = "0.0.1"; + public static final String SYSTEM_VERSION; public static String uuid = UUID.randomUUID().toString(); + + static + { + Properties properties = new Properties(); + try + { + properties.load(OpenOSRS.class.getResourceAsStream("/openosrs.properties")); + } + catch (IOException e) + { + e.printStackTrace(); + } + SYSTEM_VERSION = properties.getProperty("oprs.version", "0.0.0"); + } + + public static void preload() + { + } } diff --git a/runelite-client/src/main/java/com/openosrs/client/config/OpenOSRSConfig.java b/runelite-client/src/main/java/com/openosrs/client/config/OpenOSRSConfig.java index 9c416f5708..88faf46cb5 100644 --- a/runelite-client/src/main/java/com/openosrs/client/config/OpenOSRSConfig.java +++ b/runelite-client/src/main/java/com/openosrs/client/config/OpenOSRSConfig.java @@ -35,7 +35,7 @@ import net.runelite.client.config.ConfigItem; import net.runelite.client.config.Keybind; import net.runelite.client.config.Range; import net.runelite.client.config.Units; -import com.openosrs.client.plugins.ExternalPluginManager; +import net.runelite.client.plugins.OPRSExternalPluginManager; @ConfigGroup("openosrs") public interface OpenOSRSConfig extends Config @@ -106,22 +106,11 @@ public interface OpenOSRSConfig extends Config return true; } - @ConfigItem( - keyName = "keyboardPin", - name = "Keyboard bank pin", - description = "Enables you to type your bank pin", - position = 22 - ) - default boolean keyboardPin() - { - return false; - } - @ConfigItem( keyName = "detachHotkey", name = "Detach Cam", - description = "Detach Camera hotkey, press this and it will activate detatched camera.", - position = 23 + description = "Detach Camera hotkey, press this and it will activate detached camera.", + position = 22 ) default Keybind detachHotkey() { @@ -136,7 +125,7 @@ public interface OpenOSRSConfig extends Config ) default String getExternalRepositories() { - return ExternalPluginManager.DEFAULT_PLUGIN_REPOS; + return OPRSExternalPluginManager.DEFAULT_PLUGIN_REPOS; } @ConfigItem( diff --git a/runelite-client/src/main/java/com/openosrs/client/events/ExternalPluginChanged.java b/runelite-client/src/main/java/com/openosrs/client/events/OPRSPluginChanged.java similarity index 94% rename from runelite-client/src/main/java/com/openosrs/client/events/ExternalPluginChanged.java rename to runelite-client/src/main/java/com/openosrs/client/events/OPRSPluginChanged.java index c7bc255929..3dc10eeddf 100644 --- a/runelite-client/src/main/java/com/openosrs/client/events/ExternalPluginChanged.java +++ b/runelite-client/src/main/java/com/openosrs/client/events/OPRSPluginChanged.java @@ -25,11 +25,10 @@ package com.openosrs.client.events; import lombok.Data; -import net.runelite.api.events.Event; import net.runelite.client.plugins.Plugin; @Data -public class ExternalPluginChanged implements Event +public class OPRSPluginChanged { private final String pluginId; private final Plugin plugin; diff --git a/runelite-client/src/main/java/com/openosrs/client/events/ExternalRepositoryChanged.java b/runelite-client/src/main/java/com/openosrs/client/events/OPRSRepositoryChanged.java similarity index 94% rename from runelite-client/src/main/java/com/openosrs/client/events/ExternalRepositoryChanged.java rename to runelite-client/src/main/java/com/openosrs/client/events/OPRSRepositoryChanged.java index ff4e46c795..c356d89539 100644 --- a/runelite-client/src/main/java/com/openosrs/client/events/ExternalRepositoryChanged.java +++ b/runelite-client/src/main/java/com/openosrs/client/events/OPRSRepositoryChanged.java @@ -25,10 +25,9 @@ package com.openosrs.client.events; import lombok.Data; -import net.runelite.api.events.Event; @Data -public class ExternalRepositoryChanged implements Event +public class OPRSRepositoryChanged { private final String owner; private final boolean added; diff --git a/runelite-client/src/main/java/com/openosrs/client/game/Sound.java b/runelite-client/src/main/java/com/openosrs/client/game/Sound.java new file mode 100644 index 0000000000..27ca3e5111 --- /dev/null +++ b/runelite-client/src/main/java/com/openosrs/client/game/Sound.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2021, ThatGamerBlue + * 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 com.openosrs.client.game; + +import java.io.File; +import java.net.URL; +import lombok.EqualsAndHashCode; +import lombok.SneakyThrows; +import lombok.Value; +import net.runelite.client.RuneLite; + +public abstract class Sound +{ + public abstract URL getPath(); + + // TODO: these inner classes should probably be removed + + @Value + @EqualsAndHashCode(callSuper = true) // stop the warning + static class SoundJarResource extends Sound + { + String path; + + @Override + public URL getPath() + { + return RuneLite.class.getResource(path); + } + } + + @Value + @EqualsAndHashCode(callSuper = true) // stop the warning + static class SoundFileResource extends Sound + { + File file; + + @Override + @SneakyThrows + public URL getPath() + { + return file.toURI().toURL(); + } + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/com/openosrs/client/game/SoundManager.java b/runelite-client/src/main/java/com/openosrs/client/game/SoundManager.java new file mode 100644 index 0000000000..0c1330cd5b --- /dev/null +++ b/runelite-client/src/main/java/com/openosrs/client/game/SoundManager.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2021, ThatGamerBlue + * 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 com.openosrs.client.game; + +import java.io.IOException; +import javax.inject.Singleton; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.BooleanControl; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.FloatControl; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.SourceDataLine; +import javax.sound.sampled.UnsupportedAudioFileException; + +@Singleton +public class SoundManager +{ + public void play(final Sound sound) + { + new Thread(() -> + { + try (AudioInputStream in = AudioSystem.getAudioInputStream(sound.getPath())) + { + AudioFormat outFormat = SoundManager.this.getOutFormat(in.getFormat()); + DataLine.Info info = new DataLine.Info(SourceDataLine.class, outFormat); + try (SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info)) + { + if (line != null) + { + line.open(outFormat, 2200); + if (line.isControlSupported(FloatControl.Type.MASTER_GAIN)) + { + int volume = 50; + FloatControl gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); + BooleanControl muteControl = (BooleanControl) line.getControl(BooleanControl.Type.MUTE); + muteControl.setValue(false); + gainControl.setValue((float) (Math.log((double) volume / 100.0) / Math.log(10.0) * 20.0)); + } + line.start(); + stream(AudioSystem.getAudioInputStream(outFormat, in), line); + line.drain(); + line.stop(); + } + } + } + catch (IOException | LineUnavailableException | UnsupportedAudioFileException e) + { + throw new IllegalStateException(e); + } + }).start(); + } + + private AudioFormat getOutFormat(AudioFormat inFormat) + { + int ch = inFormat.getChannels(); + float rate = inFormat.getSampleRate(); + return new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, rate, 16, ch, ch * 2, rate, false); + } + + private void stream(AudioInputStream in, SourceDataLine line) throws IOException + { + byte[] buffer = new byte[2200]; + int n = 0; + while (n != -1) + { + line.write(buffer, 0, n); + n = in.read(buffer, 0, buffer.length); + } + } + +} \ No newline at end of file diff --git a/runelite-client/src/main/java/com/openosrs/client/game/WorldLocation.java b/runelite-client/src/main/java/com/openosrs/client/game/WorldLocation.java new file mode 100644 index 0000000000..0782f79406 --- /dev/null +++ b/runelite-client/src/main/java/com/openosrs/client/game/WorldLocation.java @@ -0,0 +1,921 @@ +/* + * Copyright (c) 2019, ST0NEWALL + * Copyright (c) 2020, Macweese + * 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 com.openosrs.client.game; + +import com.google.common.collect.ImmutableMap; +import java.util.Arrays; +import java.util.Collection; +import java.util.Map; +import java.util.stream.Collectors; +import lombok.Getter; +import net.runelite.api.coords.WorldArea; +import net.runelite.api.coords.WorldPoint; +import net.runelite.client.util.PvPUtil; + +/* + * Enums sorted alphabetically by main regions (Kingdoms) and then their sub-regions or notable features + * Example: + * Wilderness + * Mage Bank + */ +public enum WorldLocation +{ + + /*- + * Ape Atoll + * Crash Island + * Marim + */ + APE_ATOLL_TEMPLE("Ape Atoll Temple", new Location(2784, 2802, 2810, 2770), 0), + APE_ATOLL_GATE("Ape Atoll Gate", new Location(2712, 2761, 2730, 2749), 0), + APE_ATOLL_GLIDER("Ape Atoll Glider", new Location(2707, 2808, 2719, 2797), 0), + APE_ATOLL_TEAKS("Ape Atoll Teak Trees", new Location(2756, 2708, 2791, 2689), 0), + CRASH_ISLAND("Crash Island", new Location(2881, 2749, 2943, 2691), 0), + KRUK_DUNGEON_1("Monkey Madness 2 Dungeon", new Location(2689, 9150, 2815, 9088), 0), + KRUK_DUNGEON_2("Monkey Madness 2 Dungeon", new Location(2689, 9150, 2815, 9088), 1), + KRUK_DUNGEON_3("Monkey Madness 2 Dungeon", new Location(2309, 9277, 2454, 9131), 1), + MARIM_NORTH("North Marim", new Location(2731, 2804, 2783, 2786), 0), + MARIM_SOUTH("South Marim", new Location(2731, 2785, 2783, 2762), 0), + MONKEY_MADNESS_DUNGEON("Monkey Madness 1 Dungeon", new Location(2689, 9150, 2815, 9088), 0), + + /*- + * Asgarnia + * Faldor + * Burthorpe + * Edgeville + * Entrana + * Port Sarim + * Rimmington + * Taverly + */ + ASGARNIAN_ICE_DUNGEON_WYVERNS("Asgarnian Ice Dungeon - Skeletal Wyverns", new Location(3022, 9559, 3070, 9537), 0), + ASGARNIAN_ICE_DUNGEON_ICE_MONSTERS("Asgarnian Ice Dungeon - Ice Warriors & Ice Giants", new Location(3043, 9587, 3065, 9570), 0), + ASGARNIAN_ICE_DUNGEON_PIRATES("Asgarnian Ice Dungeon - Pirates", new Location(2986, 9568, 2999, 9585), 0), + BURTHOPRE_GAMES_TELEPORT("Burthorpe Games Tele", new Location(2890, 3557, 2907, 3549), 0), + CRAFTING_GUILD("Crafting Guild", new Location(2921, 3292, 2944, 3275), 0), + EDGEVILLE_MONASTERY("Edgeville Monastery", new Location(3044, 3507, 3060, 3471), 0), + FALADOR_BANK("Fally Bank", new Location(2943, 3372, 2949, 3358), 0), + FALADOR_CENTER("Fally Center", new Location(2959, 3385, 2972, 3374), 0), + FALADOR_EAST_BANK("Fally East Bank", new Location(3008, 3358, 3021, 3353), 0), + FALADOR_FARM("Falador Farm", new Location(3014, 3314, 3067, 3283), 0), + FALADOR_PARK("Fally Park", new Location(2982, 3390, 3025, 3368), 0), + FALADOR_PARTYROOM("Falador Partyroom", new Location(3035, 3386, 3056, 3370), 0), + FALADOR_RESPAWN("Fally Respawn", new Location(2957, 3355, 2998, 3325), 0), + GOBLIN_VILLAGE("Goblin Village", new Location(2948, 3516, 2963, 3493), 0), + HEROES_GUILD("Heroes' Guild", new Location(2881, 3517, 2902, 3504), 0), + HEROES_GUILD_DUNGEON("Heroes' Guild Dungeon", new Location(2885, 9918, 2945, 9882), 0), + ICE_MOUNTAIN("Ice Mountain", new Location(3001, 3508, 3024, 3463), 0), + MIND_ATLAR("Mind Altar", new Location(2970, 3520, 2990, 3509), 0), + MUDSKIPPER_POINT("Mudskipper point", new Location(2980, 3145, 3011, 3104), 0), + PORT_SARIM("Port Sarim", new Location(3024, 3250, 3055, 3192), 0), + PORT_SARIM_JAIL("Port Sarim Jail", new Location(3009, 3193, 3021, 3178), 0), + RIMMINGTON("Rimmington", new Location(2946, 3213, 2970, 3188), 0), + RIMMINGTON_DOCKS("Rimmington Docks", new Location(2905, 3228, 2922, 3222), 0), + RIMMINGTON_MINE("Rimmington Mine", new Location(2968, 3252, 2991, 3230), 0), + RIMMINGTON_PORTAL("Rimmington Portal", new Location(2946, 3228, 2960, 3218), 0), + ROGUES_DEN("Rogue's Den", new Location(3036, 4957, 3067, 4986), 1), + TAVERLY("Taverly", new Location(2880, 3442, 2917, 3409), 0), + TAVERLY_DUNGEON_BLACK_KNGIHTS("Taverly Dungeon - Black Knights", new Location(2883, 9717, 2939, 9667), 0), + TAVERLY_DUNGEON_HILL_GIANTS("Taverly Dungeon - Hill Giants", new Location(2895, 9743, 2920, 9718), 0), + TAVERLY_DUNGEON_BLACK_DRAGONS("Taverly Dungeon - Black Dragons", new Location(2812, 9836, 2846, 9822), 0), + TAVERLY_DUNGEON_HELLHOUNDS("Taverly Dungeon - Hell Hounds", new Location(2847, 9854, 2873, 9822), 0), + TAVERLY_DUNGEON_BLUE_DRAGONS("Taverly Dungeon - Blue Dragons", new Location(2890, 9778, 2923, 9813), 0), + TAVERLY_DUNGEON_BLACK_DEMONS("Taverly Dungeon - Black Demons", new Location(2844, 9800, 2873, 9773), 0), + TAVERLY_DUNGEON_POISON_SPIDERS("Taverly Dungeon - Poison Spiders", new Location(3010, 4756, 3068, 4803), 0), + TAVERLY_DUNGEON_CHAOS_DRUIDS("Taverly Dungeon - Chaos Druids", new Location(2915, 9856, 2944, 9833), 0), + TAVERLY_DUNGEON_LESSER_DEMONS("Taverly Dungeon - Lesser Demons", new Location(2924, 9813, 2946, 9777), 0), + TAVERLY_DUNGEON_MAGIC_AXES("Taverly Dungeon - Magic Axes", new Location(2947, 9798, 2971, 9769), 0), + TAVERLY_DUNGEON_CHAOS_DWARVES("Taverly Dungeon - Chaos Dwarves", new Location(2920, 9776, 2938, 9745), 0), + TAVERLY_DUNGEON_MAIN_CORRIDOR("Taverly Dungeon - Main Corridor", new Location(2880, 9793, 2889, 9850), 0), + TAVERLY_GATE("Taverly Gate", new Location(2931, 3456, 2944, 3444), 0), + TAVERLY_POH_PORTAL("Taverly POH Portal", new Location(2885, 3471, 2899, 3458), 0), + WARRIORS_GUILD("Warriors' Guild", new Location(2838, 3536, 2876, 3555), 0), + WARRIORS_GUILD_BASEMENT("Warriors' Guild Basement (Dragon Defender)", new Location(2904, 9974, 2941, 9956), 0), + + /*- + * Entrana + */ + ENTRANA_BALLOON("Entrana Balloon", new Location(2803, 3359, 2815, 3347), 0), + ENTRANA_CHURCH("Entrana Church", new Location(2840, 3356, 2858, 3341), 0), + ENTRANA_DOCKS("Entrana Docks", new Location(2825, 3338, 2847, 3328), 0), + ENTRANA_NORTH("Entrana (North Portion)", new Location(2541, 2875, 2595, 2837), 0), + + /*- + * Feldip Hills + * Corsair Cove + * Gu'Tanoth + */ + CORSAIR_COVE("Corsair Cove", new Location(2541, 2875, 2595, 2837), 0), + CORSAIR_RESOURCE_AREA("Corsair Resource Area", new Location(2453, 2905, 2488, 2883), 0), + FELDIP_HILLS_GLIDER("Feldip Hills Glider", new Location(2536, 2975, 2546, 2965), 0), + FELDIP_HILLS_RED_CHINS("Feldip Hills Red Chins", new Location(2525, 2935, 2561, 2902), 0), + GU_TANOTH("Gu'Tanoth", new Location(2497, 3060, 2558, 3008), 0), + MYTHS_GUILD("Myth's Guild", new Location(2470, 2872, 2442, 2834), 0), + + /* + * Fossil Island + */ + MUSEUM_CAMP("Fossil Island Museum Camp", new Location(3708, 3797, 3751, 3833), 0), + FOSSIL_ISLAND_HOUSE_ON_THE_HILL("House on the Hill (Fossil Island)", new Location(3747, 3891, 3795, 3855), 0), + FOSSIL_ISLAND_MUSHROOM_FOREST("Fossil Island Mushroom Forest (Herbiboar)", new Location(3670, 3894, 3707, 3814), 0), + FOSSIL_ISLAND_SWAMP_NORTH("Fossil Island Swamp (North half)", new Location(3707, 3758, 3643, 3696), 0), + FOSSIL_ISLAND_SWAMP_SOUTH("Fossil Island Swamp (South half)", new Location(3707, 3813, 3643, 3759), 0), + FOSSIL_ISLAND_VERDANT_VALLEY("Fossil Island Verdant Valley (South East Island)", new Location(3670, 3894, 3707, 3814), 0), + FOSSIL_ISLAND_VOLCANO_BANK("Fossil Island Volcano Bank", new Location(3807, 3818, 3825, 3800), 0), + + /*- + * Fremennik Province + * Fremennik Isles (Neitiznot & Jatizo) + * Fremennik Slayer Dungeon + * Lunar Isle + * Miscellania and Etceteria + * Rellekka + * Waterbirth Island + */ + ETCETERIA("Etceteria", new Location(2626, 3904, 2571, 3861), 0), + ETCETERIA_DOCKS("Etceteria Docks", new Location(2571, 3904, 2626, 3861), 0), + FREMENNIK_BASILISK_KNIGHT_DUNGEON("Fremennik Basilisk Knight Dungeon", new Location(2398, 10468, 2496, 10370), 0), + FREMENNIK_SLAYER_DUNGEON("Fremennik Slayer Dungeon", new Location(2771, 10023, 2811, 9989), 0), + FREMENNIK_SLAYER_DUNGEON_BASILISKS("Fremennik Slayer Dungeon - Baslisks", new Location(2734, 10015, 2751, 9988), 0), + FREMENNIK_SLAYER_DUNGEON_ENTRANCE("Fremennik Slayer Dungeon Entrance", new Location(2776, 3604, 2801, 3626), 0), + FREMENNIK_SLAYER_DUNGEON_JELLIES("Fremennik Slayer Dungeon - Jellies", new Location(2694, 10035, 2733, 10016), 0), + FREMENNIK_SLAYER_DUNGEON_KURASKS("Fremennik Slayer Dungeon - Kurasks", new Location(2708, 10007, 2690, 9988), 0), + FREMENNIK_SLAYER_DUNGEON_PYREFIENDS("Fremennik Slayer Dungeon - Pyrefiends", new Location(2752, 10015, 2770, 9988), 0), + FREMENNIK_SLAYER_DUNGEON_TUROTHS("Fremennik Slayer Dungeon - Turoths", new Location(2709, 10015, 2733, 9988), 0), + JATIZSO("Jatizso", new Location(2369, 3826, 2428, 3776), 0), + KELDAGRIM_EAST("Eastern Keldagrim", new Location(2884, 10236, 2943, 10181), 0), + KELDAGRIM_ENTRANCE("Keldagrim Entrance", new Location(2722, 3720, 2738, 3703), 0), + KELDAGRIM_WEST("Western Keldagrim", new Location(2819, 10236, 2875, 10182), 0), + LUNAR_ISLE_CENTRAL("Lunar Isle Central", new Location(2055, 3933, 2112, 3888), 0), + LUNAR_ISLE_EAST("Lunar Isle East", new Location(2113, 3921, 2185, 3888), 0), + LUNAR_ISLE_NORTH("Lunar Isle North", new Location(2063, 3958, 2112, 3934), 0), + LUNAR_ISLE_NORTH_EAST("Lunar Isle North East", new Location(2113, 3958, 2185, 3922), 0), + LUNAR_ISLE_SOUTH("Lunar Isle South", new Location(2057, 3887, 2112, 3843), 0), + LUNAR_ISLE_SOUTHEAST("Lunar Isle SouthEast", new Location(2113, 3887, 2185, 3843), 0), + MISCELLANIA("Miscellania", new Location(2492, 3904, 2570, 3836), 0), + MISCELLANIA_DOCKS("Miscellania Docks", new Location(2623, 3851, 2603, 3840), 0), + MOUNTAIN_CAMP("Mountain Camp", new Location(2789, 3682, 2813, 3658), 0), + NEITIZNOT("Neitiznot", new Location(2300, 3826, 2368, 3776), 0), + PIRATES_COVE("Pirate's Cove", new Location(2186, 3842, 2228, 3785), 0), + RELLEKKA_MAIN_HALL("Rellekka Main Hall", new Location(2652, 3685, 2670, 3658), 0), + RELLEKKA_MARKET("Rellekka Market", new Location(2629, 3682, 2651, 3654), 0), + RELLEKKA_NORTH_DOCKS("Rellekka North Docks", new Location(2640, 3712, 2651, 3706), 0), + RELLEKKA_NORTH_EAST("Rellekka North East", new Location(2652, 3712, 2690, 3686), 0), + RELLEKKA_POH_PORTAL("Rellekka POH Portal", new Location(2662, 3635, 2676, 3624), 0), + RELLEKKA_SOUTH_DOCKS("Rellekka South Docks", new Location(2619, 3699, 2641, 3681), 0), + RELLEKKA_ZONE("Rellekka", new Location(2600, 3708, 2690, 3645), 0), + ROCK_CRABS_EAST("Rock Crabs East (Near Keldagrim)", new Location(2691, 3738, 2730, 3713), 0), + ROCK_CRABS_WEST("Rock Crabs West (North of Rellekka)", new Location(2650, 3738, 2690, 3713), 0), + VORKATH("Vorkath", new Location(2237, 4096, 2301, 4031), 0), + WATERBIRTH_DUNGEON_ROCK_LOBSTERS("Waterbirth Dungeon - Rock Lobsters", new Location(1875, 4380, 1919, 4412), 0), + WATERBIRTH_DUNGEON_DKS_1("DKS", new Location(2886, 4473, 2941, 4424), 0), // One of these is private, not sure which + WATERBIRTH_DUNGEON_DKS_2("DKS", new Location(2886, 4409, 2941, 4361), 0), // One of these is private, not sure which + WATERBIRTH_DUNGEON_ZONE_1("Waterbirth Dungeon", new Location(2435, 10176, 2558, 10112), 0), + WATERBIRTH_DUNGEON_ZONE_2("Waterbirth Dungeon", new Location(1788, 4413, 1966, 4352), 1), + WATERBIRTH_ISLAND("Waterbirth Island", new Location(2494, 3774, 2562, 3710), 0), + + /*- + * Great Kourend + * Arceuus + * Battlefront + * Catacombs of Kourend + * Crabclaw Caves + * Forthos Dungeon + * Hosidius + * Kebos Lowlands + * Kingstown + * Kourend Woodland + * Lake Molch + * Lizardman Settlement + * Lovakengj + * Mount Karuulm + * Mount Quidamortem + * Northern Tundras + * Port Piscarilius + * Shayzien + * Wintertodt + */ + ARCEUUS("Arceuus", new Location(1620, 3780, 1739, 3708), 0), + ARCEUUS_BANK("Arceuus Bank", new Location(1620, 3754, 1639, 3735), 0), + ARCEUUS_DENSE_ESSENCE_MINE("Arceuus Dense Essence Mine", new Location(1741, 3880, 1786, 3831), 0), + ARCEUUS_LIBRARY("Arceuus Library", new Location(1605, 3833, 1662, 3781), 0), + BATTLEFRONT("Battlefront Teleport", new Location(1344, 3745, 1362, 3726), 0), + BLAST_MINE("Lovakengj Blast Mine", new Location(1467, 3888, 1513, 3840), 0), + BLOOD_ALTAR("Blood Altar", new Location(1710, 3835, 1737, 3822), 0), + CHASM_OF_FIRE("Chasm of Fire", new Location(1411, 10108, 1468, 10050), 1), + COX("CoX", new Location(1226, 3574, 1270, 3559), 0), + CRAB_CLAW_ISLE("Crab Claw Isle", new Location(1745, 3449, 1795, 3399), 0), + DARK_ALTAR("Arceuus Dark Altar", new Location(1699, 3895, 1734, 3869), 0), + FARMING_GUILD("Farming Guild", new Location(1223, 3718, 1273, 3765), 0), + FISHING_HAMLET("Fishing Hamlet (East of Wintertodt Camp)", new Location(1683, 3969, 1720, 3917), 0), + FOODHALL("Piscarilius Foodhall", new Location(1830, 3762, 1854, 3734), 0), + FORTHOS_RUINS("Forthos Ruins", new Location(1666, 3590, 1684, 3561), 0), + FORTHOS_DUNGEON_ALTAR("Forthos Dungeon - Altar", new Location(1794, 9954, 1804, 9946), 0), + FORTHOS_DUNGEON_GRUBBY_CHEST("Forthos Dungeon - Grubby Chest", new Location(1793, 9928, 1799, 9922), 0), + FORTHOS_DUNGEON_LADDER_EAST("Forthos Dungeon - East Ladder", new Location(1825, 9978, 1835, 9969), 0), + FORTHOS_DUNGEON_LADDER_WEST("Forthos Dungeon - West Ladder", new Location(1795, 9972, 1805, 9958), 0), + FORTHOS_DUNGEON_RED_DRAGONS("Forthos Dungeon - Red Dragons", new Location(1807, 9944, 1828, 9933), 0), + FORTHOS_DUNGEON_SARACHNIS("Forthos Dungeon - Sarachnis", new Location(1829, 9890, 1854, 9913), 0), + FORTHOS_DUNGEON_SPIDERS("Forthos Dungeon - Red Spiders", new Location(1830, 9968, 1848, 9947), 0), + FORTHOS_DUNGEON_UNDEAD_DRUIDS_1("Forthos Dungeon - Undead Druids", new Location(1795, 9944, 1806, 9933), 0), + FORTHOS_DUNGEON_UNDEAD_DRUIDS_2("Forthos Dungeon - Undead Druids", new Location(1806, 9973, 1814, 9958), 0), + FORTHOS_DUNGEON_ZONE("Forthos Dungeon", new Location(1789, 9985, 1858, 9914), 0), + HOSIDIUS_BANK("Hosidius Bank", new Location(1743, 3603, 1753, 3594), 0), + HOSIDIUS_FRUIT_STALLS("Hosidius Fruit Stalls", new Location(1790, 3614, 1806, 3603), 0), + HOSIDIUS_KITCHEN("Hosidius Kitchen (Bank)", new Location(1671, 3625, 1687, 3610), 0), + HOSIDIUS_PLOW_FIELD("Hosidius Plow Fields", new Location(1761, 3558, 1781, 3519), 0), + HOSIDIUS_POH_PORTAL("Hosidius POH Portal", new Location(1735, 3522, 1747, 3511), 0), + HOSIDIUS_SQUARE("Hosidius Square", new Location(1754, 3607, 1772, 3589), 0), + HOSIDIUS_VINERY("Hosidius Vinery", new Location(1799, 3573, 1816, 3537), 0), + HOSIDIUS_ZONE("Hosidius", new Location(1737, 3627, 1789, 3582), 0), + KOUREND_CASTLE("Kourend Castle", new Location(1592, 3700, 1692, 3646), 0), + KOUREND_CATACOMBS_ABYSSAL_DEMONS("Kourend Catacombs - Abyssal Demons", new Location(1667, 10101, 1683, 10082), 0), + KOUREND_CATACOMBS_BLACK_DEMONS("Kourend Catacombs - Black Demons", new Location(1713, 10073, 1724, 10086), 0), + KOUREND_CATACOMBS_BRUTAL_BLACK_DRAGONS("Kourend Catacombs - Brutal Black Dragons", new Location(1604, 10105, 1635, 10068), 0), + KOUREND_CATACOMBS_CENTER("Kourend Catacombs Center", new Location(1655, 10055, 1670, 10038), 0), + KOUREND_CATACOMBS_DUST_DEVILS("Kourend Catacombs - Dust Devils", new Location(1704, 10037, 1734, 9985), 0), + KOUREND_CATACOMBS_GREATER_DEMONS("Kourend Catacombs - Greater Demons", new Location(1684, 10105, 1724, 10087), 0), + KOUREND_CATACOMBS_NECHRYAELS("Kourend Catacombs - Nechryaels", new Location(1684, 10086, 1712, 10073), 0), + KOUREND_CATACOMBS_SOUTH("Kourend Catacombs - South", new Location(1639, 10014, 1702, 9985), 0), + KOUREND_CATACOMBS_SOUTH_WEST("Kourend Catacombs South-West Corner", new Location(1596, 10028, 1634, 9984), 0), + KOUREND_CATACOMBS_STEEL_DRAGONS("Kourend Catacombs - Steel Dragons", new Location(1599, 10066, 1630, 10029), 0), + KOUREND_CATACOMBS_ZONE("Kourend Catacombs", new Location(1595, 10106, 1735, 9984), 0), + LANDS_END("Land's End", new Location(1481, 3448, 1527, 3396), 0), + LAKE_MOLCH("Lake Molch", new Location(1357, 3643, 1377, 3624), 0), + LIZARDMAN_SHAMANS("Lizardman Shamans", new Location(1414, 3726, 1461, 3688), 0), + LOVAKENGJ("Lovakengj", new Location(1425, 3810, 1520, 3730), 0), + MOUNT_KARUULM("Mount Karuulm", new Location(1287, 3829, 1331, 3787), 0), + PISCARILIUS_ANGLERFISH("Piscarilius Angler Fishing Spot", new Location(1807, 3779, 1842, 3766), 0), + PISCARILIUS_BANK("Piscarilius Bank", new Location(1793, 3794, 1812, 3782), 0), + PISCARILIUS_PORT("Port Piscarilius", new Location(1788, 3712, 1849, 3673), 0), + PISCARILIUS_ZONE("Piscarilius", new Location(1740, 3814, 1854, 3713), 0), + SANDCRABS_BANK("Sandcrabs Bank", new Location(1706, 3475, 1730, 3455), 0), + SANDCRABS_NORTH("Sandcrabs (East of Vinery)", new Location(1848, 3572, 1884, 3532), 0), + SANDCRABS_SOUTH_1("Sandcrabs (South of Tithe Farm)", new Location(1796, 3468, 1849, 3436), 0), + SANDCRABS_SOUTH_2("Sandcrabs (South Coast)", new Location(1745, 3474, 1795, 3450), 0), + SANDCRABS_SOUTH_EAST("Sandcrabs (East of Tithe Farm)", new Location(1850, 3529, 1884, 3465), 0), + SHAYZIEN_BANK("Shayzien Bank", new Location(1494, 3622, 1515, 3611), 0), + SHAYZIEN_CRYPTS_ENTRANCE("Shayzien Crypts Entrance", new Location(1474, 3570, 1502, 3535), 0), + SHAYZIEN_INFIRMARY("Shayzien Infirmary", new Location(1565, 3574, 1590, 3604), 0), + SHAYZIEN_ZONE("Shayzien", new Location(1472, 3644, 1591, 3521), 0), + SOUL_ALTAR("Soul Altar", new Location(1804, 3869, 1834, 3841), 0), + SULPHUR_MINE("Lovakengj Sulphur Mine", new Location(1415, 3888, 1466, 3840), 0), + SULPHUR_MINE_BANK("Lovakengj Sulphur Mine Bank", new Location(1430, 3838, 1443, 3817), 0), + TITHE_FARM("Tithe Farm", new Location(1794, 3480, 1841, 3517), 0), + WINTERTODT_CAMP("Wintertodt Camp", new Location(1616, 3963, 1645, 3932), 0), + WINTERTODT_ENTRANCE("Wintertodt Entrance", new Location(1617, 3986, 1641, 3964), 0), + WINTERTODT_NORTHEAST("Wintertodt NorthEast", new Location(1630, 4027, 1651, 4008), 0), + WINTERTODT_NORTHWEST("Wintertodt NorthWest", new Location(1608, 4028, 1629, 4008), 0), + WINDERTODT_SOUTH_EAST("Windertodt South East", new Location(1630, 4007, 1651, 3987), 0), + WINTERTODT_SOUTHWEST("Wintertodt SouthWest", new Location(1608, 4007, 1629, 3987), 0), + WOODCUTTING_GUILD_BANK("Woodcutting Guild Bank", new Location(1588, 3481, 1594, 3473), 0), + WOODCUTTING_GUILD_EAST("Woodcutting Guild (East Portion)", new Location(1623, 3519, 1657, 3488), 0), + WOODCUTTING_GUILD_WEST("Woodcutting Guild (Redwoods)", new Location(1562, 3503, 1586, 3476), 0), + WOODCUTTING_GUILD_ZONE("Woodcutting Guild", new Location(1560, 3520, 1659, 3471), 0), + + /*- + * Kandarin + * Ardougne + * Battlefield + * Camelot + * Catherby + * Fishing Guild & McGrubor's Woods + * Observatory + * Ourania + * Piscatoris Fishing Colony + * Port Khazard + * Seers' Village + * Tree Gnome Stronghold + * Tree Gnome Village + * Witchaven + * Yanille + */ + ARDOUGNE_CASTLE("Ardy Castle", new Location(2567, 3311, 2591, 3283), 0), + ARDOUGNE_DOCKS("Ardy Docks", new Location(2660, 3284, 2689, 3264), 0), + ARDOUGNE_MONASTERY("Ardougne Monastery", new Location(2587, 3227, 2623, 3202), 0), + ARDOUGNE_NORTH_BANK("Ardy North Bank", new Location(2611, 3336, 2622, 3329), 0), + ARDOUGNE_SOUTH_BANK("Ardy South Bank", new Location(2645, 3288, 2659, 3279), 0), + ARDOUGNE_STALLS("Ardy Stalls", new Location(2651, 3318, 2673, 3293), 0), + ARDOUGNE_ZOO("Ardy Zoo", new Location(2598, 3288, 2636, 3265), 0), + BARBARIAN_OUTPOST("Barbarian Outpost", new Location(2517, 3580, 2557, 3540), 0), + BAXTORIAN_WATERFALL_DUNGEON("Waterfall Dungeon (Baxtorian Falls)", new Location(2556, 9861, 2594, 9918), 0), + CAMELOT_CASTLE("Camelot Castle", new Location(2743, 3481, 2775, 3468), 0), + CASTLE_WARS_BANK("Castle Wars Bank", new Location(2435, 3100, 2448, 3078), 0), + CASTLE_WARS_ZONE("Castle Wars", new Location(2435, 3127, 2474, 3074), 0), + CATHERBY("Catherby", new Location(2791, 3457, 2833, 3436), 0), + CATHERBY_DOCKS("Catherby Docks", new Location(2790, 3432, 2808, 3409), 0), + CATHERBY_FISHING_SPOTS("Catherby Fishing Spots", new Location(2834, 3441, 2862, 3425), 0), + CATHERBY_FARMING_PATCH("Catherby Farming Patch", new Location(2791, 3472, 2833, 3458), 0), + EAGLES_PEAK("Eagles' Peak", new Location(2308, 3495, 2350, 3479), 0), + FALCONRY_HUNTING_AREA("Falconry Hunting Area", new Location(2365, 3621, 2390, 3572), 0), + FISHING_GUILD("Fishing Guild", new Location(2627, 3426, 2579, 3391), 0), + FISHING_PLATFORM("Fishing Platform", new Location(2763, 3290, 2792, 3273), 0), + GNOME_AGILITY("Gnome Agility", new Location(2469, 3441, 2489, 3412), 0), + GNOME_BALL("Gnome Ball", new Location(2384, 3495, 2408, 3479), 0), + GRAND_TREE("Grand Tree", new Location(2442, 3515, 2490, 3478), 0), + KRAKEN_COVE_DUNGEON("Kraken Dungeon", new Location(2303, 10047, 2240, 9983), 0), + KRAKEN_COVE_ENTRANCE("Kraken Cove Entrance", new Location(2262, 3623, 2295, 3596), 0), + LEGENDS_GUILD("Legends' Guild", new Location(2716, 3388, 2741, 3346), 0), + LEGENDS_GUILD_DUNGEON("Legends' Guild Dungeon", new Location(2690, 9784, 2740, 9730), 0), + LIGHTHOUSE("Lighthouse", new Location(2494, 3649, 2524, 3616), 0), + MCGRUBORS_WOODS("McGrubor's Woods", new Location(2624, 3501, 2647, 3481), 0), + NIEVE("Nieve", new Location(2430, 3425, 2435, 3419), 0), + NIGHTMARE_ZONE("Nightmare Zone", new Location(2599, 3119, 2614, 3111), 0), + OBSERVATORY("Observatory", new Location(2429, 3198, 2452, 3149), 0), + OBSERVATORY_DUNGEON("Obsvervatory Dungeon", new Location(2305, 9406, 2366, 9344), 0), + OTTOS_GROTTO("Barbarian Fishing", new Location(2491, 3519, 2527, 3488), 0), + OURANIA_CAVE("ZMI", new Location(3006, 5567, 3072, 5634), 0), + THE_OUTPOST("The Outpost", new Location(2428, 3356, 2443, 3338), 0), + PISCATORIS_FISHING_COLONY("Piscatoris Fishing Colony", new Location(2302, 3708, 2364, 3653), 0), + PORT_KHAZARD("Port Khazard", new Location(2624, 3182, 2680, 3143), 0), + RANGING_GUILD("Ranging Guild", new Location(2650, 3445, 2685, 3411), 0), + RED_SALAMANDERS("Red Salamanders", new Location(2441, 3229, 2464, 3204), 0), + SEERS_VILLAGE("Seers Village", new Location(2688, 3498, 2742, 3468), 0), + SINCLAIR_MANSION("Sinclair Mansion", new Location(2723, 3584, 2756, 3552), 0), + SMOKE_DEVIL_DUNGEON("CW Smoke Devil Dungeon", new Location(2379, 9467, 2427, 9415), 0), + SMOKE_DEVIL_DUNGEON_BOSS("CW Smoke Dungeon (Boss Room)", new Location(2347, 9462, 2377, 9438), 0), + SMOKE_DEVIL_DUNGEON_ENTRANCE("Smoke Devil Dungeon Entrance", new Location(2430, 3425, 2435, 3419), 0), + TRAINING_GROUND("Training Ground (Caged Ogres)", new Location(2501, 3387, 2534, 3358), 0), + TREE_GNOME_VILLAGE("Tree Gnome Village", new Location(2514, 3175, 2547, 3158), 0), + WEST_ARDOUGNE("West Ardy", new Location(2452, 3336, 2557, 3265), 0), + WITCHAVEN("Witchaven", new Location(2704, 3267, 2741, 3295), 0), + WITCHAVEN_DUNGEON("Witchaven Dungeon", new Location(2750, 9665, 2690, 9719), 0), + WIZARDS_GUILD("Wizards Guild", new Location(2585, 3092, 2596, 3082), 0), + WHITE_WOLF_MOUNTAIN_GNOME_GLIDER("White Wolf Mountain Gnome Glider", new Location(2838, 3509, 2852, 3496), 0), + YANILLE_AGILITY_DUNGEON("Yanille Agilty Dungeon", new Location(2559, 9536, 2624, 9475), 0), + YANILE_BANK("Yanile Bank", new Location(2608, 3097, 2616, 3087), 0), + YANILLE_EAST("Yanille East", new Location(2576, 3110, 2621, 3071), 0), + YANILLE_POH_PORTAL("Yanille POH Portal", new Location(2537, 3108, 2551, 3091), 0), + YANILLE_WEST("Yanille West", new Location(2532, 3110, 2575, 3071), 0), + + /*- + * Karamja + * Brimhaven + * Cairn Isle + * Crandor & Karamja Dungeon + * Kharazi Jungle + * Mor Ul Rel (TzHaar City) + * Musa Point + * Shilo Village + * Ship Yard + * Tai Bwo Wannai + */ + BRIMHAVEN_AGILITY_ARENA("Brimhaven Agility Arena", new Location(2757, 9594, 2809, 9541), 3), + BRIMHAVEN_DOCKS("Brimhaven Docks", new Location(2758, 3241, 2777, 3220), 0), + BRIMHAVEN_DUNGEON("Brimhaven Dungeon - Main Corridor", new Location(2690, 9572, 2714, 9556), 0), + BRIMHAVEN_DUNGEON_BLACK_DEMONS("Brimhaven Dungeon - Black Demons", new Location(2694, 9495, 2726, 9475), 0), + BRIMHAVEN_DUNGEON_BRONZE_DRAGONS("Brimhaven Dungeon - Bronze Dragons", new Location(2727, 9504, 2750, 9475), 0), + BRIMHAVEN_DUNGEON_DOGS("Brimhaven Dungeon - Dogs", new Location(2653, 9530, 2675, 9509), 0), + BRIMHAVEN_DUNGEON_FIRE_GIANTS("Brimhaven Dungeon - Fire Giants", new Location(2638, 9506, 2673, 9476), 0), + BRIMHAVEN_DUNGEON_METAL_DRAGONS_SLAYER("Brimhaven Dungeon - Metal Dragons (Slayer Only)", new Location(2626, 9469, 2685, 9409), 0), + BRIMHAVEN_DUNGEON_METAL_DRAGONS("Brimhaven Dungeon - Metal Dragons", new Location(2693, 9469, 2748, 9412), 0), + BRIMHAVEN_DUNGEON_MOSS_GIANTS("Brimhaven Dungeon - Moss Giants", new Location(2630, 9575, 2670, 9531), 0), + BRIMHAVEN_DUNGEON_RED_DRAGONS("Brimhaven Dungeon - Red Dragons", new Location(2686, 9553, 2726, 9496), 0), + BRIMHAVEN_POH_PORTAL("Brimhaven POH Portal", new Location(2749, 3184, 2765, 3170), 0), + CAIRN_ISLE("Cairn Isle", new Location(2752, 2993, 2775, 2963), 0), + CRANDOR("Crandor", new Location(2813, 3310, 2864, 3231), 0), + HARDWOOD_GROVE("Hardwood Grove", new Location(2815, 3092, 2830, 3073), 0), + KARAMBWAN_FISHING_SPOT("Karambwan Fishing Spot", new Location(2896, 3116, 2920, 3104), 0), + KARAMJA_DOCKS("Karamja Docks", new Location(2813, 3310, 2864, 3231), 0), + KARAMJA_GLORY_TELEPORT("Karamja Glory Tele", new Location(2910, 3177, 2934, 3156), 0), + KARAMJA_GNOME_GLIDER("Karamja Gnome Glider", new Location(2961, 2960, 2984, 2983), 0), + KARAMJA_SHIP_YARD("Karamja Ship Yard", new Location(2949, 3066, 3004, 3016), 0), + KARAMJA_VOLCANO("Karamja Volcano", new Location(2828, 3194, 2866, 3157), 0), + KARAMJA_VOLCANO_DUNGEON("Karamja Dungeon", new Location(2827, 9589, 2866, 9549), 0), + KARAMJA_VOLCANO_DUNGEON_ELVARG("Karamja Dungeon (Elvarg)", new Location(2826, 9661, 2868, 9603), 0), + KHARAZI_JUNGLE_EAST("Kharazi Jungle (Eastern Section)", new Location(2905, 2930, 2976, 2883), 0), + KHARAZI_JUNGLE_CENTER("Kharazi Jungle (Middle Section)", new Location(2816, 2930, 2905, 2883), 0), + KHARAZI_JUNGLE_WEST("Kharazi Jungle (Western Section)", new Location(2756, 2930, 2816, 2883), 0), + MOR_UL_REK_BANK("TzHaar Bank (Inferno)", new Location(2534, 5146, 2547, 5133), 0), + NATURE_ALTAR("Nature Altar", new Location(2841, 3025, 2846, 3020), 0), + SHILO_VILLAGE_NORTH("Shilo Village North", new Location(2817, 3006, 2878, 2973), 0), + SHILO_VILLAGE_SOUTH("Shilo Village South", new Location(2816, 2972, 2879, 2944), 0), + TAI_BWO_WANNAI("Tai Bwo Wannai", new Location(2770, 3105, 2830, 3050), 0), + TZHAAR_BANK("TzHaar Bank (Jad)", new Location(2437, 5184, 2452, 5172), 0), + TZHAAR_EXIT("Tzhaar City Exit", new Location(2471, 5179, 2490, 5162), 0), + TZHAAR_FIGHT_PITS("TzHaar Fight Pit", new Location(2396, 5183, 2403, 5174), 0), + TZHAAR_INNER_SOUTH_EAST("Tzhaar Inner City South-East", new Location(2499, 5112, 2559, 5057), 0), + TZHAAR_INNER_SOUTH_WEST("Tzhaar Inner City South-West", new Location(2444, 5112, 2499, 5058), 0), + + /*- + * Kharidian Desert + * Agility Pyramid + * Al Kharid + * Bandit Camp (Desert) + * Bedabin Camp + * Citharede Abbey + * Duel Arena + * Nardah + * Pollnivneach + * Smoke Dungeon + * Sophanem + * Uzer + */ + AGILITY_PYRAMID("Agility Pyramid", new Location(3334, 2864, 3386, 2819), 0), + AL_KHARID_BANK("Al Kharid Bank", new Location(3265, 3173, 3272, 3161), 0), + AL_KHARID_GATE("Al Kharid Gate", new Location(3263, 3232, 3271, 3223), 0), + AL_KHARID_GLIDER("Al Kharid_Glider", new Location(3276, 3214, 3283, 3209), 0), + AL_KHARID_MINE("Al Kharid Mine", new Location(3295, 3316, 3303, 3278), 0), + AL_KHARID_PALACE("Al Kharid Palace", new Location(3281, 3178, 3304, 3158), 0), + BEDABIN_CAMP("Bedabin Camp", new Location(3157, 3052, 3188, 3019), 0), + CITHAREDE_ABBEY("Citharede Abbey", new Location(3355, 3190, 3425, 3150), 0), + DESERT_BANDIT_CAMP("Desert Bandit Camp", new Location(3154, 2993, 3189, 2963), 0), + DESERT_QUARRY("Desert Granite Quarry", new Location(3156, 2928, 3184, 2897), 0), + DUEL_ARENA("Duel Arena", new Location(3338, 3252, 3391, 3204), 0), // This polygon is deliberately offset + DUEL_ARENA_BANK("Duel Arena Bank", new Location(3379, 3274, 3386, 3265), 0), + DUEL_ARENA_PALM_TREES("Duel Arena Palm Trees", new Location(3340, 3280, 3354, 3264), 0), + DUEL_ARENA_TELEPORT("Duel Arena Tele", new Location(3308, 3246, 3326, 3225), 0), + FIRE_ALTAR("Fire Altar", new Location(3301, 3256, 3307, 3250), 0), + KALPHITE_LAIR("Kalphite Lair Entrance", new Location(3205, 3124, 3253, 3082), 0), + NARDAH_BANK("Nardah Bank", new Location(3417, 2902, 3437, 2883), 0), + NARDAH_ZONE("Nardah", new Location(3397, 2942, 3453, 2882), 0), + POLLNIVNEACH("Pollnivneach", new Location(3331, 2990, 3379, 2945), 0), + POLLNIVNEACH_POH_PORTAL("Pollnivneach POH Portal", new Location(3333, 3008, 3346, 2995), 0), + POLLNIVNEACH_SMOKE_DUNGEON("Pollnivneach Smoke Dungeon", new Location(3199, 9404, 3327, 9345), 0), + POLLNIVNEACH_SMOKE_DUNGEON_ENTRANCE("Pollnivneach Smoke Dungeon Entrance", new Location(3303, 2967, 3314, 2955), 0), + RUINS_OF_UZER("Uzer", new Location(3463, 3114, 3506, 3075), 0), + SHANTAY_PASS("Shantay Pass", new Location(3293, 3137, 3312, 3116), 0), + SOPHANEM("Sophanem", new Location(3272, 2811, 3324, 2751), 0), + + /*- + * Misthalin + * Barbarian Village + * Digsite + * Draynor Village + * Edgeville + * Grand Exchange + * Lumbridge + * Lumbridge Swamp + * Paterdomus + * Silvarea + * Varrock + * Wizards' Tower + */ + BARB_VILLAGE("Barb Village", new Location(3071, 3448, 3092, 3405), 0), + COOKS_GUILD("Cooks Guild", new Location(3135, 3455, 3155, 3427), 0), + CHAMPIONS_GUILD("Champoins' Guild", new Location(3184, 3364, 3199, 3348), 0), + DARK_WIZARDS("Varrock Dark Wizards", new Location(3220, 3377, 3235, 3361), 0), + DIGSITE("Digsite", new Location(3340, 3435, 3380, 3390), 0), + DIGSITE_EXAM_CENTER("Digsite Exam Center", new Location(3357, 3339, 3367, 3331), 0), + DRAYNOR_MANOR("Draynor Manor", new Location(3089, 3375, 3127, 3350), 0), + DRAYNOR_SEWERS("Draynor Sewers", new Location(3077, 9699, 3135, 9642), 0), + DRYANOR_VILLAGE("Dryanor Village", new Location(3074, 3283, 3112, 3241), 0), + EDGEVILLE_BANK("Edge Bank", new Location(3090, 3499, 3099, 3487), 0), + EDGEVILLE_DUNGEON("Edgeville Dungeon - Main Corridor (Paddewwa Tele)", new Location(3091, 9890, 3105, 9866), 0), + EDGEVILLE_DUNGEON_HILLGIANTS("Varrock Underground - Hill Giants", new Location(3095, 9854, 3125, 9821), 0), + EDGEVILLE_DUNGEON_HOB_GOBLINS("Edgeville Dungeon - Hob Goblins", new Location(3115, 9880, 3143, 9857), 0), + EDGEVILLE_DUNGEON_SLAYER_MASTER("Edgeville Dungeon - Slayer Master", new Location(3128, 9917, 3151, 9881), 0), + GRAND_EXCHANGE("Grand Exchange", new Location(3155, 3499, 3174, 3480), 0), + GRAND_EXCHANGE_AGILITY_SHORTCUT("GE Agility Shortcut", new Location(3136, 3518, 3143, 3511), 0), + GRAND_EXCHANGE_ENTRANCE("GE Entrance", new Location(3159, 3472, 3170, 3460), 0), + HAM_DUNGEON("H.A.M. Dungeon", new Location(3138, 9660, 3191, 9604), 0), + HAM_ENTRANCE("H.A.M. Hideout", new Location(3159, 3254, 3172, 3243), 0), + LUMBERYARD("Lumberyard", new Location(3289, 3520, 3327, 3488), 0), + LUMBRIDGE_BASEMENT("Lumbridge Basement", new Location(3206, 9626, 3221, 9613), 0), + LUMBRIDGE_CASTLE("Lumbridge Castle", new Location(3201, 3235, 3225, 3201), 0), + LUMBRIDGE_SWAMP("Lumby Swamp", new Location(3135, 3203, 3245, 3140), 0), + LUMBRIDGE_SWAMP_CAVES("Lumbridge Swamp Caves", new Location(3142, 9598, 3260, 9537), 0), + PATERDOMUS("Priest in Peril Temple", new Location(3404, 3495, 3419, 3481), 0), + SENNTISTEN_TELEPORT("Senntisten Tele", new Location(3305, 3342, 3319, 3328), 0), + SILVAREA("Rag and Bone Man", new Location(3350, 3505, 3378, 3492), 0), + STRONGHOLD_OF_SECURITY_FLOOR_1("Stronghold of Security - Floor 1 (Minatours)", new Location(1855, 5246, 1917, 5183), 0), + STRONGHOLD_OF_SECURITY_FLOOR_2("Stronghold of Security - Floor 2 (Flesh Crawlers)", new Location(1983, 5246, 2049, 5183), 0), + STRONGHOLD_OF_SECURITY_FLOOR_3("Stronghold of Security - Floor 3 (Catablepons)", new Location(2113, 5310, 2178, 5248), 0), + STRONGHOLD_OF_SECURITY_FLOOR_4("Stronghold of Security - Floor 4 (Ankous)", new Location(2302, 5249, 2367, 5185), 0), + VARROCK_CHURCH("Varrock Church", new Location(3249, 3488, 3259, 3471), 0), + VARROCK_BANK_EAST("Varrock East Bank", new Location(3246, 3428, 3261, 3412), 0), + VARROCK_BANK_WEST("Varrock West Bank", new Location(3172, 3450, 3197, 3425), 0), + VARROCK_MAGIC_SHOP("Varrock Magic Shop", new Location(3249, 3405, 3256, 3398), 0), + VARROCK_MINE("Varrock Mine", new Location(3278, 3372, 3294, 3355), 0), + VARROCK_MOSS_GIANTS("Varrock Sewers - Moss Giants", new Location(3190, 9910, 3153, 9876), 0), + VARROCK_MUSEUM("Varrock Museum", new Location(3249, 3455, 3267, 3442), 0), + VARROCK_PALACE("Varrock Palace", new Location(3198, 3502, 3228, 3455), 0), + VARROCK_SEWERS("Varrock Sewers", new Location(3200, 9918, 3285, 9857), 0), + VARROCK_SQUARE("Varrock Square", new Location(3201, 3444, 3229, 3412), 0), + WIZARDS_TOWER("Wizards Tower", new Location(3093, 3171, 3121, 3146), 0), + + /*- + * Morytania + * Abandoned Mine + * Barrows + * Burgh de Rott + * Canifis + * Darkmeyer + * Fenkenstrain's Castle + * Hallowvale + * Haunted Woods + * Meiyerditch + * Mort'ton + * Mort Myre Swamp + * Port Phasmatys + * Slepe + * The Sisterhood Sanctuary (Nightmare Dungeon) + */ + ABANDONED_MINE("Haunted Mine", new Location(3426, 3260, 3459, 3205), 0), + BARROWS("Barrows", new Location(3546, 3314, 3583, 3268), 0), + BARROWS_CRYPT("Barrows Crypt", new Location(3523, 9723, 3580, 9666), 0), + BURGH_DE_ROTT("Burgh de Rott", new Location(3474, 3247, 3535, 3189), 0), + CANIFIS_BANK("Canifis Bank", new Location(3508, 3483, 3516, 3474), 0), + CANIFIS_ZONE("Canifis", new Location(3472, 3506, 3519, 3467), 0), + CROMBWICK_MANOR("Crombwick Manor in Slepe", new Location(3710, 3377, 3742, 3341), 0), + DARKMEYER_BANK("Darkmeyer Bank", new Location(3600, 3370, 3610, 3364), 0), + DARKMEYER_ZONE("Darkmeyer", new Location(3592, 3392, 3662, 3331), 0), + FENKENSTRAINS_CASTLE("Fenkenstrain's Castle", new Location(3533, 3568, 3564, 3534), 0), + ECTOFUNTUS("Ectofuntus", new Location(3651, 3528, 3668, 3510), 0), + HALLOWED_SEPULCHER_ENTRANCE("Hallowed Sepulcher Entrance", new Location(3649, 3389, 3659, 3379), 0), + HALLOWED_SEPULCHER_LOBBY("Hallowed Sepulcher Lobby", new Location(2383, 5996, 2417, 5963), 0), + MORT_TON("Mort'ton", new Location(3473, 3301, 3504, 3271), 0), + MORYTANIA_FARM_PATCH("Morytania Farming Patch", new Location(3596, 3531, 3607, 3520), 0), + MORYTANIA_SWAMP_NORTH("Northern half of Morytania Swamp", new Location(3412, 3450, 3481, 3410), 0), + MORYTANIA_SWAMP_SOUTH("Southern half of Morytania Swamp", new Location(3412, 3410, 3481, 3370), 0), + NATURE_GROTTO("Nature Grotto", new Location(3410, 3356, 3461, 3322), 0), + NIGHTMARE_BOSS("The Nightmare", new Location(3798, 9769, 3818, 9749), 1), + PORT_PHASMATYS_BANK("Port Phasmatys Bank", new Location(3686, 3471, 3699, 3461), 0), + PORT_PHASMATYS_DOCKS("Port Phasmatys Docks", new Location(3689, 3512, 3711, 3481), 0), + PORT_PHASMATYS_PUB("Port Phasmatys Pub", new Location(3671, 3499, 3681, 3489), 0), + PORT_PHASMATYS_SOUTH_GATE("Port Phasmatys South Gate", new Location(3663, 3455, 3674, 3445), 0), + SALVE_GRAVEYARD("Salve Graveyard", new Location(3425, 3468, 3438, 3457), 0), + SISTERHOOD_SANCTUARY("Sisterhood Sanctuary (Slepe Dungeon)", new Location(3720, 9832, 3898, 9690), 1), + SLAYER_TOWER("Slayer Tower", new Location(3403, 3579, 3454, 3530), 0), + SLEPE("Slepe", new Location(3692, 3381, 3750, 3293), 0), + SWAMP_LIZARDS("Swamp Lizards", new Location(3521, 3451, 3568, 3426), 0), + VER_SINHAZA("ToB", new Location(3640, 3236, 3685, 3202), 0), + + /*- + * Tirannwn + * Arandar + * Gwenith + * Iowerth Dungeon + * Isafdar + * Lletya + * Mynydd + * Poison Waste + * Port Tyras + * Prifddinas + * Tyras Camp + * Zul-Andra + */ + LLETYA("Lletya", new Location(2312, 3196, 2362, 3145), 0), + ELF_CAMP("Elf Camp", new Location(2212, 3265, 2182, 3237), 0), + GWENTIH("Gwenith", new Location(2187, 3425, 2220, 3393), 0), + PRIFDDINAS("Prifddinas", new Location(3221, 6056, 3241, 6039), 0), // Fallback if there are gaps + PRIFDDINAS_BANK_NORTH("Prifddinas North Bank", new Location(3254, 6113, 3260, 6101), 0), + PRIFDDINAS_BANK_SOUTH("Prifddinas South Bank", new Location(3288, 6067, 3304, 6052), 0), + PRIFDDINAS_CITY_CENTER("Prifddinas Center", new Location(3246, 6100, 3281, 6065), 0), + PRIFDDINAS_CITY_E("Eastern Part of Prifddinas", new Location(3282, 6100, 3305, 6065), 0), + PRIFDDINAS_CITY_N("Northern Part of Prifddinas", new Location(3246, 6124, 3281, 6101), 0), + PRIFDDINAS_CITY_NE("North-Eastern Prifddinas", new Location(3282, 6136, 3319, 6101), 0), + PRIFDDINAS_CITY_NW("North-Western Prifddinas", new Location(3208, 6135, 3245, 6101), 0), + PRIFDDINAS_CITY_S("Southern Part of Prifddinas", new Location(3246, 6064, 3281, 6040), 0), + PRIFDDINAS_CITY_SE("South-Eastern Prifddinas", new Location(3282, 6039, 3321, 6023), 0), + PRIFDDINAS_CITY_SW("South-Western Prifddinas", new Location(3207, 6064, 3245, 6023), 0), + PRIFDDINAS_CITY_W("Western Part of Prifddinas", new Location(3222, 6100, 3245, 6065), 0), + PRIFDDINAS_GATE_EAST("Prifddinas East Gate (Arandar / Elven Pass)", new Location(2297, 3334, 2323, 3305), 0), + PRIFDDINAS_GATE_EAST_INSIDE("Prifddinas East Gate", new Location(3306, 6100, 3319, 6064), 0), + PRIFDDINAS_GATE_NORTH("Prifddinas North Gate", new Location(2230, 3387, 2249, 3384), 0), + PRIFDDINAS_GATE_NORTH_INSIDE("Prifddinas North Gate", new Location(3246, 6136, 3281, 6125), 0), + PRIFDDINAS_GATE_SOUTH("Prifddinas South Gate", new Location(2229, 3270, 2252, 3251), 0), + PRIFDDINAS_GATE_SOUTH_INSIDE("Prifddinas South Gate", new Location(3246, 6039, 3281, 6024), 0), + PRIFDDINAS_GATE_WEST("Prifddinas West Gate (Docks)", new Location(2154, 3338, 2182, 3317), 0), + PRIFDDINAS_GATE_WEST_INSIDE("Prifddinas West Gate", new Location(3207, 6100, 3221, 6065), 0), + PRIFDDINAS_GAUNTLET_PORTAL("Prifddinas Gauntlet Portal", new Location(3224, 6112, 3243, 6087), 0), + PRIFDDINAS_POH_PORTAL("Prifddinas POH Portal", new Location(3230, 6081, 3247, 6067), 0), + PRIFDDINAS_RED_CHINS("Prifddinas Red Chins", new Location(2255, 3418, 2283, 3397), 0), + PRIFDDINAS_SLAYER_CAVE_ENTRANCE("Prifddinas Slayer Cave Entrance", new Location(3221, 6056, 3241, 6039), 0), + PRIFDDINAS_ZALCANO_ENTRANCE("Prifddinas Zalcano Entrance", new Location(3277, 6065, 3287, 6053), 0), + TYRAS_CAMP("Tyras Camp", new Location(2168, 3163, 2201, 3134), 0), + TYRAS_DOCKS("Port Tyras", new Location(2135, 3133, 2167, 3110), 0), + ZALCANO("Zalcano", new Location(3019, 6074, 3048, 6035), 0), + GAUNTLET_LOBBY("Gauntlet Lobby", new Location(3025, 6130, 3040, 6115), 1), + ZUL_ANDRA("Zul-Andra", new Location(2182, 3070, 2214, 3042), 0), + + /*- + * Troll Country + * Death Plateau + * God Wars Dungeon + * Ice Path + * Troll Stronghold + * Trollheim + * Trollweiss Mountain + * Weiss + */ + DEATH_PLATEAU("Death Plateau", new Location(2838, 3610, 2880, 3580), 0), + GOD_WARS_DUNGEON("GWD", new Location(2820, 5375, 2944, 5253), 2), + GOD_WARS_DUNGEON_ENTRANCE("GWD Entrance", new Location(2904, 3756, 2921, 3742), 0), + TROLL_STRONGHOLD("Troll Stronghold", new Location(2836, 3698, 2862, 3659), 0), + TROLLHEIM_TELEPORT("Trollheim Tele", new Location(2882, 3685, 2899, 3669), 0), + WEISS("Weiss", new Location(2837, 3967, 2890, 3914), 0), + + /* + * Dungeons, Caves, Islands and other miscellaneous areas + */ + ABYSS("Abyss", new Location(3010, 4862, 3068, 4804), 0), + ABYSSAL_AREA("Abyssal Area", new Location(3008, 4926, 3071, 4864), 0), + ABYSSAL_NEXUS("Abyssal Nexus", new Location(3010, 4803, 3068, 4756), 0), + BLAST_FURNACE("Blast Furnace", new Location(1934, 4974, 1958, 4955), 0), + CAVE_HORROR_ENTRANCE("Mos Le'Harmless Cave Entrance (Cave Horrors)", new Location(3737, 2986, 3759, 2961), 0), + COSMIC_ALTAR("Zanaris Cosmic Altar", new Location(2400, 4387, 2425, 4367), 0), + DWARVEN_MINE_CAMP("Dwarven Mine - North Exit", new Location(3013, 9854, 3033, 9820), 0), + DWARVEN_MINE_CART("Dwarven Mine - Cart Transport", new Location(2988, 9849, 3006, 9821), 0), + DWARVEN_MINE_FALADOR("Dwarven Mine - Falador Exit", new Location(3030, 9788, 3062, 9758), 0), + GORAK_PLANE("Gorak Plane", new Location(3006, 5377, 3070, 5313), 0), + FISHER_REALM("Fisher Realm (Fairy Ring BJR)", new Location(2622, 4738, 2688, 4667), 0), + HARMONY("Harmony Island", new Location(3778, 2879, 3835, 2816), 0), + MINING_GUILD("Mining Guild", new Location(3008, 9756, 3061, 9698), 0), + MOLE_LAIR("Mole Lair", new Location(1730, 5246, 1787, 5131), 0), + MOS_LE_HARMLESS("Mos Le'Harmless", new Location(3649, 3005, 3709, 2958), 0), + MOS_LE_HARMLESS_DOCKS("Mos Le'Harmless Docks", new Location(3664, 2957, 3692, 2929), 0), + MOTHERLODE_MINE("Motherlode Mine", new Location(3713, 5695, 3777, 5632), 0), + PEST_CONTROL("Pest Control", new Location(2630, 2679, 2682, 2627), 0), + PURO_PURO("Puro-Puro", new Location(2561, 4349, 2622, 4289), 0), + SORCERESS_GARDEN("Sorceress's Garden", new Location(2884, 5499, 2938, 5444), 0), + TROUBLE_BREWING("Trouble Brewing", new Location(3774, 3024, 3843, 2942), 0), + ZANARIS_BANK("Zanaris Bank", new Location(2374, 4468, 2390, 4451), 0), + ZANARIS("Zanaris", new Location(2398, 4478, 2460, 4419), 0), + + /* + * Wilderness Locations + */ + ANNAKARL_TELEPORT("GDZ", new Location(3279, 3895, 3296, 3875), 0), + AXE_HUT("Axe Hut", new Location(3187, 3962, 3194, 3957), 0), + BANDIT_CAMP("Bandit Camp", new Location(3017, 3712, 3059, 3681), 0), + BLACK_SALAMANDERS("Black Salamanders", new Location(3291, 3677, 3301, 3664), 0), + CALLISTO("Callisto", new Location(3266, 3863, 3315, 3827), 0), + CEMETERY("Cemetery", new Location(2956, 3767, 2996, 3736), 0), + CHAOS_ALTAR_PRAYER("Chaos Altar", new Location(2945, 3826, 2970, 3813), 0), + CHAOS_ALTAR_RUNECRAFT("Chaos Runecrafting Altar", new Location(3055, 3596, 3067, 3585), 0), + CHAOS_FANATIC("Chaos Fanatic", new Location(2971, 3854, 2992, 3834), 0), + CHAOS_TEMPLE("Chaos Temple", new Location(3220, 3632, 3255, 3593), 0), + BLACK_CHINCHOMPAS("Chins", new Location(3128, 3792, 3160, 3754), 0), + CORP_CAVE("Corp Cave", new Location(3201, 3684, 3219, 3672), 0), + CRAZY_ARCHAEOLOGIST("Crazy Archaeologist", new Location(2952, 3709, 2985, 3678), 0), + DARK_CRAB_TELEPORT("Dark Crab Tele", new Location(3343, 3800, 3355, 3780), 0), + DARK_WARRIORS("Dark Warriors", new Location(3014, 3648, 3046, 3616), 0), + DEEP_WILDERNESS_DUNGEON("Deep Wilderness Dungeon", new Location(3038, 10330, 3053, 10305), 0), + DEEP_WILDERNESS_DUNGEON_ENTRANCE("Deep Wild Dungeon", new Location(3042, 3929, 3051, 3920), 0), + DEEP_WILDERNESS_DUNGEON_FIRE_GIANTS("Deep Wilderness Dungeon Fire Giants", new Location(3035, 10349, 3060, 10331), 0), + DEEP_WILDERNESS_DUNGEON_WINES("Deep Wilderness Dungeon Wines", new Location(3013, 10365, 3060, 10350), 0), + DWARVES("Dwarves", new Location(3230, 3805, 3264, 3779), 0), + EDGEVILLE_DUNGEON_EARTH_WARRIORS("Edgeville Dungeon - Earth Warriors", new Location(3114, 9999, 3129, 9960), 0), + EDGEVILLE_DUNGEON_CHAOS_DRUIDS("Edgeville Dungeon - Chaos Druids", new Location(3104, 9944, 3135, 9923), 0), + EDGEVILLE_DUNGEON_SPIDERS("Edgeville Dungeon - Spiders", new Location(3104, 9959, 3135, 9945), 0), + EDGEVILLE_DUNGEON_BLACK_DEMONS("Edgeville Dungeon - Black Demons", new Location(3077, 9966, 3103, 9941), 0), + // is this label description intuitive? + ENTS("Ents", new Location(3300, 3627, 3320, 3584), 0), + FEROX_ENCLAVE("Ferox Enclave", new Location(3119, 3646, 3160, 3616), 0), + GLORY_HILL("Glory Hill", new Location(3331, 3890, 3348, 3866), 0), + GLORY_HOLE("Glory Hole", new Location(3352, 3897, 3386, 3869), 0), + CARRALLANGAR_GRAVES("Graves", new Location(3128, 3686, 3181, 3658), 0), + GREEN_DRAGONS_EAST("East Drags", new Location(3326, 3704, 3365, 3671), 0), + GREEN_DRAGONS_GRAVEYARD("Graveyard Drags", new Location(3129, 3717, 3172, 3691), 0), + GREEN_DRAGONS_WEST("West Drags", new Location(2960, 3627, 2992, 3598), 0), + HOBGOBLINS("Hobgoblins", new Location(3073, 3775, 3104, 3745), 0), + ICE_GATE("Ice Gate", new Location(2945, 3913, 2978, 3878), 0), + ICE_ROCK("Ice Rock", new Location(2957, 3942, 2984, 3929), 0), + KBD_CAGE("KBD CAGE", new Location(3007, 3855, 3021, 3839), 0), + LAVA_DRAGON_GAP("Gap", new Location(3238, 3855, 3258, 3841), 0), + LAVA_DRAGON_ISLE("Lava Drags", new Location(3175, 3857, 3221, 3805), 0), + LAVA_MAZE_DUNGEON("Lava Maze Dungeon", new Location(3075, 10239, 3008, 10291), 0), + LAVA_MAZE_TELE("Lava Maze Tele", new Location(3019, 3842, 3044, 3812), 0), + MAGE_ARENA("Mage Arena", new Location(3088, 3949, 3123, 3919), 0), + MAGE_BANK("Mage Bank", new Location(3082, 3960, 3103, 3952), 0), + MAGE_BANK_SAFE_ZONE("Mage Bank Safe Zone", new Location(2526, 4727, 2550, 4707), 0), + NEW_GATE("New Gate", new Location(3348, 3890, 3325, 3911), 0), + OBELISK_13("13s Port", new Location(3152, 3624, 3160, 3616), 0), + OBELISK_19("19s", new Location(3220, 3672, 3234, 3660), 0), +// OBELISK_27("27 GWDs Portal", new Location(3031, 3736, 3039, 3728), 0), + OBELISK_35("36 Port", new Location(3097, 3804, 3115, 3785), 0), + OBELISK_44("44s", new Location(2973, 3870, 2987, 3859), 0), + OBELISK_50("50 ports", new Location(3301, 3923, 3315, 3909), 0), + OLD_GATE("Old Gate", new Location(3211, 3906, 3238, 3882), 0), + PIRATE_HUT("Pirate Hut", new Location(3037, 3959, 3045, 3948), 0), + POISON_SPIDERS("Poison Spiders", new Location(3282, 3803, 3302, 3785), 0), + REV_CAVE_AGILITY_65("Rev Cave Green Dragon Agility Jump", new Location(3216, 10090, 3226, 10080), 0), + REV_CAVE_AGILITY_75_1("Rev Cave 75 Agility Jump", new Location(3195, 10200, 3212, 10190), 0), + REV_CAVE_AGILITY_75_2("Rev Cave 75 Agility Jump (North of Ankous)", new Location(3173, 10214, 3186, 10205), 0), + REV_CAVE_AGILITY_89("Rev Cave 89 Agility Jump", new Location(3233, 10148, 3244, 10140), 0), + REV_CAVE_ANKOUS("Rev Cave Ankous", new Location(3160, 10204, 3191, 10177), 0), + REV_CAVE_BLACK_DEMONS("Rev Cave Black Demons", new Location(3158, 10171, 3187, 10145), 0), + REV_CAVE_BLACK_DRAGS("Rev Cave Black Drags", new Location(3223, 10216, 3254, 10190), 0), + REV_CAVE_CORRIDOR_NORTH("Revenant Cave Corridor", new Location(3255, 10213, 3263, 10191), 0), + REV_CAVE_CORRIDOR_SOUTH("Rev Cave Green Dragon Corridor", new Location(3238, 10106, 3252, 10077), 0), + REV_CAVE_ENTRANCE_NORTH("Rev Entrance", new Location(3118, 3837, 3142, 3818), 0), + REV_CAVE_ENTRANCE_SOUTH("South Rev Entrance", new Location(3071, 3660, 3092, 3645), 0), + REV_CAVE_EXIT_NORTH("Rev Cave North Exit", new Location(3238, 10236, 3243, 10231), 0), + REV_CAVE_EXIT_SOUTH("Rev Cave South Exit", new Location(3190, 10062, 3215, 10052), 0), + REV_CAVE_GREATER_DEMONS("Rev Cave Greater Demons", new Location(3210, 10140, 3240, 10115), 0), + REV_CAVE_GREEN_DRAGONS_1("Rev Cave Green Dragons", new Location(3215, 10078, 3234, 10052), 0), + REV_CAVE_GREEN_DRAGONS_2("Rev Cave Green Dragons", new Location(3200, 10106, 3231, 10091), 0), + REV_CAVE_HELL_HOUNDS("Rev Cave Hell Hounds", new Location(3190, 10078, 3210, 10063), 0), + REV_CAVE_ICE_GIANTS("Rev Cave Ice Giants", new Location(3200, 10173, 3221, 10155), 0), + REV_CAVE_LESSER_DEMONS("Rev Cave Lesser Demons", new Location(3143, 10125, 3176, 10104), 0), + REVENANT_DARK_BEAST("Revenant Dark Beast", new Location(3244, 10154, 3260, 10136), 0), + REVENANT_MAIN_CHAMBER("Main Rev Chamber", new Location(3227, 10187, 3261, 10157), 0), + ROGUE_CASTLE("Rogue Castle", new Location(3275, 3947, 3299, 3920), 0), + RUNE_ROCKS("Rune Rocks", new Location(3055, 3890, 3072, 3876), 0), + SCORPIA("Scorpia", new Location(3216, 3949, 3248, 3935), 0), + SPERM_HILL("Sperm Hill", new Location(3282, 3687, 3300, 3677), 0), + SPIDER_HILL("Spider Hill", new Location(3156, 3896, 3182, 3871), 0), + VENENATIS("Venenatis", new Location(3298, 3759, 3353, 3722), 0), + VETTION("Vet'tion", new Location(3183, 3796, 3227, 3765), 0), + VOLCANO("Volcano", new Location(3345, 3957, 3390, 3916), 0), + WEB("Web", new Location(3153, 3961, 3163, 3948), 0), + WILDY_AGILITY_COURSE("Wildy Agility Course", new Location(2988, 3967, 3008, 3906), 0), + WILDERNESS_GOD_WARS_DUNGEON("God Wars Dungeon", new Location(3010, 3745, 3027, 3727), 0), + WILDERNESS_GOD_WARS("Wildy GWD Chamber", new Location(3012, 10168, 3068, 10113), 0), + WILDERNESS_LEVER("Lever", new Location(3149, 3933, 3162, 3917), 0), + WILDERNESS_RESOURCE_AREA("Resource Area", new Location(3174, 3946, 3195, 3923), 0), + ZAMORAK_MAGE("Zammy Mage", new Location(3099, 3561, 3107, 3553), 0); + + @Getter + private final String name; + @Getter + private final WorldArea worldArea; + @Getter + private final Location location; + @Getter + private static final Map LOCATION_MAP; + + static + { + ImmutableMap.Builder builder = ImmutableMap.builder(); + + for (WorldLocation value : values()) + { + builder.put(value.getWorldArea(), value.getName()); + } + + LOCATION_MAP = builder.build(); + } + + /** + * Creates a location used to get the name of a location by a WorldPoint + * + * @param name - The name that is used to represent the area in overlays etc + * @param location - A Location made out of 4 points on the world map + * @param plane - The plane of the World Area + */ + WorldLocation(String name, Location location, int plane) + { + this.name = name; + this.location = location; + this.worldArea = new WorldArea(location.x, location.y, location.width, location.height, plane); + } + + /** + * Returns all locations that aren't in the wild + * + * @return - A Collection of non-wilderness WorldLocations + */ + public static Collection getNonWildernessLocations() + { + return Arrays.stream(WorldLocation.values()).filter(loc -> + PvPUtil.getWildernessLevelFrom(loc.worldArea.toWorldPoint()) < 0).collect(Collectors.toList()); + } + + /** + * Returns only the WorldLocations that are in the wilderness + * + * @return - A Collection of WorldLocations in the wilderness + */ + public static Collection getWildernessLocations() + { + return Arrays.stream(WorldLocation.values()).filter(loc -> + PvPUtil.getWildernessLevelFrom(loc.worldArea.toWorldPoint()) > 0).collect(Collectors.toList()); + } + + /** + * Returns the WorldLocation that a WorldPoint is in, or the closest WorldLocation to the point + * + * @param worldPoint - the WorldPoint to find the WorldLocation of + * @return - Containing location or closest location if it isn't in any + */ + public static String location(WorldPoint worldPoint) + { + int dist = 128; // x2 Region lengths + String s = ""; + WorldArea closestArea = null; + + for (Map.Entry entry : LOCATION_MAP.entrySet()) + { + final WorldArea worldArea = entry.getKey(); + + if (worldArea.toWorldPointList().contains(worldPoint)) + { + s = entry.getValue(); + return s; + } + + final int distTo = worldArea.distanceTo(worldPoint); + + if (distTo < dist) + { + dist = distTo; + closestArea = worldArea; + } + } + + if (closestArea == null) + { + return s; + } + + if (worldPoint.getY() > closestArea.toWorldPoint().getY() + closestArea.getHeight()) + { + s = s + "N"; + } + + if (worldPoint.getY() < closestArea.toWorldPoint().getY()) + { + s = s + "S"; + } + + if (worldPoint.getX() < closestArea.toWorldPoint().getX()) + { + s = s + "W"; + } + + if (worldPoint.getX() > (closestArea.toWorldPoint().getX() + closestArea.getWidth())) + { + s = s + "E"; + } + + s = s + " of "; + s = s + LOCATION_MAP.get(closestArea); + + if (s.startsWith(" of ")) + { + s = s.substring(3); + } + + return s; + } + + + public static class Location + { + @Getter + private final int x; + @Getter + private final int y; + @Getter + private final int x1; + @Getter + private final int y1; + final int width; + final int height; + + Location(int x, int y, int x1, int y1) + { + this.x = Math.min(x, x1); + this.y = Math.min(y, y1); + this.x1 = Math.max(x, x1); + this.y1 = Math.max(y, y1); + this.width = Math.abs(x1 - x); + this.height = Math.abs(y1 - y); + } + + @Override + public String toString() + { + return "Location{" + + "x=" + x + + ", y=" + y + + ", width=" + width + + ", height=" + height + + '}'; + } + } + + @Override + public String toString() + { + return "WorldLocation{" + + "name='" + name + '\'' + + ", worldArea=" + worldArea + + '}'; + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/com/openosrs/client/graphics/ModelOutlineRenderer.java b/runelite-client/src/main/java/com/openosrs/client/graphics/ModelOutlineRenderer.java new file mode 100644 index 0000000000..5e2f10445f --- /dev/null +++ b/runelite-client/src/main/java/com/openosrs/client/graphics/ModelOutlineRenderer.java @@ -0,0 +1,1113 @@ +/* + * Copyright (c) 2018, Woox + * 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 com.openosrs.client.graphics; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import java.awt.Color; +import java.awt.image.BufferedImage; +import java.awt.image.DataBufferInt; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +import lombok.RequiredArgsConstructor; +import lombok.Value; +import net.runelite.api.Client; +import net.runelite.api.DecorativeObject; +import net.runelite.api.GameObject; +import net.runelite.api.GroundObject; +import net.runelite.api.MainBufferProvider; +import net.runelite.api.Model; +import net.runelite.api.NPC; +import net.runelite.api.NPCComposition; +import net.runelite.api.Perspective; +import net.runelite.api.Player; +import net.runelite.api.ItemLayer; +import net.runelite.api.TileObject; +import net.runelite.api.WallObject; +import net.runelite.api.coords.LocalPoint; +import net.runelite.client.task.Schedule; + +@Singleton +public class ModelOutlineRenderer +{ + /* + * This class doesn't really "need" static variables, but they are + * static for performance reasons. Arrays are kept outside methods + * to avoid frequent big allocations. Arrays should mostly be seen + * as ArrayLists. The size of them is increased whenever they need + * to become bigger. + */ + + private final Client client; + + private boolean isReset; + private boolean usedSinceLastCheck; + + // Dimensions of the underlying image + private int imageWidth; + private int imageHeight; + + // Boundaries for the current rasterization + private int clipX1; + private int clipY1; + private int clipX2; + private int clipY2; + + // Pixel points that would be rendered to + private int[] visited; + private int currentVisitedNumber = 0; + + // Transformed vertex positions + private int[] projectedVerticesX; + private int[] projectedVerticesY; + private boolean[] projectedVerticesRenderable; + + // An array of pixel points to raster onto the image. These are checked against + // clip boundaries and the visited array to prevent drawing on top of the model + // and outside the scene area. They are grouped per distance to the closest pixel + // drawn on the model. + private int[][] outlinePixels; + private int[] outlinePixelsLengths; // outlinePixelsLength[i] is the used length of outlinePixels[i] + private int outlineArrayWidth; + + // A list of pixel distances ordered from shortest to longest distance for + // each outline width. These are calculated once upon first usage and then + // stored here to prevent reevaluation. + private List> precomputedDistancePriorities; + + @Inject + private ModelOutlineRenderer(Client client) + { + this.client = client; + + reset(); + } + + @Schedule(period = 5, unit = ChronoUnit.SECONDS) + public void checkUsage() + { + if (!isReset && !usedSinceLastCheck) + { + // Reset memory allocated when the rasterizer becomes inactive + reset(); + } + usedSinceLastCheck = false; + } + + /** + * Reset memory used by the rasterizer + */ + private void reset() + { + visited = new int[0]; + projectedVerticesX = new int[0]; + projectedVerticesY = new int[0]; + projectedVerticesRenderable = new boolean[0]; + outlinePixels = new int[0][]; + outlinePixelsLengths = new int[0]; + precomputedDistancePriorities = new ArrayList<>(0); + isReset = true; + } + + /** + * Calculate the next power of two of a value + * + * @param value The value to find the next power of two of + * @return Returns the next power of two + */ + private static int nextPowerOfTwo(int value) + { + value--; + value |= value >> 1; + value |= value >> 2; + value |= value >> 4; + value |= value >> 8; + value |= value >> 16; + value++; + return value; + } + + /** + * Determine if a triangle goes counter clockwise + * + * @return Returns true if the triangle goes counter clockwise and should be culled, otherwise false + */ + private static boolean cullFace(int x1, int y1, int x2, int y2, int x3, int y3) + { + return + (y2 - y1) * (x3 - x2) - + (x2 - x1) * (y3 - y2) < 0; + } + + /** + * Gets the list of pixel distances ordered by distance from closest pixel for a specific outline width. + * + * @param outlineWidth The outline width + * @return Returns the list of pixel distances + */ + private List getPriorityList(int outlineWidth) + { + while (precomputedDistancePriorities.size() <= outlineWidth) + { + precomputedDistancePriorities.add(null); + } + + // Grab the cached outline width if we have one + if (precomputedDistancePriorities.get(outlineWidth) != null) + { + return precomputedDistancePriorities.get(outlineWidth); + } + + List ps = new ArrayList<>(); + for (int x = 0; x <= outlineWidth; x++) + { + for (int y = 0; y <= outlineWidth; y++) + { + if (x == 0 && y == 0) + { + continue; + } + + double dist = Math.sqrt(x * x + y * y); + if (dist > outlineWidth) + { + continue; + } + + int outerAlpha = outlineWidth == 1 ? 255 // For preventing division by 0 + : (int) (255 * (dist - 1) / (outlineWidth - 1)); + ps.add(new PixelDistanceAlpha(outerAlpha, x + y * outlineArrayWidth)); + } + } + ps.sort(Comparator.comparingDouble(PixelDistanceAlpha::getOuterAlpha)); + precomputedDistancePriorities.set(outlineWidth, ps); + + return ps; + } + + /** + * Checks that the size of outlinePixels is big enough to hold a specific + * amount of elements. This is used to reduce the amount of if checks needed + * when adding elements to outlinePixels. + * + * @param distArrayPos The position in the array + * @param additionalMinimumSize The additional minimum size required + */ + private void ensureMinimumOutlineQueueSize(int distArrayPos, int additionalMinimumSize) + { + int minimumSize = outlinePixelsLengths[distArrayPos] + additionalMinimumSize; + while (outlinePixels[distArrayPos].length < minimumSize) + { + int[] newArr = new int[nextPowerOfTwo(minimumSize)]; + System.arraycopy(outlinePixels[distArrayPos], 0, newArr, 0, + outlinePixels[distArrayPos].length); + outlinePixels[distArrayPos] = newArr; + } + } + + /** + * Resets the visited flag for a specific amount of pixels + * + * @param pixelAmount The amount of pixels to reset + */ + private void resetVisited(int pixelAmount) + { + // The visited array is essentially a boolean array, but by + // making it an int array and checking if visited[i] == currentVisitedNumber + // and changing currentVisitedNumber for every new outline, we can essentially + // reset the whole array without having to iterate over every element + + if (visited.length < pixelAmount) + { + visited = new int[nextPowerOfTwo(pixelAmount)]; + currentVisitedNumber = 0; + } + + currentVisitedNumber++; + } + + /** + * Resets the pixels that are queued for outlining + * + * @param outlineWidth The width of the outline to reset pixels for + */ + private void resetOutline(int outlineWidth) + { + outlineArrayWidth = outlineWidth + 2; + + int arraySizes = outlineArrayWidth * outlineArrayWidth; + if (outlinePixels.length < arraySizes) + { + outlinePixels = new int[arraySizes][]; + outlinePixelsLengths = new int[arraySizes]; + for (int i = 0; i < arraySizes; i++) + { + outlinePixels[i] = new int[4]; + } + } + else + { + for (int i = 0; i < arraySizes; i++) + { + outlinePixelsLengths[i] = 0; + } + } + } + + /** + * Simulates a horizontal line rasterization and adds the pixels to the left + * and to the right to the outline queue if they are within the clip area. + * + * @param pixelPos The pixel position in the line where x == 0 + * @param x1 The starting x position + * @param x2 The ending x position + */ + private void simulateHorizontalLineRasterizationForOutline(int pixelPos, int x1, int x2) + { + if (x2 > clipX2) + { + x2 = clipX2; + } + if (x1 < clipX1) + { + x1 = clipX1; + } + if (x1 >= x2) + { + return; + } + + // Queue the pixel positions to the left and to the right of the line + ensureMinimumOutlineQueueSize(1, 2); + if (x2 < clipX2) + { + outlinePixels[1][outlinePixelsLengths[1]++] = pixelPos + x2; + } + if (x1 > clipX1) + { + outlinePixels[1][outlinePixelsLengths[1]++] = pixelPos + x1 - 1; + } + + // Divide by 4 to account for loop unrolling + int xDist = x2 - x1 >> 2; + pixelPos += x1; + + // This loop could run over 100m times per second without loop unrolling in some cases, + // so unrolling it can give a noticeable performance boost. + while (xDist-- > 0) + { + visited[pixelPos++] = currentVisitedNumber; + visited[pixelPos++] = currentVisitedNumber; + visited[pixelPos++] = currentVisitedNumber; + visited[pixelPos++] = currentVisitedNumber; + } + + // Draw up to 3 more pixels if there were any left + xDist = (x2 - x1) & 3; + while (xDist-- > 0) + { + visited[pixelPos++] = currentVisitedNumber; + } + } + + /** + * Queues the pixel positions above and below two horizontal lines, excluding those + * where the x positions of the lines intersect. + * + * @param pixelPos The pixel position at x == 0 of the second line + * @param x1 The starting x position of the first line + * @param x2 The ending x position of the first line + * @param x3 The starting x position of the second line + * @param x4 The ending x position of the second line + */ + private void outlineAroundHorizontalLine(int pixelPos, int x1, int x2, int x3, int x4) + { + if (x1 < clipX1) + { + x1 = clipX1; + } + if (x2 < clipX1) + { + x2 = clipX1; + } + if (x3 < clipX1) + { + x3 = clipX1; + } + if (x4 < clipX1) + { + x4 = clipX1; + } + + if (x1 > clipX2) + { + x1 = clipX2; + } + if (x2 > clipX2) + { + x2 = clipX2; + } + if (x3 > clipX2) + { + x3 = clipX2; + } + if (x4 > clipX2) + { + x4 = clipX2; + } + + if (x1 < x3) + { + ensureMinimumOutlineQueueSize(outlineArrayWidth, x3 - x1); + for (int x = x1; x < x3; x++) + { + outlinePixels[outlineArrayWidth][outlinePixelsLengths[outlineArrayWidth]++] = pixelPos - imageWidth + x; + } + } + else + { + ensureMinimumOutlineQueueSize(outlineArrayWidth, x1 - x3); + for (int x = x3; x < x1; x++) + { + outlinePixels[outlineArrayWidth][outlinePixelsLengths[outlineArrayWidth]++] = pixelPos + x; + } + } + + if (x2 < x4) + { + ensureMinimumOutlineQueueSize(outlineArrayWidth, x4 - x2); + for (int x = x2; x < x4; x++) + { + outlinePixels[outlineArrayWidth][outlinePixelsLengths[outlineArrayWidth]++] = pixelPos + x; + } + } + else + { + ensureMinimumOutlineQueueSize(outlineArrayWidth, x2 - x4); + for (int x = x4; x < x2; x++) + { + outlinePixels[outlineArrayWidth][outlinePixelsLengths[outlineArrayWidth]++] = pixelPos - imageWidth + x; + } + } + } + + /** + * Simulates rasterization of a triangle and adds every pixel outside the triangle + * to the outline queue. + * + * @param x1 The x position of the first vertex in the triangle + * @param y1 The y position of the first vertex in the triangle + * @param x2 The x position of the second vertex in the triangle + * @param y2 The y position of the second vertex in the triangle + * @param x3 The x position of the third vertex in the triangle + * @param y3 The y position of the third vertex in the triangle + */ + private void simulateTriangleRasterizationForOutline(int x1, int y1, int x2, int y2, int x3, int y3) + { + // Swap vertices so y1 <= y2 <= y3 using bubble sort + if (y1 > y2) + { + int yp = y1; + int xp = x1; + y1 = y2; + y2 = yp; + x1 = x2; + x2 = xp; + } + if (y2 > y3) + { + int yp = y2; + int xp = x2; + y2 = y3; + y3 = yp; + x2 = x3; + x3 = xp; + } + if (y1 > y2) + { + int yp = y1; + int xp = x1; + y1 = y2; + y2 = yp; + x1 = x2; + x2 = xp; + } + + if (y1 > clipY2) + { + // All points are outside clip boundaries + return; + } + + int slope1 = 0; + if (y1 != y2) + { + slope1 = (x2 - x1 << 14) / (y2 - y1); + } + + int slope2 = 0; + if (y3 != y2) + { + slope2 = (x3 - x2 << 14) / (y3 - y2); + } + + int slope3 = 0; + if (y1 != y3) + { + slope3 = (x1 - x3 << 14) / (y1 - y3); + } + + if (y2 > clipY2) + { + y2 = clipY2; + } + if (y3 > clipY2) + { + y3 = clipY2; + } + if (y1 == y3 || y3 < 0) + { + return; + } + + x1 <<= 14; + x2 <<= 14; + x3 = x1; + + if (y1 < 0) + { + x3 -= y1 * slope3; + x1 -= y1 * slope1; + y1 = 0; + } + if (y2 < 0) + { + x2 -= slope2 * y2; + y2 = 0; + } + + int pixelPos = y1 * imageWidth; + int currX1; + int currX2; + if (y1 != y2 && slope3 < slope1 || y1 == y2 && slope3 > slope2) + { + int height1 = y2 - y1; + int height2 = y3 - y2; + + int prevX1; + int prevX2; + if (height1 <= 0) + { + prevX1 = x3 >> 14; + prevX2 = x2 >> 14; + } + else + { + prevX1 = x3 >> 14; + prevX2 = x1 >> 14; + } + + outlineAroundHorizontalLine(pixelPos, prevX1, prevX2, prevX2, prevX2); + + while (height1-- > 0) + { + currX1 = x3 >> 14; + currX2 = x1 >> 14; + outlineAroundHorizontalLine(pixelPos, currX1, currX2, prevX1, prevX2); + simulateHorizontalLineRasterizationForOutline(pixelPos, currX1, currX2); + x3 += slope3; + x1 += slope1; + pixelPos += imageWidth; + prevX1 = currX1; + prevX2 = currX2; + } + + while (height2-- > 0) + { + currX1 = x3 >> 14; + currX2 = x2 >> 14; + outlineAroundHorizontalLine(pixelPos, currX1, currX2, prevX1, prevX2); + simulateHorizontalLineRasterizationForOutline(pixelPos, currX1, currX2); + x3 += slope3; + x2 += slope2; + pixelPos += imageWidth; + prevX1 = currX1; + prevX2 = currX2; + } + + outlineAroundHorizontalLine(pixelPos, prevX1, prevX1, prevX1, prevX2); + } + else + { + int height1 = y2 - y1; + int height2 = y3 - y2; + + int prevX1; + int prevX2; + if (height1 <= 0) + { + prevX1 = x2 >> 14; + prevX2 = x3 >> 14; + } + else + { + prevX1 = x1 >> 14; + prevX2 = x3 >> 14; + } + + outlineAroundHorizontalLine(pixelPos, prevX1, prevX2, prevX2, prevX2); + + while (height1-- > 0) + { + currX1 = x1 >> 14; + currX2 = x3 >> 14; + outlineAroundHorizontalLine(pixelPos, currX1, currX2, prevX1, prevX2); + simulateHorizontalLineRasterizationForOutline(pixelPos, currX1, currX2); + x1 += slope1; + x3 += slope3; + pixelPos += imageWidth; + prevX1 = currX1; + prevX2 = currX2; + } + + while (height2-- > 0) + { + currX1 = x2 >> 14; + currX2 = x3 >> 14; + outlineAroundHorizontalLine(pixelPos, currX1, currX2, prevX1, prevX2); + simulateHorizontalLineRasterizationForOutline(pixelPos, currX1, currX2); + x3 += slope3; + x2 += slope2; + pixelPos += imageWidth; + prevX1 = currX1; + prevX2 = currX2; + } + + outlineAroundHorizontalLine(pixelPos, prevX1, prevX1, prevX1, prevX2); + } + } + + /** + * Translates the vertices 3D points to the screen canvas 2D points + * + * @param localX The local x position of the vertices + * @param localY The local y position of the vertices + * @param localZ The local z position of the vertices + * @param vertexOrientation The orientation of the vertices + * @return Returns true if any of them are inside the clip area, otherwise false + */ + private boolean projectVertices(Model model, final int localX, final int localY, final int localZ, final int vertexOrientation) + { + final int cameraX = client.getCameraX(); + final int cameraY = client.getCameraY(); + final int cameraZ = client.getCameraZ(); + final int cameraYaw = client.getCameraYaw(); + final int cameraPitch = client.getCameraPitch(); + final int scale = client.getScale(); + final int orientationSin = Perspective.SINE[vertexOrientation]; + final int orientationCos = Perspective.COSINE[vertexOrientation]; + final int pitchSin = Perspective.SINE[cameraPitch]; + final int pitchCos = Perspective.COSINE[cameraPitch]; + final int yawSin = Perspective.SINE[cameraYaw]; + final int yawCos = Perspective.COSINE[cameraYaw]; + final int vertexCount = model.getVerticesCount(); + final int[] verticesX = model.getVerticesX(); + final int[] verticesY = model.getVerticesY(); + final int[] verticesZ = model.getVerticesZ(); + + boolean anyVisible = false; + + // Make sure the arrays are big enough + while (projectedVerticesX.length < vertexCount) + { + int newSize = nextPowerOfTwo(vertexCount); + projectedVerticesX = new int[newSize]; + projectedVerticesY = new int[newSize]; + projectedVerticesRenderable = new boolean[newSize]; + } + + for (int i = 0; i < vertexCount; i++) + { + int vx = verticesX[i]; + int vy = verticesZ[i]; + int vz = verticesY[i]; + int vh; // Value holder + + // Rotate based on orientation + vh = vx * orientationCos + vy * orientationSin >> 16; + vy = vy * orientationCos - vx * orientationSin >> 16; + vx = vh; + + // Translate to local coords + vx += localX; + vy += localY; + vz += localZ; + + // Translate to camera + vx -= cameraX; + vy -= cameraY; + vz -= cameraZ; + + // Transform to canvas + vh = vx * yawCos + vy * yawSin >> 16; + vy = vy * yawCos - vx * yawSin >> 16; + vx = vh; + vh = vz * pitchCos - vy * pitchSin >> 16; + vz = vz * pitchSin + vy * pitchCos >> 16; + vy = vh; + + if (vz >= 50) + { + projectedVerticesX[i] = (clipX1 + clipX2) / 2 + vx * scale / vz; + projectedVerticesY[i] = (clipY1 + clipY2) / 2 + vy * scale / vz; + + projectedVerticesRenderable[i] = true; + anyVisible |= + projectedVerticesX[i] >= clipX1 && projectedVerticesX[i] < clipX2 && + projectedVerticesY[i] >= clipY1 && projectedVerticesY[i] < clipY2; + } + else + { + projectedVerticesRenderable[i] = false; + } + } + + return anyVisible; + } + + /** + * Simulate rendering of the model and puts every pixel of the wireframe of + * the non-culled and non-transparent faces into the outline pixel queue. + */ + private void simulateModelRasterizationForOutline(Model model) + { + final int triangleCount = model.getTrianglesCount(); + final int[] indices1 = model.getTrianglesX(); + final int[] indices2 = model.getTrianglesY(); + final int[] indices3 = model.getTrianglesZ(); + final byte[] triangleTransparencies = model.getTriangleTransparencies(); + + for (int i = 0; i < triangleCount; i++) + { + if (projectedVerticesRenderable[indices1[i]] && + projectedVerticesRenderable[indices2[i]] && + projectedVerticesRenderable[indices3[i]] && + // 254 and 255 counts as fully transparent + (triangleTransparencies == null || (triangleTransparencies[i] & 255) < 254)) + { + final int index1 = indices1[i]; + final int index2 = indices2[i]; + final int index3 = indices3[i]; + final int v1x = projectedVerticesX[index1]; + final int v1y = projectedVerticesY[index1]; + final int v2x = projectedVerticesX[index2]; + final int v2y = projectedVerticesY[index2]; + final int v3x = projectedVerticesX[index3]; + final int v3y = projectedVerticesY[index3]; + + if (!cullFace(v1x, v1y, v2x, v2y, v3x, v3y)) + { + simulateTriangleRasterizationForOutline( + v1x, v1y, v2x, v2y, v3x, v3y); + } + } + } + } + + /** + * Draws an outline of the pixels in the outline queue to an image + * + * @param image The image to draw the outline to + * @param outlineWidth The width of the outline + * @param innerColor The color of the pixels of the outline closest to the model + * @param outerColor The color of the pixels of the outline furthest away from the model + */ + private void renderOutline(BufferedImage image, int outlineWidth, Color innerColor, Color outerColor) + { + int[] imageData = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); + List ps = getPriorityList(outlineWidth); + + for (PixelDistanceAlpha p : ps) + { + int color; + int alpha; + if (outlineWidth == 1) + { + color = + ((innerColor.getRed() + outerColor.getRed()) << 15) | + ((innerColor.getGreen() + outerColor.getGreen() << 7)) | + ((innerColor.getBlue() + outerColor.getBlue() >> 1)); + alpha = (innerColor.getAlpha() + outerColor.getAlpha()) >> 1; + } + else + { + int outerAlpha = p.getOuterAlpha(); + int innerAlpha = 255 - outerAlpha; + int innerAlphaFraction = (innerAlpha * innerColor.getAlpha()) / 255; + int outerAlphaFraction = (outerAlpha * outerColor.getAlpha()) / 255; + alpha = innerAlphaFraction + outerAlphaFraction; + if (alpha != 0) + { + color = + ((innerColor.getRed() * innerAlphaFraction + + outerColor.getRed() * outerAlphaFraction) / alpha << 16) | + ((innerColor.getGreen() * innerAlphaFraction + + outerColor.getGreen() * outerAlphaFraction) / alpha << 8) | + ((innerColor.getBlue() * innerAlphaFraction + + outerColor.getBlue() * outerAlphaFraction) / alpha); + } + else + { + color = 0; + } + } + + final int distArrayPos = p.getDistArrayPos(); + final int nextDistArrayPosY = distArrayPos + outlineArrayWidth; + final int nextDistArrayPosX = distArrayPos + 1; + ensureMinimumOutlineQueueSize(nextDistArrayPosX, outlinePixelsLengths[distArrayPos] * 2); + ensureMinimumOutlineQueueSize(nextDistArrayPosY, outlinePixelsLengths[distArrayPos] * 2); + + // The following 3 branches do the same thing, but when the requirements are simple, + // there are less checks needed which can give a performance boost. + if (alpha == 255) + { + if (outlineWidth == 1) + { + for (int i2 = 0; i2 < outlinePixelsLengths[distArrayPos]; i2++) + { + int pixelPos = outlinePixels[distArrayPos][i2]; + int x = pixelPos % imageWidth; + int y = pixelPos / imageWidth; + if (x < clipX1 || x >= clipX2 || + y < clipY1 || y >= clipY2 || + visited[pixelPos] == currentVisitedNumber) + { + continue; + } + + imageData[pixelPos] = color; + } + } + else + { + for (int i2 = 0; i2 < outlinePixelsLengths[distArrayPos]; i2++) + { + int pixelPos = outlinePixels[distArrayPos][i2]; + int x = pixelPos % imageWidth; + int y = pixelPos / imageWidth; + if (x < clipX1 || x >= clipX2 || + y < clipY1 || y >= clipY2 || + visited[pixelPos] == currentVisitedNumber) + { + continue; + } + visited[pixelPos] = currentVisitedNumber; + + imageData[pixelPos] = color; + + if (pixelPos % imageWidth != 0) + { + outlinePixels[nextDistArrayPosX][outlinePixelsLengths[nextDistArrayPosX]++] = pixelPos - 1; + } + if ((pixelPos + 1) % imageWidth != 0) + { + outlinePixels[nextDistArrayPosX][outlinePixelsLengths[nextDistArrayPosX]++] = pixelPos + 1; + } + outlinePixels[nextDistArrayPosY][outlinePixelsLengths[nextDistArrayPosY]++] = pixelPos - imageWidth; + outlinePixels[nextDistArrayPosY][outlinePixelsLengths[nextDistArrayPosY]++] = pixelPos + imageWidth; + } + } + } + else + { + for (int i2 = 0; i2 < outlinePixelsLengths[distArrayPos]; i2++) + { + int pixelPos = outlinePixels[distArrayPos][i2]; + int x = pixelPos % imageWidth; + int y = pixelPos / imageWidth; + if (x < clipX1 || x >= clipX2 || + y < clipY1 || y >= clipY2 || + visited[pixelPos] == currentVisitedNumber) + { + continue; + } + visited[pixelPos] = currentVisitedNumber; + + imageData[pixelPos] = + ((((color & 0xFF0000) * alpha + (imageData[pixelPos] & 0xFF0000) * (255 - alpha)) / 255) & 0xFF0000) + + ((((color & 0xFF00) * alpha + (imageData[pixelPos] & 0xFF00) * (255 - alpha)) / 255) & 0xFF00) + + ((((color & 0xFF) * alpha + (imageData[pixelPos] & 0xFF) * (255 - alpha)) / 255) & 0xFF); + + if (pixelPos % imageWidth != 0) + { + outlinePixels[nextDistArrayPosX][outlinePixelsLengths[nextDistArrayPosX]++] = pixelPos - 1; + } + if ((pixelPos + 1) % imageWidth != 0) + { + outlinePixels[nextDistArrayPosX][outlinePixelsLengths[nextDistArrayPosX]++] = pixelPos + 1; + } + outlinePixels[nextDistArrayPosY][outlinePixelsLengths[nextDistArrayPosY]++] = pixelPos - imageWidth; + outlinePixels[nextDistArrayPosY][outlinePixelsLengths[nextDistArrayPosY]++] = pixelPos + imageWidth; + } + } + } + } + + /** + * Draws an outline around a model to an image + * + * @param localX The local x position of the model + * @param localY The local y position of the model + * @param localZ The local z position of the model + * @param orientation The orientation of the model + * @param outlineWidth The width of the outline + * @param innerColor The color of the pixels of the outline closest to the model + * @param outerColor The color of the pixels of the outline furthest away from the model + */ + private void drawModelOutline(Model model, int localX, int localY, int localZ, int orientation, int outlineWidth, Color innerColor, Color outerColor) + { + if (outlineWidth <= 0) + { + return; + } + + isReset = false; + usedSinceLastCheck = true; + + MainBufferProvider bufferProvider = (MainBufferProvider) client.getBufferProvider(); + BufferedImage image = (BufferedImage) bufferProvider.getImage(); + + clipX1 = client.getViewportXOffset(); + clipY1 = client.getViewportYOffset(); + clipX2 = client.getViewportWidth() + clipX1; + clipY2 = client.getViewportHeight() + clipY1; + imageWidth = image.getWidth(); + imageHeight = image.getHeight(); + final int pixelAmount = imageWidth * imageHeight; + + resetVisited(pixelAmount); + resetOutline(outlineWidth); + + if (!projectVertices(model, + localX, localY, localZ, orientation)) + { + // No vertex of the model is visible on the screen, so we can + // assume there are no parts of the model to outline. + return; + } + + simulateModelRasterizationForOutline(model); + + renderOutline(image, outlineWidth, innerColor, outerColor); + } + + public void drawOutline(NPC npc, int outlineWidth, Color color) + { + drawOutline(npc, outlineWidth, color, color); + } + + public void drawOutline(NPC npc, int outlineWidth, Color innerColor, Color outerColor) + { + int size = 1; + NPCComposition composition = npc.getTransformedComposition(); + if (composition != null) + { + size = composition.getSize(); + } + + LocalPoint lp = npc.getLocalLocation(); + if (lp != null) + { + // NPCs z position are calculated based on the tile height of the northeastern tile + final int northEastX = lp.getX() + Perspective.LOCAL_TILE_SIZE * (size - 1) / 2; + final int northEastY = lp.getY() + Perspective.LOCAL_TILE_SIZE * (size - 1) / 2; + final LocalPoint northEastLp = new LocalPoint(northEastX, northEastY); + + drawModelOutline(npc.getModel(), lp.getX(), lp.getY(), + Perspective.getTileHeight(client, northEastLp, client.getPlane()), + npc.getCurrentOrientation(), outlineWidth, innerColor, outerColor); + } + } + + public void drawOutline(Player player, int outlineWidth, Color color) + { + drawOutline(player, outlineWidth, color, color); + } + + public void drawOutline(Player player, int outlineWidth, Color innerColor, Color outerColor) + { + LocalPoint lp = player.getLocalLocation(); + if (lp != null) + { + drawModelOutline(player.getModel(), lp.getX(), lp.getY(), + Perspective.getTileHeight(client, lp, client.getPlane()), + player.getCurrentOrientation(), outlineWidth, innerColor, outerColor); + } + } + + public void drawOutline(GameObject gameObject, int outlineWidth, Color innerColor, Color outerColor) + { + LocalPoint lp = gameObject.getLocalLocation(); + if (lp != null) + { + drawModelOutline(gameObject.getModel(), lp.getX(), lp.getY(), + Perspective.getTileHeight(client, lp, gameObject.getPlane()), + gameObject.getRsOrientation(), outlineWidth, innerColor, outerColor); + } + } + + public void drawOutline(GroundObject groundObject, int outlineWidth, Color innerColor, Color outerColor) + { + LocalPoint lp = groundObject.getLocalLocation(); + if (lp != null) + { + drawModelOutline(groundObject.getModel(), lp.getX(), lp.getY(), + Perspective.getTileHeight(client, lp, client.getPlane()), + 0, outlineWidth, innerColor, outerColor); + } + } + + private void drawOutline(ItemLayer tileItemPile, int outlineWidth, Color innerColor, Color outerColor) + { + LocalPoint lp = tileItemPile.getLocalLocation(); + if (lp != null) + { + Model model = tileItemPile.getModelBottom(); + if (model != null) + { + drawModelOutline(model, lp.getX(), lp.getY(), + Perspective.getTileHeight(client, lp, tileItemPile.getPlane()), + 0, outlineWidth, innerColor, outerColor); + } + + model = tileItemPile.getModelMiddle(); + if (model != null) + { + drawModelOutline(model, lp.getX(), lp.getY(), + Perspective.getTileHeight(client, lp, tileItemPile.getPlane()), + 0, outlineWidth, innerColor, outerColor); + } + + model = tileItemPile.getModelTop(); + if (model != null) + { + drawModelOutline(model, lp.getX(), lp.getY(), + Perspective.getTileHeight(client, lp, tileItemPile.getPlane()), + 0, outlineWidth, innerColor, outerColor); + } + } + } + + private void drawOutline(DecorativeObject decorativeObject, int outlineWidth, Color innerColor, Color outerColor) + { + LocalPoint lp = decorativeObject.getLocalLocation(); + if (lp != null) + { + Model model = decorativeObject.getModel1(); + if (model != null) + { + drawModelOutline(model, + lp.getX() + decorativeObject.getXOffset(), + lp.getY() + decorativeObject.getYOffset(), + Perspective.getTileHeight(client, lp, decorativeObject.getPlane()), + decorativeObject.getOrientation(), outlineWidth, innerColor, outerColor); + } + + model = decorativeObject.getModel2(); + if (model != null) + { + // Offset is not used for the second model + drawModelOutline(model, lp.getX(), lp.getY(), + Perspective.getTileHeight(client, lp, decorativeObject.getPlane()), + decorativeObject.getOrientation(), outlineWidth, innerColor, outerColor); + } + } + } + + private void drawOutline(WallObject wallObject, int outlineWidth, Color innerColor, Color outerColor) + { + LocalPoint lp = wallObject.getLocalLocation(); + if (lp != null) + { + Model model = wallObject.getModelA(); + if (model != null) + { + drawModelOutline(model, lp.getX(), lp.getY(), + Perspective.getTileHeight(client, lp, wallObject.getPlane()), + wallObject.getOrientationA(), outlineWidth, innerColor, outerColor); + } + + model = wallObject.getModelB(); + if (model != null) + { + drawModelOutline(model, lp.getX(), lp.getY(), + Perspective.getTileHeight(client, lp, wallObject.getPlane()), + wallObject.getOrientationB(), outlineWidth, innerColor, outerColor); + } + } + } + + public void drawOutline(TileObject tileObject, int outlineWidth, Color color) + { + drawOutline(tileObject, outlineWidth, color, color); + } + + public void drawOutline(TileObject tileObject, + int outlineWidth, Color innerColor, Color outerColor) + { + if (tileObject instanceof GameObject) + { + drawOutline((GameObject) tileObject, outlineWidth, innerColor, outerColor); + } + else if (tileObject instanceof GroundObject) + { + drawOutline((GroundObject) tileObject, outlineWidth, innerColor, outerColor); + } + else if (tileObject instanceof ItemLayer) + { + drawOutline((ItemLayer) tileObject, outlineWidth, innerColor, outerColor); + } + else if (tileObject instanceof DecorativeObject) + { + drawOutline((DecorativeObject) tileObject, outlineWidth, innerColor, outerColor); + } + else if (tileObject instanceof WallObject) + { + drawOutline((WallObject) tileObject, outlineWidth, innerColor, outerColor); + } + } + + @Value + @RequiredArgsConstructor + class PixelDistanceAlpha + { + private final int outerAlpha; + private final int distArrayPos; + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/com/openosrs/client/plugins/ExternalPluginClasspath.java b/runelite-client/src/main/java/com/openosrs/client/plugins/ExternalPluginClasspath.java deleted file mode 100644 index 0e0e72842b..0000000000 --- a/runelite-client/src/main/java/com/openosrs/client/plugins/ExternalPluginClasspath.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.openosrs.client.plugins; - -import org.pf4j.DevelopmentPluginClasspath; - -class ExternalPluginClasspath extends DevelopmentPluginClasspath -{ - static final String GRADLE_DEPS_PATH = "build/deps"; - - ExternalPluginClasspath() - { - addJarsDirectories(GRADLE_DEPS_PATH); - } -} diff --git a/runelite-client/src/main/java/com/openosrs/client/plugins/ExternalPluginFileFilter.java b/runelite-client/src/main/java/com/openosrs/client/plugins/ExternalPluginFileFilter.java deleted file mode 100644 index 39b261d861..0000000000 --- a/runelite-client/src/main/java/com/openosrs/client/plugins/ExternalPluginFileFilter.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.openosrs.client.plugins; - -import java.io.File; -import java.io.FileFilter; -import java.util.Arrays; -import java.util.List; - -/** - * Determines whether a {@link File} is an external plugin folder. To be considered a plugin a folder must: - *

- * * Must not be a blacklisted name - * * Have a {@code .gradle.kts} file in the root named after the folder - * * Have a {@code MANIFEST.MF} located at {@code build/tmp/jar/MANIFEST.MF} - */ -public class ExternalPluginFileFilter implements FileFilter -{ - private static final List blacklist = Arrays.asList( - ".git", - "build", - "target", - "release" - ); - - private static final List buildFiles = Arrays.asList( - "%s.gradle.kts", - "%s.gradle" - ); - - @Override - public boolean accept(File pathName) - { - // Check if this path looks like a plugin development directory - if (!pathName.isDirectory()) - { - return false; - } - - String dirName = pathName.getName(); - if (blacklist.contains(dirName)) - { - return false; - } - - // Check if the plugin directory has a MANIFEST.MF which si required for loading - if (!new File(pathName, ExternalPluginManager.DEVELOPMENT_MANIFEST_PATH).exists()) - { - return false; - } - - // By convention plugins their directory is $name and they have a $name.gradle.kts or $name.gradle file in their root - for (String buildFile : buildFiles) - { - if (new File(pathName, String.format(buildFile, dirName)).exists()) - { - return true; - } - } - - return false; - } -} diff --git a/runelite-client/src/main/java/com/openosrs/client/plugins/Plugin.java b/runelite-client/src/main/java/com/openosrs/client/plugins/Plugin.java deleted file mode 100644 index 81e661de09..0000000000 --- a/runelite-client/src/main/java/com/openosrs/client/plugins/Plugin.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.openosrs.client.plugins; - -import com.google.inject.Injector; -import org.pf4j.ExtensionPoint; - -public class Plugin extends net.runelite.client.plugins.Plugin implements ExtensionPoint -{ - public Injector injector; -} diff --git a/runelite-client/src/main/java/com/openosrs/client/plugins/openosrs/OpenOSRSPlugin.java b/runelite-client/src/main/java/com/openosrs/client/plugins/openosrs/OpenOSRSPlugin.java deleted file mode 100644 index 3f0ca8d288..0000000000 --- a/runelite-client/src/main/java/com/openosrs/client/plugins/openosrs/OpenOSRSPlugin.java +++ /dev/null @@ -1,289 +0,0 @@ -/* - * - * Copyright (c) 2019, Zeruth - * 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 com.openosrs.client.plugins.openosrs; - -import ch.qos.logback.classic.Logger; -import com.openosrs.client.plugins.openosrs.externals.ExternalPluginManagerPanel; -import com.openosrs.client.config.OpenOSRSConfig; -import java.awt.event.KeyEvent; -import java.awt.image.BufferedImage; -import javax.inject.Inject; -import javax.inject.Singleton; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.Client; -import static net.runelite.api.ScriptID.BANK_PIN_OP; -import net.runelite.api.events.ScriptCallbackEvent; -import net.runelite.api.widgets.WidgetID; -import static net.runelite.api.widgets.WidgetInfo.BANK_PIN_1; -import static net.runelite.api.widgets.WidgetInfo.BANK_PIN_10; -import static net.runelite.api.widgets.WidgetInfo.BANK_PIN_2; -import static net.runelite.api.widgets.WidgetInfo.BANK_PIN_3; -import static net.runelite.api.widgets.WidgetInfo.BANK_PIN_4; -import static net.runelite.api.widgets.WidgetInfo.BANK_PIN_5; -import static net.runelite.api.widgets.WidgetInfo.BANK_PIN_6; -import static net.runelite.api.widgets.WidgetInfo.BANK_PIN_7; -import static net.runelite.api.widgets.WidgetInfo.BANK_PIN_8; -import static net.runelite.api.widgets.WidgetInfo.BANK_PIN_9; -import static net.runelite.api.widgets.WidgetInfo.BANK_PIN_EXIT_BUTTON; -import static net.runelite.api.widgets.WidgetInfo.BANK_PIN_FIRST_ENTERED; -import static net.runelite.api.widgets.WidgetInfo.BANK_PIN_FORGOT_BUTTON; -import static net.runelite.api.widgets.WidgetInfo.BANK_PIN_FOURTH_ENTERED; -import static net.runelite.api.widgets.WidgetInfo.BANK_PIN_INSTRUCTION_TEXT; -import static net.runelite.api.widgets.WidgetInfo.BANK_PIN_SECOND_ENTERED; -import static net.runelite.api.widgets.WidgetInfo.BANK_PIN_THIRD_ENTERED; -import net.runelite.client.callback.ClientThread; -import net.runelite.client.config.Keybind; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.events.ConfigChanged; -import net.runelite.client.input.KeyListener; -import net.runelite.client.input.KeyManager; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.ui.ClientToolbar; -import net.runelite.client.ui.NavigationButton; -import net.runelite.client.util.HotkeyListener; -import net.runelite.client.util.ImageUtil; -import org.slf4j.LoggerFactory; - -@PluginDescriptor( - loadWhenOutdated = true, // prevent users from disabling - hidden = true, // prevent users from disabling - name = "OpenOSRS" -) -@Singleton -@Slf4j -public class OpenOSRSPlugin extends Plugin -{ - private final openosrsKeyListener keyListener = new openosrsKeyListener(); - - @Inject - private OpenOSRSConfig config; - - @Inject - private KeyManager keyManager; - - @Inject - private Client client; - - @Inject - private ClientThread clientThread; - - @Inject - private ClientToolbar clientToolbar; - - private NavigationButton navButton; - - private final HotkeyListener hotkeyListener = new HotkeyListener(() -> this.keybind) - { - @Override - public void hotkeyPressed() - { - detach = !detach; - client.setOculusOrbState(detach ? 1 : 0); - client.setOculusOrbNormalSpeed(detach ? 36 : 12); - } - }; - private int entered = -1; - private int enterIdx; - private boolean expectInput; - private boolean detach; - private Keybind keybind; - - @Override - protected void startUp() - { - ExternalPluginManagerPanel panel = injector.getInstance(ExternalPluginManagerPanel.class); - - final BufferedImage icon = ImageUtil.getResourceStreamFromClass(getClass(), "externalmanager_icon.png"); - - navButton = NavigationButton.builder() - .tooltip("External Plugin Manager") - .icon(icon) - .priority(1) - .panel(panel) - .build(); - clientToolbar.addNavigation(navButton); - - entered = -1; - enterIdx = 0; - expectInput = false; - this.keybind = config.detachHotkey(); - keyManager.registerKeyListener(hotkeyListener); - } - - @Override - protected void shutDown() - { - clientToolbar.removeNavigation(navButton); - - entered = 0; - enterIdx = 0; - expectInput = false; - keyManager.unregisterKeyListener(keyListener); - keyManager.unregisterKeyListener(hotkeyListener); - } - - @Subscribe - private void onConfigChanged(ConfigChanged event) - { - if (!event.getGroup().equals("openosrs")) - { - return; - } - - this.keybind = config.detachHotkey(); - - if (!config.keyboardPin()) - { - entered = 0; - enterIdx = 0; - expectInput = false; - keyManager.unregisterKeyListener(keyListener); - } - - if (event.getKey().equals("shareLogs") && !config.shareLogs()) - { - final Logger logger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME); - logger.detachAppender("Sentry"); - } - } - - @Subscribe - private void onScriptCallbackEvent(ScriptCallbackEvent e) - { - if (!config.keyboardPin()) - { - return; - } - - if (e.getEventName().equals("bankpin")) - { - int[] intStack = client.getIntStack(); - int intStackSize = client.getIntStackSize(); - - // This'll be anywhere from -1 to 3 - // 0 = first number, 1 second, etc - // Anything other than 0123 means the bankpin interface closes - int enterIdx = intStack[intStackSize - 1]; - - if (enterIdx < 0 || enterIdx > 3) - { - keyManager.unregisterKeyListener(keyListener); - this.enterIdx = 0; - this.entered = 0; - expectInput = false; - return; - } - else if (enterIdx == 0) - { - keyManager.registerKeyListener(keyListener); - } - - this.enterIdx = enterIdx; - expectInput = true; - } - } - - private void handleKey(char c) - { - if (client.getWidget(WidgetID.BANK_PIN_GROUP_ID, BANK_PIN_INSTRUCTION_TEXT.getChildId()) == null - || !client.getWidget(BANK_PIN_INSTRUCTION_TEXT).getText().equals("First click the FIRST digit.") - && !client.getWidget(BANK_PIN_INSTRUCTION_TEXT).getText().equals("Now click the SECOND digit.") - && !client.getWidget(BANK_PIN_INSTRUCTION_TEXT).getText().equals("Time for the THIRD digit.") - && !client.getWidget(BANK_PIN_INSTRUCTION_TEXT).getText().equals("Finally, the FOURTH digit.")) - - { - entered = 0; - enterIdx = 0; - expectInput = false; - keyManager.unregisterKeyListener(keyListener); - return; - } - - if (!expectInput) - { - return; - } - - int num = Character.getNumericValue(c); - - // We gotta copy this cause enteridx changes while the script is executing - int oldEnterIdx = enterIdx; - - // Script 685 will call 653, which in turn will set expectInput to true - expectInput = false; - client.runScript(BANK_PIN_OP, num, enterIdx, entered, BANK_PIN_EXIT_BUTTON.getId(), BANK_PIN_FORGOT_BUTTON.getId(), BANK_PIN_1.getId(), BANK_PIN_2.getId(), BANK_PIN_3.getId(), BANK_PIN_4.getId(), BANK_PIN_5.getId(), BANK_PIN_6.getId(), BANK_PIN_7.getId(), BANK_PIN_8.getId(), BANK_PIN_9.getId(), BANK_PIN_10.getId(), BANK_PIN_FIRST_ENTERED.getId(), BANK_PIN_SECOND_ENTERED.getId(), BANK_PIN_THIRD_ENTERED.getId(), BANK_PIN_FOURTH_ENTERED.getId(), BANK_PIN_INSTRUCTION_TEXT.getId()); - - if (oldEnterIdx == 0) - { - entered = num * 1000; - } - else if (oldEnterIdx == 1) - { - entered += num * 100; - } - else if (oldEnterIdx == 2) - { - entered += num * 10; - } - } - - private class openosrsKeyListener implements KeyListener - { - private int lastKeyCycle; - - @Override - public void keyTyped(KeyEvent keyEvent) - { - if (!Character.isDigit(keyEvent.getKeyChar())) - { - return; - } - - if (client.getGameCycle() - lastKeyCycle <= 5) - { - keyEvent.consume(); - return; - } - - lastKeyCycle = client.getGameCycle(); - - clientThread.invoke(() -> handleKey(keyEvent.getKeyChar())); - keyEvent.consume(); - } - - @Override - public void keyPressed(KeyEvent keyEvent) - { - } - - @Override - public void keyReleased(KeyEvent keyEvent) - { - } - } -} \ No newline at end of file diff --git a/runelite-client/src/main/java/com/openosrs/client/ui/components/InfoPanel.java b/runelite-client/src/main/java/com/openosrs/client/ui/components/InfoPanel.java index 07efae32cb..f0d0fa1b2f 100644 --- a/runelite-client/src/main/java/com/openosrs/client/ui/components/InfoPanel.java +++ b/runelite-client/src/main/java/com/openosrs/client/ui/components/InfoPanel.java @@ -24,6 +24,7 @@ */ package com.openosrs.client.ui.components; +import com.openosrs.client.OpenOSRS; import java.awt.Color; import java.awt.Cursor; import java.awt.Dimension; @@ -46,7 +47,7 @@ import net.runelite.client.ui.ColorScheme; import net.runelite.client.ui.FontManager; import com.openosrs.client.ui.OpenOSRSSplashScreen; import net.runelite.client.util.ImageUtil; -import com.openosrs.client.util.LinkBrowser; +import net.runelite.client.util.LinkBrowser; @Slf4j public class InfoPanel extends JPanel @@ -88,7 +89,7 @@ public class InfoPanel extends JPanel c.weighty = 0; // OpenOSRS version - this.add(createPanelTextButton("OpenOSRS Version: " + RuneLiteProperties.getLauncherVersion()), c); + this.add(createPanelTextButton("OpenOSRS Version: " + OpenOSRS.SYSTEM_VERSION), c); c.gridy++; final JLabel logsFolder = createPanelButton("Open logs folder", null, () -> LinkBrowser.openLocalFile(LOGS_DIR)); diff --git a/runelite-client/src/main/java/com/openosrs/client/ui/overlay/OverlayUtil.java b/runelite-client/src/main/java/com/openosrs/client/ui/overlay/OverlayUtil.java deleted file mode 100644 index 06fd875d6d..0000000000 --- a/runelite-client/src/main/java/com/openosrs/client/ui/overlay/OverlayUtil.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.openosrs.client.ui.overlay; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.Polygon; -import net.runelite.api.Client; -import net.runelite.api.Perspective; -import net.runelite.api.coords.LocalPoint; -import net.runelite.api.coords.WorldPoint; - -public class OverlayUtil extends net.runelite.client.ui.overlay.OverlayUtil -{ - public static void drawTiles(Graphics2D graphics, Client client, WorldPoint point, WorldPoint playerPoint, Color color, int strokeWidth, int outlineAlpha, int fillAlpha) - { - if (point.distanceTo(playerPoint) >= 32) - { - return; - } - LocalPoint lp = LocalPoint.fromWorld(client, point); - if (lp == null) - { - return; - } - - Polygon poly = Perspective.getCanvasTilePoly(client, lp); - if (poly == null) - { - return; - } - drawStrokeAndFillPoly(graphics, color, strokeWidth, outlineAlpha, fillAlpha, poly); - } - - public static void drawStrokeAndFillPoly(Graphics2D graphics, Color color, int strokeWidth, int outlineAlpha, int fillAlpha, Polygon poly) - { - graphics.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), outlineAlpha)); - graphics.setStroke(new BasicStroke(strokeWidth)); - graphics.draw(poly); - graphics.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), fillAlpha)); - graphics.fill(poly); - } -} diff --git a/runelite-client/src/main/java/com/openosrs/client/util/ColorUtil.java b/runelite-client/src/main/java/com/openosrs/client/util/ColorUtil.java deleted file mode 100644 index 57f68c4703..0000000000 --- a/runelite-client/src/main/java/com/openosrs/client/util/ColorUtil.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.openosrs.client.util; - -import java.awt.Color; - -public class ColorUtil extends net.runelite.client.util.ColorUtil -{ - /** - * Modifies the alpha component on a Color - * - * @param color The color to set the alpha value on - * @param alpha The alpha value to set on the color - * @return color - */ - public static int setAlphaComponent(Color color, int alpha) - { - return setAlphaComponent(color.getRGB(), alpha); - } - - /** - * Modifies the alpha component on a Color - * - * @param color The color to set the alpha value on - * @param alpha The alpha value to set on the color - * @return color - */ - public static int setAlphaComponent(int color, int alpha) - { - if (alpha < 0 || alpha > 255) - { - throw new IllegalArgumentException("alpha must be between 0 and 255."); - } - return (color & 0x00ffffff) | (alpha << 24); - } -} diff --git a/runelite-client/src/main/java/com/openosrs/client/util/DeferredDocumentChangedListener.java b/runelite-client/src/main/java/com/openosrs/client/util/DeferredDocumentChangedListener.java deleted file mode 100644 index b9728e03be..0000000000 --- a/runelite-client/src/main/java/com/openosrs/client/util/DeferredDocumentChangedListener.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.openosrs.client.util; - -import java.util.ArrayList; -import java.util.List; -import javax.swing.Timer; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; - -public class DeferredDocumentChangedListener implements DocumentListener -{ - private final Timer timer; - private final List listeners; - - public DeferredDocumentChangedListener() - { - listeners = new ArrayList<>(25); - timer = new Timer(200, e -> fireStateChanged()); - timer.setRepeats(false); - } - - public void addChangeListener(ChangeListener listener) - { - listeners.add(listener); - } - - private void fireStateChanged() - { - if (!listeners.isEmpty()) - { - ChangeEvent evt = new ChangeEvent(this); - for (ChangeListener listener : listeners) - { - listener.stateChanged(evt); - } - } - } - - @Override - public void insertUpdate(DocumentEvent e) - { - timer.restart(); - } - - @Override - public void removeUpdate(DocumentEvent e) - { - timer.restart(); - } - - @Override - public void changedUpdate(DocumentEvent e) - { - timer.restart(); - } - -} diff --git a/runelite-client/src/main/java/com/openosrs/client/util/ImageUtil.java b/runelite-client/src/main/java/com/openosrs/client/util/ImageUtil.java deleted file mode 100644 index 3282e61c98..0000000000 --- a/runelite-client/src/main/java/com/openosrs/client/util/ImageUtil.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.openosrs.client.util; - -import java.awt.Color; -import java.awt.image.BufferedImage; -import java.awt.image.WritableRaster; -import java.util.function.Predicate; - -public class ImageUtil extends net.runelite.client.util.ImageUtil -{ - /** - * Recolors pixels of the given image with the given color based on a given recolor condition - * predicate. - * - * @param image The image which should have its non-transparent pixels recolored. - * @param color The color with which to recolor pixels. - * @param recolorCondition The condition on which to recolor pixels with the given color. - * @return The given image with all pixels fulfilling the recolor condition predicate - * set to the given color. - */ - public static BufferedImage recolorImage(final BufferedImage image, final Color color, final Predicate recolorCondition) - { - final BufferedImage recoloredImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB); - for (int x = 0; x < recoloredImage.getWidth(); x++) - { - for (int y = 0; y < recoloredImage.getHeight(); y++) - { - final Color pixelColor = new Color(image.getRGB(x, y), true); - if (!recolorCondition.test(pixelColor)) - { - recoloredImage.setRGB(x, y, image.getRGB(x, y)); - continue; - } - - recoloredImage.setRGB(x, y, color.getRGB()); - } - } - return recoloredImage; - } - - public static BufferedImage recolorImage(BufferedImage image, final Color color) - { - int width = image.getWidth(); - int height = image.getHeight(); - WritableRaster raster = image.getRaster(); - - for (int xx = 0; xx < width; xx++) - { - for (int yy = 0; yy < height; yy++) - { - int[] pixels = raster.getPixel(xx, yy, (int[]) null); - pixels[0] = color.getRed(); - pixels[1] = color.getGreen(); - pixels[2] = color.getBlue(); - raster.setPixel(xx, yy, pixels); - } - } - return image; - } -} diff --git a/runelite-client/src/main/java/com/openosrs/client/util/LinkBrowser.java b/runelite-client/src/main/java/com/openosrs/client/util/LinkBrowser.java deleted file mode 100644 index 64df5e1127..0000000000 --- a/runelite-client/src/main/java/com/openosrs/client/util/LinkBrowser.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.openosrs.client.util; - -import java.awt.Desktop; -import java.awt.Toolkit; -import java.awt.datatransfer.StringSelection; -import java.io.File; -import java.io.IOException; -import javax.swing.JOptionPane; -import javax.swing.SwingUtilities; -import lombok.extern.slf4j.Slf4j; - -@Slf4j -public class LinkBrowser extends net.runelite.client.util.LinkBrowser -{ - /** - * Tries to open the specified {@code File} with the systems default text editor. If operation fails - * an error message is displayed with the option to copy the absolute file path to clipboard. - * - * @param file the File instance of the log file - * @return did the file open successfully? - */ - public static boolean openLocalFile(final File file) - { - if (file == null || !file.exists()) - { - return false; - } - - if (attemptOpenLocalFile(file)) - { - log.debug("Opened log file through Desktop#edit to {}", file); - return true; - } - - showMessageBox("Unable to open log file. Press 'OK' and the file path will be copied to your clipboard", file.getAbsolutePath()); - return false; - } - - private static boolean attemptOpenLocalFile(final File file) - { - if (!Desktop.isDesktopSupported()) - { - return false; - } - - final Desktop desktop = Desktop.getDesktop(); - - if (!desktop.isSupported(Desktop.Action.OPEN)) - { - return false; - } - - try - { - desktop.open(file); - return true; - } - catch (IOException ex) - { - log.warn("Failed to open Desktop#edit {}", file, ex); - return false; - } - } - - /** - * Open swing message box with specified message and copy data to clipboard - * @param message message to show - */ - private static void showMessageBox(final String message, final String data) - { - SwingUtilities.invokeLater(() -> - { - final int result = JOptionPane.showConfirmDialog(null, message, "Message", - JOptionPane.OK_CANCEL_OPTION); - - if (result == JOptionPane.OK_OPTION) - { - final StringSelection stringSelection = new StringSelection(data); - Toolkit.getDefaultToolkit().getSystemClipboard().setContents(stringSelection, null); - } - }); - } -} diff --git a/runelite-client/src/main/java/com/openosrs/client/util/MiscUtils.java b/runelite-client/src/main/java/com/openosrs/client/util/MiscUtils.java deleted file mode 100644 index d5bc562121..0000000000 --- a/runelite-client/src/main/java/com/openosrs/client/util/MiscUtils.java +++ /dev/null @@ -1,202 +0,0 @@ -package com.openosrs.client.util; - -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; -import net.runelite.api.Client; -import net.runelite.api.Player; -import net.runelite.api.WorldType; -import net.runelite.api.coords.WorldPoint; - -public class MiscUtils -{ - private static final int[] abovePointsX = {2944, 3392, 3392, 2944}; - private static final int[] abovePointsY = {3523, 3523, 3971, 3971}; - private static final int[] belowPointsX = {2944, 2944, 3264, 3264}; - private static final int[] belowPointsY = {9918, 10360, 10360, 9918}; - - private static final Polygon abovePoly = new Polygon(abovePointsX, abovePointsY, abovePointsX.length); - private static final Polygon belowPoly = new Polygon(belowPointsX, belowPointsY, belowPointsX.length); - - private static final ChronoUnit[] ORDERED_CHRONOS = new ChronoUnit[] - { - ChronoUnit.YEARS, - ChronoUnit.MONTHS, - ChronoUnit.WEEKS, - ChronoUnit.DAYS, - ChronoUnit.HOURS, - ChronoUnit.MINUTES, - ChronoUnit.SECONDS - }; - - //test replacement so private for now - private static boolean inWildy(WorldPoint point) - { - if (point == null) - { - return false; - } - - return abovePoly.contains(point.getX(), point.getY()) || belowPoly.contains(point.getX(), point.getY()); - } - - public static int getWildernessLevelFrom(Client client, WorldPoint point) - { - if (client == null) - { - return 0; - } - - if (point == null) - { - return 0; - } - - int x = point.getX(); - - if (point.getPlane() == 0 && (x < 2940 || x > 3391)) - { - return 0; - } - - int y = point.getY(); - //v underground //v above ground - int wildernessLevel = clamp(y > 6400 ? ((y - 9920) / 8) + 1 : ((y - 3520) / 8) + 1, 0, 56); - - if (point.getPlane() > 0 && y < 9920) - { - wildernessLevel = 0; - } - - if (client.getWorldType().stream().anyMatch(worldType -> worldType == WorldType.PVP || worldType == WorldType.HIGH_RISK)) - { - wildernessLevel += 15; - } - - return Math.max(0, wildernessLevel); - } - - public static int clamp(int val, int min, int max) - { - return Math.max(min, Math.min(max, val)); - } - - public static float clamp(float val, float min, float max) - { - return Math.max(min, Math.min(max, val)); - } - - public static boolean inWilderness(Client client) - { - Player localPlayer = client.getLocalPlayer(); - - if (localPlayer == null) - { - return false; - } - - return inWildy(localPlayer.getWorldLocation()); - - //return getWildernessLevelFrom(client, localPlayer.getWorldLocation()) > 0; - } - - public static String formatTimeAgo(Duration dur) - { - long dA = 0, dB = 0, rm; - ChronoUnit cA = null, cB = null; - for (int i = 0; i < ORDERED_CHRONOS.length; i++) - { - cA = ORDERED_CHRONOS[i]; - dA = dur.getSeconds() / cA.getDuration().getSeconds(); - rm = dur.getSeconds() % cA.getDuration().getSeconds(); - if (dA <= 0) - { - cA = null; - continue; - } - - if (i + 1 < ORDERED_CHRONOS.length) - { - cB = ORDERED_CHRONOS[i + 1]; - dB = rm / cB.getDuration().getSeconds(); - - if (dB <= 0) - { - cB = null; - } - } - - break; - } - - if (cA == null) - { - return "just now."; - } - - String str = formatUnit(cA, dA); - - if (cB != null) - { - str += " and " + formatUnit(cB, dB); - } - - return str + " ago."; - } - - private static String formatUnit(ChronoUnit chrono, long val) - { - boolean multiple = val != 1; - String str; - if (multiple) - { - str = val + " "; - } - else - { - str = "a" + (chrono == ChronoUnit.HOURS ? "n " : " "); - } - str += chrono.name().toLowerCase(); - if (!multiple) - { - if (str.charAt(str.length() - 1) == 's') - { - str = str.substring(0, str.length() - 1); - } - } - else if (str.charAt(str.length() - 1) != 's') - { - str += "s"; - } - 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); - } -} diff --git a/runelite-client/src/main/java/com/openosrs/client/util/SwingUtil.java b/runelite-client/src/main/java/com/openosrs/client/util/SwingUtil.java deleted file mode 100644 index 799b67bfa4..0000000000 --- a/runelite-client/src/main/java/com/openosrs/client/util/SwingUtil.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.openosrs.client.util; - -import java.awt.EventQueue; -import java.lang.reflect.InvocationTargetException; - -public class SwingUtil extends net.runelite.client.util.SwingUtil -{ - public static void syncExec(final Runnable r) throws InvocationTargetException, InterruptedException - { - if (EventQueue.isDispatchThread()) - { - r.run(); - } - else - { - EventQueue.invokeAndWait(r); - } - } -} diff --git a/runelite-client/src/main/java/com/openosrs/client/util/WeaponMap.java b/runelite-client/src/main/java/com/openosrs/client/util/WeaponMap.java new file mode 100644 index 0000000000..8dda59ad46 --- /dev/null +++ b/runelite-client/src/main/java/com/openosrs/client/util/WeaponMap.java @@ -0,0 +1,832 @@ +package com.openosrs.client.util; + +import java.util.HashMap; +import net.runelite.api.ItemID; + +public class WeaponMap +{ + public static HashMap StyleMap = new HashMap<>(); + + static + { + //Melee + StyleMap.put(ItemID._3RD_AGE_AXE, WeaponStyle.MELEE); + StyleMap.put(ItemID._3RD_AGE_LONGSWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID._3RD_AGE_PICKAXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.ABYSSAL_BLUDGEON, WeaponStyle.MELEE); + StyleMap.put(ItemID.ABYSSAL_DAGGER, WeaponStyle.MELEE); + StyleMap.put(ItemID.ABYSSAL_DAGGER_P, WeaponStyle.MELEE); + StyleMap.put(ItemID.ABYSSAL_DAGGER_P_13269, WeaponStyle.MELEE); + StyleMap.put(ItemID.ABYSSAL_DAGGER_P_13271, WeaponStyle.MELEE); + StyleMap.put(ItemID.ABYSSAL_TENTACLE, WeaponStyle.MELEE); + StyleMap.put(ItemID.ABYSSAL_WHIP, WeaponStyle.MELEE); + StyleMap.put(ItemID.ABYSSAL_WHIP_20405, WeaponStyle.MELEE); + StyleMap.put(ItemID.ADAMANT_2H_SWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.ADAMANT_AXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.ADAMANT_BATTLEAXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.ADAMANT_CANE, WeaponStyle.MELEE); + StyleMap.put(ItemID.ADAMANT_CLAWS, WeaponStyle.MELEE); + StyleMap.put(ItemID.ADAMANT_DAGGER, WeaponStyle.MELEE); + StyleMap.put(ItemID.ADAMANT_DAGGERP, WeaponStyle.MELEE); + StyleMap.put(ItemID.ADAMANT_DAGGERP_5676, WeaponStyle.MELEE); + StyleMap.put(ItemID.ADAMANT_DAGGERP_5694, WeaponStyle.MELEE); + StyleMap.put(ItemID.ADAMANT_HALBERD, WeaponStyle.MELEE); + StyleMap.put(ItemID.ADAMANT_HASTA, WeaponStyle.MELEE); + StyleMap.put(ItemID.ADAMANT_LONGSWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.ADAMANT_MACE, WeaponStyle.MELEE); + StyleMap.put(ItemID.ADAMANT_PICKAXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.ADAMANT_SCIMITAR, WeaponStyle.MELEE); + StyleMap.put(ItemID.ADAMANT_SPEAR, WeaponStyle.MELEE); + StyleMap.put(ItemID.ADAMANT_SPEARP, WeaponStyle.MELEE); + StyleMap.put(ItemID.ADAMANT_SPEARP_5712, WeaponStyle.MELEE); + StyleMap.put(ItemID.ADAMANT_SPEARP_5726, WeaponStyle.MELEE); + StyleMap.put(ItemID.ADAMANT_SWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.ADAMANT_WARHAMMER, WeaponStyle.MELEE); + StyleMap.put(ItemID.ALE_OF_THE_GODS, WeaponStyle.MELEE); + StyleMap.put(ItemID.ANCIENT_MACE, WeaponStyle.MELEE); + StyleMap.put(ItemID.ANGER_BATTLEAXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.ANGER_MACE, WeaponStyle.MELEE); + StyleMap.put(ItemID.ANGER_SPEAR, WeaponStyle.MELEE); + StyleMap.put(ItemID.ANGER_SWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.AMYS_SAW, WeaponStyle.MELEE); + StyleMap.put(ItemID.ARCEUUS_BANNER, WeaponStyle.MELEE); + StyleMap.put(ItemID.ARCLIGHT, WeaponStyle.MELEE); + StyleMap.put(ItemID.ARMADYL_GODSWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.ARMADYL_GODSWORD_20593, WeaponStyle.MELEE); + StyleMap.put(ItemID.ARMADYL_GODSWORD_22665, WeaponStyle.MELEE); + StyleMap.put(ItemID.ARMADYL_GODSWORD_OR, WeaponStyle.MELEE); + StyleMap.put(ItemID.ASSORTED_FLOWERS, WeaponStyle.MELEE); + StyleMap.put(ItemID.BANDOS_GODSWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.BANDOS_GODSWORD_20782, WeaponStyle.MELEE); + StyleMap.put(ItemID.BANDOS_GODSWORD_21060, WeaponStyle.MELEE); + StyleMap.put(ItemID.BANDOS_GODSWORD_OR, WeaponStyle.MELEE); + StyleMap.put(ItemID.BARBTAIL_HARPOON, WeaponStyle.MELEE); + StyleMap.put(ItemID.BARRELCHEST_ANCHOR, WeaponStyle.MELEE); + StyleMap.put(ItemID.BEACH_BOXING_GLOVES, WeaponStyle.MELEE); + StyleMap.put(ItemID.BEACH_BOXING_GLOVES_11706, WeaponStyle.MELEE); + StyleMap.put(ItemID.BIRTHDAY_BALLOONS, WeaponStyle.MELEE); + StyleMap.put(ItemID.BIRTHDAY_CAKE, WeaponStyle.MELEE); + StyleMap.put(ItemID.BLACK_2H_SWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.BLACK_AXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.BLACK_BATTLEAXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.BLACK_CANE, WeaponStyle.MELEE); + StyleMap.put(ItemID.BLACK_CLAWS, WeaponStyle.MELEE); + StyleMap.put(ItemID.BLACK_DAGGER, WeaponStyle.MELEE); + StyleMap.put(ItemID.BLACK_DAGGERP, WeaponStyle.MELEE); + StyleMap.put(ItemID.BLACK_DAGGERP_5682, WeaponStyle.MELEE); + StyleMap.put(ItemID.BLACK_DAGGERP_5700, WeaponStyle.MELEE); + StyleMap.put(ItemID.BLACK_FLOWERS, WeaponStyle.MELEE); + StyleMap.put(ItemID.BLACK_HALBERD, WeaponStyle.MELEE); + StyleMap.put(ItemID.BLACK_LONGSWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.BLACK_MACE, WeaponStyle.MELEE); + StyleMap.put(ItemID.BLACK_PICKAXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.BLACK_SALAMANDER, WeaponStyle.MELEE); + StyleMap.put(ItemID.BLACK_SCIMITAR, WeaponStyle.MELEE); + StyleMap.put(ItemID.BLACK_SPEAR, WeaponStyle.MELEE); + StyleMap.put(ItemID.BLACK_SPEARP, WeaponStyle.MELEE); + StyleMap.put(ItemID.BLACK_SPEARP_5734, WeaponStyle.MELEE); + StyleMap.put(ItemID.BLACK_SPEARP_5736, WeaponStyle.MELEE); + StyleMap.put(ItemID.BLACK_SWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.BLACK_WARHAMMER, WeaponStyle.MELEE); + StyleMap.put(ItemID.BLADE_OF_SAELDOR, WeaponStyle.MELEE); + StyleMap.put(ItemID.BLADE_OF_SAELDOR_C, WeaponStyle.MELEE); + StyleMap.put(ItemID.BLADE_OF_SAELDOR_INACTIVE, WeaponStyle.MELEE); + StyleMap.put(ItemID.BLESSED_AXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.BLISTERWOOD_SICKLE, WeaponStyle.MELEE); + StyleMap.put(ItemID.BLUE_FLOWERS, WeaponStyle.MELEE); + StyleMap.put(ItemID.BLUE_FLOWERS_8936, WeaponStyle.MELEE); + StyleMap.put(ItemID.BLURITE_SWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.BONE_CLUB, WeaponStyle.MELEE); + StyleMap.put(ItemID.BONE_DAGGER, WeaponStyle.MELEE); + StyleMap.put(ItemID.BONE_DAGGER_P, WeaponStyle.MELEE); + StyleMap.put(ItemID.BONE_DAGGER_P_8876, WeaponStyle.MELEE); + StyleMap.put(ItemID.BONE_DAGGER_P_8878, WeaponStyle.MELEE); + StyleMap.put(ItemID.BONE_SPEAR, WeaponStyle.MELEE); + StyleMap.put(ItemID.BOXING_GLOVES, WeaponStyle.MELEE); + StyleMap.put(ItemID.BOXING_GLOVES_7673, WeaponStyle.MELEE); + StyleMap.put(ItemID.BRINE_SABRE, WeaponStyle.MELEE); + StyleMap.put(ItemID.BRONZE_2H_SWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.BRONZE_AXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.BRONZE_BATTLEAXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.BRONZE_CLAWS, WeaponStyle.MELEE); + StyleMap.put(ItemID.BRONZE_DAGGER, WeaponStyle.MELEE); + StyleMap.put(ItemID.BRONZE_DAGGERP, WeaponStyle.MELEE); + StyleMap.put(ItemID.BRONZE_DAGGERP_5670, WeaponStyle.MELEE); + StyleMap.put(ItemID.BRONZE_DAGGERP_5688, WeaponStyle.MELEE); + StyleMap.put(ItemID.BRONZE_HALBERD, WeaponStyle.MELEE); + StyleMap.put(ItemID.BRONZE_HASTA, WeaponStyle.MELEE); + StyleMap.put(ItemID.BRONZE_LONGSWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.BRONZE_MACE, WeaponStyle.MELEE); + StyleMap.put(ItemID.BRONZE_PICKAXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.BRONZE_SCIMITAR, WeaponStyle.MELEE); + StyleMap.put(ItemID.BRONZE_SPEAR, WeaponStyle.MELEE); + StyleMap.put(ItemID.BRONZE_SPEARP, WeaponStyle.MELEE); + StyleMap.put(ItemID.BRONZE_SPEARP_5704, WeaponStyle.MELEE); + StyleMap.put(ItemID.BRONZE_SPEARP_5718, WeaponStyle.MELEE); + StyleMap.put(ItemID.BRONZE_SWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.BRONZE_WARHAMMER, WeaponStyle.MELEE); + StyleMap.put(ItemID.BRUMA_TORCH, WeaponStyle.MELEE); + StyleMap.put(ItemID.BUTTERFLY_NET, WeaponStyle.MELEE); + StyleMap.put(ItemID.CANDY_CANE, WeaponStyle.MELEE); + StyleMap.put(ItemID.CATTLEPROD, WeaponStyle.MELEE); + StyleMap.put(ItemID.CHAOTIC_HANDEGG, WeaponStyle.MELEE); + StyleMap.put(ItemID.CLEAVER, WeaponStyle.MELEE); + StyleMap.put(ItemID.CORRUPTED_AXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.CORRUPTED_HALBERD_ATTUNED, WeaponStyle.MELEE); + StyleMap.put(ItemID.CORRUPTED_HALBERD_BASIC, WeaponStyle.MELEE); + StyleMap.put(ItemID.CORRUPTED_HALBERD_PERFECTED, WeaponStyle.MELEE); + StyleMap.put(ItemID.CORRUPTED_HARPOON, WeaponStyle.MELEE); + StyleMap.put(ItemID.CORRUPTED_PICKAXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.CORRUPTED_SCEPTRE, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRIER_BELL, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_AXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_AXE_23862, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_AXE_INACTIVE, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_HALBERD, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_HALBERD_110, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_HALBERD_110_I, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_HALBERD_210, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_HALBERD_210_I, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_HALBERD_24125, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_HALBERD_310, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_HALBERD_310_I, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_HALBERD_410, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_HALBERD_410_I, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_HALBERD_510, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_HALBERD_510_I, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_HALBERD_610, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_HALBERD_610_I, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_HALBERD_710, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_HALBERD_710_I, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_HALBERD_810, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_HALBERD_810_I, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_HALBERD_910, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_HALBERD_910_I, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_HALBERD_ATTUNED, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_HALBERD_BASIC, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_HALBERD_FULL, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_HALBERD_FULL_I, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_HALBERD_INACTIVE, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_HALBERD_PERFECTED, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_HARPOON, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_HARPOON_23864, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_HARPOON_INACTIVE, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_PICKAXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_PICKAXE_23863, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_PICKAXE_INACTIVE, WeaponStyle.MELEE); + StyleMap.put(ItemID.CRYSTAL_SCEPTRE, WeaponStyle.MELEE); + StyleMap.put(ItemID.CURSED_GOBLIN_HAMMER, WeaponStyle.MELEE); + StyleMap.put(ItemID.DARKLIGHT, WeaponStyle.MELEE); + StyleMap.put(ItemID.DARK_DAGGER, WeaponStyle.MELEE); + StyleMap.put(ItemID.DECORATIVE_SWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.DECORATIVE_SWORD_4503, WeaponStyle.MELEE); + StyleMap.put(ItemID.DECORATIVE_SWORD_4508, WeaponStyle.MELEE); + StyleMap.put(ItemID.DHAROKS_GREATAXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.DHAROKS_GREATAXE_0, WeaponStyle.MELEE); + StyleMap.put(ItemID.DHAROKS_GREATAXE_100, WeaponStyle.MELEE); + StyleMap.put(ItemID.DHAROKS_GREATAXE_25, WeaponStyle.MELEE); + StyleMap.put(ItemID.DHAROKS_GREATAXE_50, WeaponStyle.MELEE); + StyleMap.put(ItemID.DHAROKS_GREATAXE_75, WeaponStyle.MELEE); + StyleMap.put(ItemID.DINHS_BULWARK, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_2H_SWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_2H_SWORD_20559, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_AXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_BATTLEAXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_CANE, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_CLAWS, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_CLAWS_20784, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_DAGGER, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_DAGGER_20407, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_DAGGERP, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_DAGGERP_5680, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_DAGGERP_5698, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_HALBERD, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_HARPOON, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_HASTA, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_HASTAKP, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_HASTAP, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_HASTAP_22737, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_HASTAP_22740, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_HUNTER_LANCE, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_LONGSWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_MACE, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_PICKAXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_PICKAXE_12797, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_PICKAXE_OR, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_SCIMITAR, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_SCIMITAR_20406, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_SCIMITAR_OR, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_SPEAR, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_SPEARP, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_SPEARP_5716, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_SPEARP_5730, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_SWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_WARHAMMER, WeaponStyle.MELEE); + StyleMap.put(ItemID.DRAGON_WARHAMMER_20785, WeaponStyle.MELEE); + StyleMap.put(ItemID.EASTER_BASKET, WeaponStyle.MELEE); + StyleMap.put(ItemID.EGG_WHISK, WeaponStyle.MELEE); + StyleMap.put(ItemID.ELDER_MAUL, WeaponStyle.MELEE); + StyleMap.put(ItemID.ELDER_MAUL_21205, WeaponStyle.MELEE); + StyleMap.put(ItemID.ENCHANTED_LYRE, WeaponStyle.MELEE); + StyleMap.put(ItemID.ENCHANTED_LYRE1, WeaponStyle.MELEE); + StyleMap.put(ItemID.ENCHANTED_LYRE2, WeaponStyle.MELEE); + StyleMap.put(ItemID.ENCHANTED_LYRE3, WeaponStyle.MELEE); + StyleMap.put(ItemID.ENCHANTED_LYRE4, WeaponStyle.MELEE); + StyleMap.put(ItemID.ENCHANTED_LYRE5, WeaponStyle.MELEE); + StyleMap.put(ItemID.EVENT_RPG, WeaponStyle.MELEE); + StyleMap.put(ItemID.EXCALIBUR, WeaponStyle.MELEE); + StyleMap.put(ItemID.EXCALIBUR_8280, WeaponStyle.MELEE); + StyleMap.put(ItemID.FLAMTAER_HAMMER, WeaponStyle.MELEE); + StyleMap.put(ItemID.FREMENNIK_BLADE, WeaponStyle.MELEE); + StyleMap.put(ItemID.FROZEN_ABYSSAL_WHIP, WeaponStyle.MELEE); + StyleMap.put(ItemID.GADDERHAMMER, WeaponStyle.MELEE); + StyleMap.put(ItemID.GHRAZI_RAPIER, WeaponStyle.MELEE); + StyleMap.put(ItemID.GHRAZI_RAPIER_23628, WeaponStyle.MELEE); + StyleMap.put(ItemID.GILDED_2H_SWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.GILDED_HASTA, WeaponStyle.MELEE); + StyleMap.put(ItemID.GILDED_SCIMITAR, WeaponStyle.MELEE); + StyleMap.put(ItemID.GILDED_SPEAR, WeaponStyle.MELEE); + StyleMap.put(ItemID.GLOWING_DAGGER, WeaponStyle.MELEE); + StyleMap.put(ItemID.GOLDEN_TENCH, WeaponStyle.MELEE); + StyleMap.put(ItemID.GRANITE_HAMMER, WeaponStyle.MELEE); + StyleMap.put(ItemID.GRANITE_LONGSWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.GRANITE_MAUL, WeaponStyle.MELEE); + StyleMap.put(ItemID.GRANITE_MAUL_12848, WeaponStyle.MELEE); + StyleMap.put(ItemID.GRANITE_MAUL_20557, WeaponStyle.MELEE); + StyleMap.put(ItemID.GRANITE_MAUL_24225, WeaponStyle.MELEE); + StyleMap.put(ItemID.GRANITE_MAUL_24227, WeaponStyle.MELEE); + StyleMap.put(ItemID.GREEN_BANNER, WeaponStyle.MELEE); + StyleMap.put(ItemID.GUTHANS_WARSPEAR, WeaponStyle.MELEE); + StyleMap.put(ItemID.GUTHANS_WARSPEAR_0, WeaponStyle.MELEE); + StyleMap.put(ItemID.GUTHANS_WARSPEAR_100, WeaponStyle.MELEE); + StyleMap.put(ItemID.GUTHANS_WARSPEAR_25, WeaponStyle.MELEE); + StyleMap.put(ItemID.GUTHANS_WARSPEAR_50, WeaponStyle.MELEE); + StyleMap.put(ItemID.GUTHANS_WARSPEAR_75, WeaponStyle.MELEE); + StyleMap.put(ItemID.HALBERD, WeaponStyle.MELEE); + StyleMap.put(ItemID.HARRYS_CUTLASS, WeaponStyle.MELEE); + StyleMap.put(ItemID.HAM_JOINT, WeaponStyle.MELEE); + StyleMap.put(ItemID.HAND_FAN, WeaponStyle.MELEE); + StyleMap.put(ItemID.HILL_GIANT_CLUB, WeaponStyle.MELEE); + StyleMap.put(ItemID.HOLY_HANDEGG, WeaponStyle.MELEE); + StyleMap.put(ItemID.HOSIDIUS_BANNER, WeaponStyle.MELEE); + StyleMap.put(ItemID.INFERNAL_AXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.INFERNAL_AXE_UNCHARGED, WeaponStyle.MELEE); + StyleMap.put(ItemID.INFERNAL_HARPOON, WeaponStyle.MELEE); + StyleMap.put(ItemID.INFERNAL_HARPOON_UNCHARGED, WeaponStyle.MELEE); + StyleMap.put(ItemID.INFERNAL_PICKAXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.INFERNAL_PICKAXE_UNCHARGED, WeaponStyle.MELEE); + StyleMap.put(ItemID.INQUISITORS_MACE, WeaponStyle.MELEE); + StyleMap.put(ItemID.IRON_2H_SWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.IRON_AXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.IRON_BATTLEAXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.IRON_CLAWS, WeaponStyle.MELEE); + StyleMap.put(ItemID.IRON_DAGGER, WeaponStyle.MELEE); + StyleMap.put(ItemID.IRON_DAGGERP, WeaponStyle.MELEE); + StyleMap.put(ItemID.IRON_DAGGERP_5668, WeaponStyle.MELEE); + StyleMap.put(ItemID.IRON_DAGGERP_5686, WeaponStyle.MELEE); + StyleMap.put(ItemID.IRON_HALBERD, WeaponStyle.MELEE); + StyleMap.put(ItemID.IRON_HASTA, WeaponStyle.MELEE); + StyleMap.put(ItemID.IRON_LONGSWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.IRON_MACE, WeaponStyle.MELEE); + StyleMap.put(ItemID.IRON_PICKAXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.IRON_SCIMITAR, WeaponStyle.MELEE); + StyleMap.put(ItemID.IRON_SPEAR, WeaponStyle.MELEE); + StyleMap.put(ItemID.IRON_SPEARP, WeaponStyle.MELEE); + StyleMap.put(ItemID.IRON_SPEARP_5706, WeaponStyle.MELEE); + StyleMap.put(ItemID.IRON_SPEARP_5720, WeaponStyle.MELEE); + StyleMap.put(ItemID.IRON_SWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.IRON_WARHAMMER, WeaponStyle.MELEE); + StyleMap.put(ItemID.JADE_MACHETE, WeaponStyle.MELEE); + StyleMap.put(ItemID.KATANA, WeaponStyle.MELEE); + StyleMap.put(ItemID.KITCHEN_KNIFE, WeaponStyle.MELEE); + StyleMap.put(ItemID.KERIS, WeaponStyle.MELEE); + StyleMap.put(ItemID.LARGE_SPADE, WeaponStyle.MELEE); + StyleMap.put(ItemID.LEAFBLADED_BATTLEAXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.LEAFBLADED_SPEAR, WeaponStyle.MELEE); + StyleMap.put(ItemID.LEAFBLADED_SPEAR_4159, WeaponStyle.MELEE); + StyleMap.put(ItemID.LEAFBLADED_SWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.LOVAKENGJ_BANNER, WeaponStyle.MELEE); + StyleMap.put(ItemID.LUCKY_CUTLASS, WeaponStyle.MELEE); + StyleMap.put(ItemID.LYRE, WeaponStyle.MELEE); + StyleMap.put(ItemID.MACE, WeaponStyle.MELEE); + StyleMap.put(ItemID.MACHETE, WeaponStyle.MELEE); + StyleMap.put(ItemID.MAGIC_BUTTERFLY_NET, WeaponStyle.MELEE); + StyleMap.put(ItemID.MAGIC_SECATEURS, WeaponStyle.MELEE); + StyleMap.put(ItemID.MAGIC_SECATEURS_NZ, WeaponStyle.MELEE); + StyleMap.put(ItemID.MAPLE_BLACKJACK, WeaponStyle.MELEE); + StyleMap.put(ItemID.MAPLE_BLACKJACKD, WeaponStyle.MELEE); + StyleMap.put(ItemID.MAPLE_BLACKJACKO, WeaponStyle.MELEE); + StyleMap.put(ItemID.MEAT_TENDERISER, WeaponStyle.MELEE); + StyleMap.put(ItemID.MERFOLK_TRIDENT, WeaponStyle.MELEE); + StyleMap.put(ItemID.MITHRIL_2H_SWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.MITHRIL_AXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.MITHRIL_BATTLEAXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.MITHRIL_CLAWS, WeaponStyle.MELEE); + StyleMap.put(ItemID.MITHRIL_DAGGER, WeaponStyle.MELEE); + StyleMap.put(ItemID.MITHRIL_DAGGERP, WeaponStyle.MELEE); + StyleMap.put(ItemID.MITHRIL_DAGGERP_5674, WeaponStyle.MELEE); + StyleMap.put(ItemID.MITHRIL_DAGGERP_5692, WeaponStyle.MELEE); + StyleMap.put(ItemID.MITHRIL_HALBERD, WeaponStyle.MELEE); + StyleMap.put(ItemID.MITHRIL_HASTA, WeaponStyle.MELEE); + StyleMap.put(ItemID.MITHRIL_LONGSWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.MITHRIL_MACE, WeaponStyle.MELEE); + StyleMap.put(ItemID.MITHRIL_PICKAXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.MITHRIL_SCIMITAR, WeaponStyle.MELEE); + StyleMap.put(ItemID.MITHRIL_SPEAR, WeaponStyle.MELEE); + StyleMap.put(ItemID.MITHRIL_SPEARP, WeaponStyle.MELEE); + StyleMap.put(ItemID.MITHRIL_SPEARP_5710, WeaponStyle.MELEE); + StyleMap.put(ItemID.MITHRIL_SPEARP_5724, WeaponStyle.MELEE); + StyleMap.put(ItemID.MITHRIL_SWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.MITHRIL_WARHAMMER, WeaponStyle.MELEE); + StyleMap.put(ItemID.MIXED_FLOWERS, WeaponStyle.MELEE); + StyleMap.put(ItemID.MOUSE_TOY, WeaponStyle.MELEE); + StyleMap.put(ItemID.NEW_CRYSTAL_HALBERD_FULL, WeaponStyle.MELEE); + StyleMap.put(ItemID.NEW_CRYSTAL_HALBERD_FULL_I, WeaponStyle.MELEE); + StyleMap.put(ItemID.NEW_CRYSTAL_HALBERD_FULL_16893, WeaponStyle.MELEE); + StyleMap.put(ItemID.NEW_CRYSTAL_HALBERD_FULL_I_16892, WeaponStyle.MELEE); + StyleMap.put(ItemID.NOOSE_WAND, WeaponStyle.MELEE); + StyleMap.put(ItemID.NUNCHAKU, WeaponStyle.MELEE); + StyleMap.put(ItemID.OAK_BLACKJACK, WeaponStyle.MELEE); + StyleMap.put(ItemID.OAK_BLACKJACKD, WeaponStyle.MELEE); + StyleMap.put(ItemID.OAK_BLACKJACKO, WeaponStyle.MELEE); + StyleMap.put(ItemID.OILY_FISHING_ROD, WeaponStyle.MELEE); + StyleMap.put(ItemID.OILY_PEARL_FISHING_ROD, WeaponStyle.MELEE); + StyleMap.put(ItemID.OPAL_MACHETE, WeaponStyle.MELEE); + StyleMap.put(ItemID.ORANGE_FLOWERS, WeaponStyle.MELEE); + StyleMap.put(ItemID.ORANGE_SALAMANDER, WeaponStyle.MELEE); + StyleMap.put(ItemID.PEACEFUL_HANDEGG, WeaponStyle.MELEE); + StyleMap.put(ItemID.PET_ROCK, WeaponStyle.MELEE); + StyleMap.put(ItemID.PISCARILIUS_BANNER, WeaponStyle.MELEE); + StyleMap.put(ItemID.PROP_SWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.PURPLE_FLOWERS, WeaponStyle.MELEE); + StyleMap.put(ItemID.RAPIER, WeaponStyle.MELEE); + StyleMap.put(ItemID.RAT_POLE, WeaponStyle.MELEE); + StyleMap.put(ItemID.RAT_POLE_6774, WeaponStyle.MELEE); + StyleMap.put(ItemID.RAT_POLE_6775, WeaponStyle.MELEE); + StyleMap.put(ItemID.RAT_POLE_6776, WeaponStyle.MELEE); + StyleMap.put(ItemID.RAT_POLE_6777, WeaponStyle.MELEE); + StyleMap.put(ItemID.RAT_POLE_6778, WeaponStyle.MELEE); + StyleMap.put(ItemID.RAT_POLE_6779, WeaponStyle.MELEE); + StyleMap.put(ItemID.RED_FLOWERS, WeaponStyle.MELEE); + StyleMap.put(ItemID.RED_FLOWERS_8938, WeaponStyle.MELEE); + StyleMap.put(ItemID.RED_SALAMANDER, WeaponStyle.MELEE); + StyleMap.put(ItemID.RED_TOPAZ_MACHETE, WeaponStyle.MELEE); + StyleMap.put(ItemID.ROCK_HAMMER, WeaponStyle.MELEE); + StyleMap.put(ItemID.ROYAL_SCEPTRE, WeaponStyle.MELEE); + StyleMap.put(ItemID.RUBBER_CHICKEN, WeaponStyle.MELEE); + StyleMap.put(ItemID.RUBBER_CHICKEN_22666, WeaponStyle.MELEE); + StyleMap.put(ItemID.RUNE_2H_SWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.RUNE_AXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.RUNE_BATTLEAXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.RUNE_BATTLEAXE_20552, WeaponStyle.MELEE); + StyleMap.put(ItemID.RUNE_CANE, WeaponStyle.MELEE); + StyleMap.put(ItemID.RUNE_CLAWS, WeaponStyle.MELEE); + StyleMap.put(ItemID.RUNE_DAGGER, WeaponStyle.MELEE); + StyleMap.put(ItemID.RUNE_DAGGERP, WeaponStyle.MELEE); + StyleMap.put(ItemID.RUNE_DAGGERP_5678, WeaponStyle.MELEE); + StyleMap.put(ItemID.RUNE_DAGGERP_5696, WeaponStyle.MELEE); + StyleMap.put(ItemID.RUNE_HALBERD, WeaponStyle.MELEE); + StyleMap.put(ItemID.RUNE_HASTA, WeaponStyle.MELEE); + StyleMap.put(ItemID.RUNE_LONGSWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.RUNE_MACE, WeaponStyle.MELEE); + StyleMap.put(ItemID.RUNE_PICKAXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.RUNE_SCIMITAR, WeaponStyle.MELEE); + StyleMap.put(ItemID.RUNE_SCIMITAR_20402, WeaponStyle.MELEE); + StyleMap.put(ItemID.RUNE_SCIMITAR_23330, WeaponStyle.MELEE); + StyleMap.put(ItemID.RUNE_SCIMITAR_23332, WeaponStyle.MELEE); + StyleMap.put(ItemID.RUNE_SCIMITAR_23334, WeaponStyle.MELEE); + StyleMap.put(ItemID.RUNE_SPEAR, WeaponStyle.MELEE); + StyleMap.put(ItemID.RUNE_SPEARP, WeaponStyle.MELEE); + StyleMap.put(ItemID.RUNE_SPEARP_5714, WeaponStyle.MELEE); + StyleMap.put(ItemID.RUNE_SPEARP_5728, WeaponStyle.MELEE); + StyleMap.put(ItemID.RUNE_SWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.RUNE_WARHAMMER, WeaponStyle.MELEE); + StyleMap.put(ItemID.SARADOMINS_BLESSED_SWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.SARADOMIN_GODSWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.SARADOMIN_GODSWORD_OR, WeaponStyle.MELEE); + StyleMap.put(ItemID.SARADOMIN_MJOLNIR, WeaponStyle.MELEE); + StyleMap.put(ItemID.SARADOMIN_SWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.SARAS_BLESSED_SWORD_FULL, WeaponStyle.MELEE); + StyleMap.put(ItemID.SCYTHE, WeaponStyle.MELEE); + StyleMap.put(ItemID.SCYTHE_OF_VITUR, WeaponStyle.MELEE); + StyleMap.put(ItemID.SCYTHE_OF_VITUR_22664, WeaponStyle.MELEE); + StyleMap.put(ItemID.SCYTHE_OF_VITUR_UNCHARGED, WeaponStyle.MELEE); + StyleMap.put(ItemID.SEVERED_LEG_24792, WeaponStyle.MELEE); + StyleMap.put(ItemID.SHADOW_SWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.SHAYZIEN_BANNER, WeaponStyle.MELEE); + StyleMap.put(ItemID.SILVERLIGHT, WeaponStyle.MELEE); + StyleMap.put(ItemID.SILVERLIGHT_6745, WeaponStyle.MELEE); + StyleMap.put(ItemID.SILVERLIGHT_8279, WeaponStyle.MELEE); + StyleMap.put(ItemID.SILVER_SICKLE, WeaponStyle.MELEE); + StyleMap.put(ItemID.SILVER_SICKLE_B, WeaponStyle.MELEE); + StyleMap.put(ItemID.SNOWBALL, WeaponStyle.MELEE); + StyleMap.put(ItemID.SPEAR, WeaponStyle.MELEE); + StyleMap.put(ItemID.STALE_BAGUETTE, WeaponStyle.MELEE); + StyleMap.put(ItemID.STATIUSS_WARHAMMER, WeaponStyle.MELEE); + StyleMap.put(ItemID.STATIUSS_WARHAMMER_23620, WeaponStyle.MELEE); + StyleMap.put(ItemID.STEEL_2H_SWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.STEEL_AXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.STEEL_BATTLEAXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.STEEL_CLAWS, WeaponStyle.MELEE); + StyleMap.put(ItemID.STEEL_DAGGER, WeaponStyle.MELEE); + StyleMap.put(ItemID.STEEL_DAGGERP, WeaponStyle.MELEE); + StyleMap.put(ItemID.STEEL_DAGGERP_5672, WeaponStyle.MELEE); + StyleMap.put(ItemID.STEEL_DAGGERP_5690, WeaponStyle.MELEE); + StyleMap.put(ItemID.STEEL_HALBERD, WeaponStyle.MELEE); + StyleMap.put(ItemID.STEEL_HASTA, WeaponStyle.MELEE); + StyleMap.put(ItemID.STEEL_LONGSWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.STEEL_PICKAXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.STEEL_SCIMITAR, WeaponStyle.MELEE); + StyleMap.put(ItemID.STEEL_SPEAR, WeaponStyle.MELEE); + StyleMap.put(ItemID.STEEL_SPEARP, WeaponStyle.MELEE); + StyleMap.put(ItemID.STEEL_SPEARP_5708, WeaponStyle.MELEE); + StyleMap.put(ItemID.STEEL_SPEARP_5722, WeaponStyle.MELEE); + StyleMap.put(ItemID.STEEL_SWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.STEEL_WARHAMMER, WeaponStyle.MELEE); + StyleMap.put(ItemID.STONE_BOWL, WeaponStyle.MELEE); + StyleMap.put(ItemID.SWAMP_LIZARD, WeaponStyle.MELEE); + StyleMap.put(ItemID.SWIFT_BLADE, WeaponStyle.MELEE); + StyleMap.put(ItemID.TOKTZXILAK, WeaponStyle.MELEE); + StyleMap.put(ItemID.TOKTZXILAK_20554, WeaponStyle.MELEE); + StyleMap.put(ItemID.TOKTZXILEK, WeaponStyle.MELEE); + StyleMap.put(ItemID.TORAGS_HAMMERS, WeaponStyle.MELEE); + StyleMap.put(ItemID.TORAGS_HAMMERS_0, WeaponStyle.MELEE); + StyleMap.put(ItemID.TORAGS_HAMMERS_100, WeaponStyle.MELEE); + StyleMap.put(ItemID.TORAGS_HAMMERS_25, WeaponStyle.MELEE); + StyleMap.put(ItemID.TORAGS_HAMMERS_50, WeaponStyle.MELEE); + StyleMap.put(ItemID.TORAGS_HAMMERS_75, WeaponStyle.MELEE); + StyleMap.put(ItemID.TRAINING_SWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.TRAILBLAZER_AXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.TRAILBLAZER_BANNER, WeaponStyle.MELEE); + StyleMap.put(ItemID.TRAILBLAZER_CANE, WeaponStyle.MELEE); + StyleMap.put(ItemID.TRAILBLAZER_HARPOON, WeaponStyle.MELEE); + StyleMap.put(ItemID.TRAILBLAZER_PICKAXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.TROLLWEISS, WeaponStyle.MELEE); + StyleMap.put(ItemID.TWISTED_BANNER, WeaponStyle.MELEE); + StyleMap.put(ItemID.TZHAARKETEM, WeaponStyle.MELEE); + StyleMap.put(ItemID.TZHAARKETOM, WeaponStyle.MELEE); + StyleMap.put(ItemID.TZHAARKETOM_T, WeaponStyle.MELEE); + StyleMap.put(ItemID.VERACS_FLAIL, WeaponStyle.MELEE); + StyleMap.put(ItemID.VERACS_FLAIL_0, WeaponStyle.MELEE); + StyleMap.put(ItemID.VERACS_FLAIL_100, WeaponStyle.MELEE); + StyleMap.put(ItemID.VERACS_FLAIL_25, WeaponStyle.MELEE); + StyleMap.put(ItemID.VERACS_FLAIL_50, WeaponStyle.MELEE); + StyleMap.put(ItemID.VERACS_FLAIL_75, WeaponStyle.MELEE); + StyleMap.put(ItemID.VESTAS_BLIGHTED_LONGSWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.VESTAS_LONGSWORD_INACTIVE, WeaponStyle.MELEE); + StyleMap.put(ItemID.VESTAS_LONGSWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.VESTAS_LONGSWORD_23615, WeaponStyle.MELEE); + StyleMap.put(ItemID.VESTAS_SPEAR, WeaponStyle.MELEE); + StyleMap.put(ItemID.VIGGORAS_CHAINMACE, WeaponStyle.MELEE); + StyleMap.put(ItemID.VIGGORAS_CHAINMACE_U, WeaponStyle.MELEE); + StyleMap.put(ItemID.VOLCANIC_ABYSSAL_WHIP, WeaponStyle.MELEE); + StyleMap.put(ItemID.WESTERN_BANNER_1, WeaponStyle.MELEE); + StyleMap.put(ItemID.WESTERN_BANNER_2, WeaponStyle.MELEE); + StyleMap.put(ItemID.WESTERN_BANNER_3, WeaponStyle.MELEE); + StyleMap.put(ItemID.WESTERN_BANNER_4, WeaponStyle.MELEE); + StyleMap.put(ItemID.WHITE_2H_SWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.WHITE_BATTLEAXE, WeaponStyle.MELEE); + StyleMap.put(ItemID.WHITE_CLAWS, WeaponStyle.MELEE); + StyleMap.put(ItemID.WHITE_DAGGER, WeaponStyle.MELEE); + StyleMap.put(ItemID.WHITE_DAGGERP, WeaponStyle.MELEE); + StyleMap.put(ItemID.WHITE_DAGGERP_6595, WeaponStyle.MELEE); + StyleMap.put(ItemID.WHITE_DAGGERP_6597, WeaponStyle.MELEE); + StyleMap.put(ItemID.WHITE_FLOWERS, WeaponStyle.MELEE); + StyleMap.put(ItemID.WHITE_HALBERD, WeaponStyle.MELEE); + StyleMap.put(ItemID.WHITE_LONGSWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.WHITE_MACE, WeaponStyle.MELEE); + StyleMap.put(ItemID.WHITE_SCIMITAR, WeaponStyle.MELEE); + StyleMap.put(ItemID.WHITE_SWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.WHITE_WARHAMMER, WeaponStyle.MELEE); + StyleMap.put(ItemID.WILDERNESS_SWORD_1, WeaponStyle.MELEE); + StyleMap.put(ItemID.WILDERNESS_SWORD_2, WeaponStyle.MELEE); + StyleMap.put(ItemID.WILDERNESS_SWORD_3, WeaponStyle.MELEE); + StyleMap.put(ItemID.WILDERNESS_SWORD_4, WeaponStyle.MELEE); + StyleMap.put(ItemID.WILLOW_BLACKJACK, WeaponStyle.MELEE); + StyleMap.put(ItemID.WILLOW_BLACKJACKD, WeaponStyle.MELEE); + StyleMap.put(ItemID.WILLOW_BLACKJACKO, WeaponStyle.MELEE); + StyleMap.put(ItemID.WOLFBANE, WeaponStyle.MELEE); + StyleMap.put(ItemID.WOODEN_SPOON, WeaponStyle.MELEE); + StyleMap.put(ItemID.WOODEN_SWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.YELLOW_FLOWERS, WeaponStyle.MELEE); + StyleMap.put(ItemID.ZAMORAKIAN_HASTA, WeaponStyle.MELEE); + StyleMap.put(ItemID.ZAMORAKIAN_SPEAR, WeaponStyle.MELEE); + StyleMap.put(ItemID.ZAMORAK_GODSWORD, WeaponStyle.MELEE); + StyleMap.put(ItemID.ZAMORAK_GODSWORD_OR, WeaponStyle.MELEE); + StyleMap.put(ItemID.ZOMBIE_HEAD, WeaponStyle.MELEE); + + //Ranged + StyleMap.put(ItemID._3RD_AGE_BOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.ADAMANT_CROSSBOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.ADAMANT_DART, WeaponStyle.RANGE); + StyleMap.put(ItemID.ADAMANT_DARTP, WeaponStyle.RANGE); + StyleMap.put(ItemID.ADAMANT_DARTP_5633, WeaponStyle.RANGE); + StyleMap.put(ItemID.ADAMANT_DARTP_5640, WeaponStyle.RANGE); + StyleMap.put(ItemID.ADAMANT_KNIFE, WeaponStyle.RANGE); + StyleMap.put(ItemID.ADAMANT_KNIFEP, WeaponStyle.RANGE); + StyleMap.put(ItemID.ADAMANT_KNIFEP_5659, WeaponStyle.RANGE); + StyleMap.put(ItemID.ADAMANT_KNIFEP_5666, WeaponStyle.RANGE); + StyleMap.put(ItemID.ADAMANT_THROWNAXE, WeaponStyle.RANGE); + StyleMap.put(ItemID.ARMADYL_CROSSBOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.ARMADYL_CROSSBOW_23611, WeaponStyle.RANGE); + StyleMap.put(ItemID.BLACK_CHINCHOMPA, WeaponStyle.RANGE); + StyleMap.put(ItemID.BLACK_DART, WeaponStyle.RANGE); + StyleMap.put(ItemID.BLACK_DARTP, WeaponStyle.RANGE); + StyleMap.put(ItemID.BLACK_DARTP_5631, WeaponStyle.RANGE); + StyleMap.put(ItemID.BLACK_DARTP_5638, WeaponStyle.RANGE); + StyleMap.put(ItemID.BLACK_KNIFE, WeaponStyle.RANGE); + StyleMap.put(ItemID.BLACK_KNIFEP, WeaponStyle.RANGE); + StyleMap.put(ItemID.BLACK_KNIFEP_5658, WeaponStyle.RANGE); + StyleMap.put(ItemID.BLACK_KNIFEP_5665, WeaponStyle.RANGE); + StyleMap.put(ItemID.BLURITE_CROSSBOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.BRONZE_CROSSBOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.BRONZE_DART, WeaponStyle.RANGE); + StyleMap.put(ItemID.BRONZE_DARTP, WeaponStyle.RANGE); + StyleMap.put(ItemID.BRONZE_DARTP_5628, WeaponStyle.RANGE); + StyleMap.put(ItemID.BRONZE_DARTP_5635, WeaponStyle.RANGE); + StyleMap.put(ItemID.BRONZE_KNIFE, WeaponStyle.RANGE); + StyleMap.put(ItemID.BRONZE_KNIFEP, WeaponStyle.RANGE); + StyleMap.put(ItemID.BRONZE_KNIFEP_5654, WeaponStyle.RANGE); + StyleMap.put(ItemID.BRONZE_KNIFEP_5661, WeaponStyle.RANGE); + StyleMap.put(ItemID.BRONZE_THROWNAXE, WeaponStyle.RANGE); + StyleMap.put(ItemID.CHINCHOMPA, WeaponStyle.RANGE); + StyleMap.put(ItemID.CHINCHOMPA_10033, WeaponStyle.RANGE); + StyleMap.put(ItemID.COMP_OGRE_BOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.CORRUPTED_BOW_ATTUNED, WeaponStyle.RANGE); + StyleMap.put(ItemID.CORRUPTED_BOW_BASIC, WeaponStyle.RANGE); + StyleMap.put(ItemID.CORRUPTED_BOW_PERFECTED, WeaponStyle.RANGE); + StyleMap.put(ItemID.CRAWS_BOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.CRAWS_BOW_U, WeaponStyle.RANGE); + StyleMap.put(ItemID.CROSSBOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.CRYSTAL_BOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.CRYSTAL_BOW_110, WeaponStyle.RANGE); + StyleMap.put(ItemID.CRYSTAL_BOW_110_I, WeaponStyle.RANGE); + StyleMap.put(ItemID.CRYSTAL_BOW_210, WeaponStyle.RANGE); + StyleMap.put(ItemID.CRYSTAL_BOW_210_I, WeaponStyle.RANGE); + StyleMap.put(ItemID.CRYSTAL_BOW_310, WeaponStyle.RANGE); + StyleMap.put(ItemID.CRYSTAL_BOW_310_I, WeaponStyle.RANGE); + StyleMap.put(ItemID.CRYSTAL_BOW_410, WeaponStyle.RANGE); + StyleMap.put(ItemID.CRYSTAL_BOW_410_I, WeaponStyle.RANGE); + StyleMap.put(ItemID.CRYSTAL_BOW_510, WeaponStyle.RANGE); + StyleMap.put(ItemID.CRYSTAL_BOW_510_I, WeaponStyle.RANGE); + StyleMap.put(ItemID.CRYSTAL_BOW_610, WeaponStyle.RANGE); + StyleMap.put(ItemID.CRYSTAL_BOW_610_I, WeaponStyle.RANGE); + StyleMap.put(ItemID.CRYSTAL_BOW_710, WeaponStyle.RANGE); + StyleMap.put(ItemID.CRYSTAL_BOW_710_I, WeaponStyle.RANGE); + StyleMap.put(ItemID.CRYSTAL_BOW_810, WeaponStyle.RANGE); + StyleMap.put(ItemID.CRYSTAL_BOW_810_I, WeaponStyle.RANGE); + StyleMap.put(ItemID.CRYSTAL_BOW_910, WeaponStyle.RANGE); + StyleMap.put(ItemID.CRYSTAL_BOW_910_I, WeaponStyle.RANGE); + StyleMap.put(ItemID.CRYSTAL_BOW_24123, WeaponStyle.RANGE); + StyleMap.put(ItemID.CRYSTAL_BOW_ATTUNED, WeaponStyle.RANGE); + StyleMap.put(ItemID.CRYSTAL_BOW_BASIC, WeaponStyle.RANGE); + StyleMap.put(ItemID.CRYSTAL_BOW_FULL, WeaponStyle.RANGE); + StyleMap.put(ItemID.CRYSTAL_BOW_FULL_I, WeaponStyle.RANGE); + StyleMap.put(ItemID.CRYSTAL_BOW_INACTIVE, WeaponStyle.RANGE); + StyleMap.put(ItemID.CRYSTAL_BOW_PERFECTED, WeaponStyle.RANGE); + StyleMap.put(ItemID.CURSED_GOBLIN_BOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.DARK_BOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.DARK_BOW_12765, WeaponStyle.RANGE); + StyleMap.put(ItemID.DARK_BOW_12766, WeaponStyle.RANGE); + StyleMap.put(ItemID.DARK_BOW_12767, WeaponStyle.RANGE); + StyleMap.put(ItemID.DARK_BOW_12768, WeaponStyle.RANGE); + StyleMap.put(ItemID.DARK_BOW_20408, WeaponStyle.RANGE); + StyleMap.put(ItemID.DART, WeaponStyle.RANGE); + StyleMap.put(ItemID.DORGESHUUN_CROSSBOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.DRAGON_CROSSBOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.DRAGON_DART, WeaponStyle.RANGE); + StyleMap.put(ItemID.DRAGON_DARTP, WeaponStyle.RANGE); + StyleMap.put(ItemID.DRAGON_DARTP_11233, WeaponStyle.RANGE); + StyleMap.put(ItemID.DRAGON_DARTP_11234, WeaponStyle.RANGE); + StyleMap.put(ItemID.DRAGON_HUNTER_CROSSBOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.DRAGON_KNIFE, WeaponStyle.RANGE); + StyleMap.put(ItemID.DRAGON_KNIFEP, WeaponStyle.RANGE); + StyleMap.put(ItemID.DRAGON_KNIFEP_22808, WeaponStyle.RANGE); + StyleMap.put(ItemID.DRAGON_KNIFEP_22810, WeaponStyle.RANGE); + StyleMap.put(ItemID.DRAGON_THROWNAXE, WeaponStyle.RANGE); + StyleMap.put(ItemID.HEAVY_BALLISTA, WeaponStyle.RANGE); + StyleMap.put(ItemID.HEAVY_BALLISTA_23630, WeaponStyle.RANGE); + StyleMap.put(ItemID.HOLY_WATER, WeaponStyle.RANGE); + StyleMap.put(ItemID.HUNTERS_CROSSBOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.IRON_CROSSBOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.IRON_DART, WeaponStyle.RANGE); + StyleMap.put(ItemID.IRON_DARTP, WeaponStyle.RANGE); + StyleMap.put(ItemID.IRON_DARTP_5629, WeaponStyle.RANGE); + StyleMap.put(ItemID.IRON_DARTP_5636, WeaponStyle.RANGE); + StyleMap.put(ItemID.IRON_KNIFE, WeaponStyle.RANGE); + StyleMap.put(ItemID.IRON_KNIFEP, WeaponStyle.RANGE); + StyleMap.put(ItemID.IRON_KNIFEP_5655, WeaponStyle.RANGE); + StyleMap.put(ItemID.IRON_KNIFEP_5662, WeaponStyle.RANGE); + StyleMap.put(ItemID.IRON_THROWNAXE, WeaponStyle.RANGE); + StyleMap.put(ItemID.KARILS_CROSSBOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.KARILS_CROSSBOW_0, WeaponStyle.RANGE); + StyleMap.put(ItemID.KARILS_CROSSBOW_100, WeaponStyle.RANGE); + StyleMap.put(ItemID.KARILS_CROSSBOW_25, WeaponStyle.RANGE); + StyleMap.put(ItemID.KARILS_CROSSBOW_50, WeaponStyle.RANGE); + StyleMap.put(ItemID.KARILS_CROSSBOW_75, WeaponStyle.RANGE); + StyleMap.put(ItemID.LIGHT_BALLISTA, WeaponStyle.RANGE); + StyleMap.put(ItemID.LONGBOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.MAGIC_COMP_BOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.MAGIC_LONGBOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.MAGIC_SHORTBOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.MAGIC_SHORTBOW_20558, WeaponStyle.RANGE); + StyleMap.put(ItemID.MAGIC_SHORTBOW_I, WeaponStyle.RANGE); + StyleMap.put(ItemID.MAPLE_LONGBOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.MAPLE_SHORTBOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.MITHRIL_DART, WeaponStyle.RANGE); + StyleMap.put(ItemID.MITHRIL_DARTP, WeaponStyle.RANGE); + StyleMap.put(ItemID.MITHRIL_DARTP_5632, WeaponStyle.RANGE); + StyleMap.put(ItemID.MITHRIL_DARTP_5639, WeaponStyle.RANGE); + StyleMap.put(ItemID.MITHRIL_KNIFE, WeaponStyle.RANGE); + StyleMap.put(ItemID.MITHRIL_KNIFEP, WeaponStyle.RANGE); + StyleMap.put(ItemID.MITHRIL_KNIFEP_5657, WeaponStyle.RANGE); + StyleMap.put(ItemID.MITHRIL_KNIFEP_5664, WeaponStyle.RANGE); + StyleMap.put(ItemID.MITHRIL_THROWNAXE, WeaponStyle.RANGE); + StyleMap.put(ItemID.MITHRIL_CROSSBOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.MONKEY_TALISMAN, WeaponStyle.RANGE); + StyleMap.put(ItemID.MORRIGANS_JAVELIN, WeaponStyle.RANGE); + StyleMap.put(ItemID.MORRIGANS_JAVELIN_23619, WeaponStyle.RANGE); + StyleMap.put(ItemID.MORRIGANS_THROWING_AXE, WeaponStyle.RANGE); + StyleMap.put(ItemID.MUD_PIE, WeaponStyle.RANGE); + StyleMap.put(ItemID.NEW_CRYSTAL_BOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.NEW_CRYSTAL_BOW_4213, WeaponStyle.RANGE); + StyleMap.put(ItemID.NEW_CRYSTAL_BOW_16888, WeaponStyle.RANGE); + StyleMap.put(ItemID.NEW_CRYSTAL_BOW_I, WeaponStyle.RANGE); + StyleMap.put(ItemID.NEW_CRYSTAL_BOW_I_16889, WeaponStyle.RANGE); + StyleMap.put(ItemID.OAK_LONGBOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.OAK_SHORTBOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.OGRE_BOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.PHOENIX_CROSSBOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.RED_CHINCHOMPA, WeaponStyle.RANGE); + StyleMap.put(ItemID.RED_CHINCHOMPA_10034, WeaponStyle.RANGE); + StyleMap.put(ItemID.RUNE_CROSSBOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.RUNE_CROSSBOW_23601, WeaponStyle.RANGE); + StyleMap.put(ItemID.RUNE_DART, WeaponStyle.RANGE); + StyleMap.put(ItemID.RUNE_DARTP, WeaponStyle.RANGE); + StyleMap.put(ItemID.RUNE_DARTP_5634, WeaponStyle.RANGE); + StyleMap.put(ItemID.RUNE_DARTP_5641, WeaponStyle.RANGE); + StyleMap.put(ItemID.RUNE_KNIFE, WeaponStyle.RANGE); + StyleMap.put(ItemID.RUNE_KNIFEP, WeaponStyle.RANGE); + StyleMap.put(ItemID.RUNE_KNIFEP_5660, WeaponStyle.RANGE); + StyleMap.put(ItemID.RUNE_KNIFEP_5667, WeaponStyle.RANGE); + StyleMap.put(ItemID.RUNE_THROWNAXE, WeaponStyle.RANGE); + StyleMap.put(ItemID.SEERCULL, WeaponStyle.RANGE); + StyleMap.put(ItemID.SHORTBOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.SIGNED_OAK_BOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.STARTER_BOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.STEEL_CROSSBOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.STEEL_DART, WeaponStyle.RANGE); + StyleMap.put(ItemID.STEEL_DARTP, WeaponStyle.RANGE); + StyleMap.put(ItemID.STEEL_DARTP_5630, WeaponStyle.RANGE); + StyleMap.put(ItemID.STEEL_DARTP_5637, WeaponStyle.RANGE); + StyleMap.put(ItemID.STEEL_KNIFE, WeaponStyle.RANGE); + StyleMap.put(ItemID.STEEL_KNIFEP, WeaponStyle.RANGE); + StyleMap.put(ItemID.STEEL_KNIFEP_5656, WeaponStyle.RANGE); + StyleMap.put(ItemID.STEEL_KNIFEP_5663, WeaponStyle.RANGE); + StyleMap.put(ItemID.STEEL_THROWNAXE, WeaponStyle.RANGE); + StyleMap.put(ItemID.TOKTZXILUL, WeaponStyle.RANGE); + StyleMap.put(ItemID.TOXIC_BLOWPIPE, WeaponStyle.RANGE); + StyleMap.put(ItemID.TOXIC_BLOWPIPE_EMPTY, WeaponStyle.RANGE); + StyleMap.put(ItemID.TRAINING_BOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.TWISTED_BOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.WILLOW_COMP_BOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.WILLOW_LONGBOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.WILLOW_SHORTBOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.YEW_COMP_BOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.YEW_LONGBOW, WeaponStyle.RANGE); + StyleMap.put(ItemID.YEW_SHORTBOW, WeaponStyle.RANGE); + + //Magic + StyleMap.put(ItemID._3RD_AGE_WAND, WeaponStyle.MAGIC); + StyleMap.put(ItemID.AHRIMS_STAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.AHRIMS_STAFF_0, WeaponStyle.MAGIC); + StyleMap.put(ItemID.AHRIMS_STAFF_100, WeaponStyle.MAGIC); + StyleMap.put(ItemID.AHRIMS_STAFF_25, WeaponStyle.MAGIC); + StyleMap.put(ItemID.AHRIMS_STAFF_50, WeaponStyle.MAGIC); + StyleMap.put(ItemID.AHRIMS_STAFF_75, WeaponStyle.MAGIC); + StyleMap.put(ItemID.AHRIMS_STAFF_23653, WeaponStyle.MAGIC); + StyleMap.put(ItemID.AIR_BATTLESTAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.ANCIENT_CROZIER, WeaponStyle.MAGIC); + StyleMap.put(ItemID.ANCIENT_STAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.APPRENTICE_WAND, WeaponStyle.MAGIC); + StyleMap.put(ItemID.ARMADYL_CROZIER, WeaponStyle.MAGIC); + StyleMap.put(ItemID.BANDOS_CROZIER, WeaponStyle.MAGIC); + StyleMap.put(ItemID.BATTLESTAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.BEGINNER_WAND, WeaponStyle.MAGIC); + StyleMap.put(ItemID.BLISTERWOOD_FLAIL, WeaponStyle.MAGIC); + StyleMap.put(ItemID.BROKEN_STAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.BRYOPHYTAS_STAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.BRYOPHYTAS_STAFF_UNCHARGED, WeaponStyle.MAGIC); + StyleMap.put(ItemID.CORRUPTED_STAFF_ATTUNED, WeaponStyle.MAGIC); + StyleMap.put(ItemID.CORRUPTED_STAFF_BASIC, WeaponStyle.MAGIC); + StyleMap.put(ItemID.CORRUPTED_STAFF_PERFECTED, WeaponStyle.MAGIC); + StyleMap.put(ItemID.CRYSTAL_STAFF_ATTUNED, WeaponStyle.MAGIC); + StyleMap.put(ItemID.CRYSTAL_STAFF_BASIC, WeaponStyle.MAGIC); + StyleMap.put(ItemID.CRYSTAL_STAFF_PERFECTED, WeaponStyle.MAGIC); + StyleMap.put(ItemID.CURSED_GOBLIN_STAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.DAWNBRINGER, WeaponStyle.MAGIC); + StyleMap.put(ItemID.DRAMEN_STAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.DUST_BATTLESTAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.EARTH_BATTLESTAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.ELDRITCH_NIGHTMARE_STAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.FIRE_BATTLESTAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.GUTHIX_CROZIER, WeaponStyle.MAGIC); + StyleMap.put(ItemID.GUTHIX_STAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.HARMONISED_NIGHTMARE_STAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.IBANS_STAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.IBANS_STAFF_1410, WeaponStyle.MAGIC); + StyleMap.put(ItemID.IBANS_STAFF_U, WeaponStyle.MAGIC); + StyleMap.put(ItemID.IVANDIS_FLAIL, WeaponStyle.MAGIC); + StyleMap.put(ItemID.KODAI_WAND, WeaponStyle.MAGIC); + StyleMap.put(ItemID.KODAI_WAND_23626, WeaponStyle.MAGIC); + StyleMap.put(ItemID.LAVA_BATTLESTAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.LAVA_BATTLESTAFF_21198, WeaponStyle.MAGIC); + StyleMap.put(ItemID.LUNAR_STAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.MAGIC_STAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.MASTER_WAND, WeaponStyle.MAGIC); + StyleMap.put(ItemID.MASTER_WAND_20560, WeaponStyle.MAGIC); + StyleMap.put(ItemID.MIST_BATTLESTAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.MUD_BATTLESTAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.MYSTIC_AIR_STAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.MYSTIC_DUST_STAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.MYSTIC_EARTH_STAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.MYSTIC_FIRE_STAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.MYSTIC_LAVA_STAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.MYSTIC_LAVA_STAFF_21200, WeaponStyle.MAGIC); + StyleMap.put(ItemID.MYSTIC_MIST_STAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.MYSTIC_MUD_STAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.MYSTIC_SMOKE_STAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.MYSTIC_STEAM_STAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.MYSTIC_STEAM_STAFF_12796, WeaponStyle.MAGIC); + StyleMap.put(ItemID.MYSTIC_WATER_STAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.NIGHTMARE_STAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.PHARAOHS_SCEPTRE, WeaponStyle.MAGIC); + StyleMap.put(ItemID.PHARAOHS_SCEPTRE_1, WeaponStyle.MAGIC); + StyleMap.put(ItemID.PHARAOHS_SCEPTRE_2, WeaponStyle.MAGIC); + StyleMap.put(ItemID.PHARAOHS_SCEPTRE_3, WeaponStyle.MAGIC); + StyleMap.put(ItemID.PHARAOHS_SCEPTRE_4, WeaponStyle.MAGIC); + StyleMap.put(ItemID.PHARAOHS_SCEPTRE_5, WeaponStyle.MAGIC); + StyleMap.put(ItemID.PHARAOHS_SCEPTRE_6, WeaponStyle.MAGIC); + StyleMap.put(ItemID.PHARAOHS_SCEPTRE_7, WeaponStyle.MAGIC); + StyleMap.put(ItemID.PHARAOHS_SCEPTRE_8, WeaponStyle.MAGIC); + StyleMap.put(ItemID.ROD_OF_IVANDIS_1, WeaponStyle.MAGIC); + StyleMap.put(ItemID.ROD_OF_IVANDIS_10, WeaponStyle.MAGIC); + StyleMap.put(ItemID.ROD_OF_IVANDIS_2, WeaponStyle.MAGIC); + StyleMap.put(ItemID.ROD_OF_IVANDIS_3, WeaponStyle.MAGIC); + StyleMap.put(ItemID.ROD_OF_IVANDIS_4, WeaponStyle.MAGIC); + StyleMap.put(ItemID.ROD_OF_IVANDIS_5, WeaponStyle.MAGIC); + StyleMap.put(ItemID.ROD_OF_IVANDIS_6, WeaponStyle.MAGIC); + StyleMap.put(ItemID.ROD_OF_IVANDIS_7, WeaponStyle.MAGIC); + StyleMap.put(ItemID.ROD_OF_IVANDIS_8, WeaponStyle.MAGIC); + StyleMap.put(ItemID.ROD_OF_IVANDIS_9, WeaponStyle.MAGIC); + StyleMap.put(ItemID.SANGUINESTI_STAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.SANGUINESTI_STAFF_UNCHARGED, WeaponStyle.MAGIC); + StyleMap.put(ItemID.SARADOMIN_CROZIER, WeaponStyle.MAGIC); + StyleMap.put(ItemID.SARADOMIN_STAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.SKULL_SCEPTRE, WeaponStyle.MAGIC); + StyleMap.put(ItemID.SKULL_SCEPTRE_I, WeaponStyle.MAGIC); + StyleMap.put(ItemID.SLAYERS_STAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.SLAYERS_STAFF_E, WeaponStyle.MAGIC); + StyleMap.put(ItemID.SMOKE_BATTLESTAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.STAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.STAFF_OF_AIR, WeaponStyle.MAGIC); + StyleMap.put(ItemID.STAFF_OF_BALANCE, WeaponStyle.MAGIC); + StyleMap.put(ItemID.STAFF_OF_BOB_THE_CAT, WeaponStyle.MAGIC); + StyleMap.put(ItemID.STAFF_OF_EARTH, WeaponStyle.MAGIC); + StyleMap.put(ItemID.STAFF_OF_FIRE, WeaponStyle.MAGIC); + StyleMap.put(ItemID.STAFF_OF_LIGHT, WeaponStyle.MAGIC); + StyleMap.put(ItemID.STAFF_OF_THE_DEAD, WeaponStyle.MAGIC); + StyleMap.put(ItemID.STAFF_OF_THE_DEAD_23613, WeaponStyle.MAGIC); + StyleMap.put(ItemID.STAFF_OF_WATER, WeaponStyle.MAGIC); + StyleMap.put(ItemID.STARTER_STAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.STEAM_BATTLESTAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.STEAM_BATTLESTAFF_12795, WeaponStyle.MAGIC); + StyleMap.put(ItemID.TEACHER_WAND, WeaponStyle.MAGIC); + StyleMap.put(ItemID.THAMMARONS_SCEPTRE, WeaponStyle.MAGIC); + StyleMap.put(ItemID.THAMMARONS_SCEPTRE_U, WeaponStyle.MAGIC); + StyleMap.put(ItemID.TOKTZMEJTAL, WeaponStyle.MAGIC); + StyleMap.put(ItemID.TOXIC_STAFF_OF_THE_DEAD, WeaponStyle.MAGIC); + StyleMap.put(ItemID.TOXIC_STAFF_UNCHARGED, WeaponStyle.MAGIC); + StyleMap.put(ItemID.TRIDENT_OF_THE_SEAS, WeaponStyle.MAGIC); + StyleMap.put(ItemID.TRIDENT_OF_THE_SEAS_E, WeaponStyle.MAGIC); + StyleMap.put(ItemID.TRIDENT_OF_THE_SEAS_FULL, WeaponStyle.MAGIC); + StyleMap.put(ItemID.TRIDENT_OF_THE_SWAMP, WeaponStyle.MAGIC); + StyleMap.put(ItemID.TRIDENT_OF_THE_SWAMP_E, WeaponStyle.MAGIC); + StyleMap.put(ItemID.UNCHARGED_TOXIC_TRIDENT, WeaponStyle.MAGIC); + StyleMap.put(ItemID.UNCHARGED_TOXIC_TRIDENT_E, WeaponStyle.MAGIC); + StyleMap.put(ItemID.UNCHARGED_TRIDENT, WeaponStyle.MAGIC); + StyleMap.put(ItemID.UNCHARGED_TRIDENT_E, WeaponStyle.MAGIC); + StyleMap.put(ItemID.VOID_KNIGHT_MACE, WeaponStyle.MAGIC); + StyleMap.put(ItemID.VOID_KNIGHT_MACE_BROKEN, WeaponStyle.MAGIC); + StyleMap.put(ItemID.VOLATILE_NIGHTMARE_STAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.WAND, WeaponStyle.MAGIC); + StyleMap.put(ItemID.WATER_BATTLESTAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.WHITE_MAGIC_STAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.ZAMORAK_CROZIER, WeaponStyle.MAGIC); + StyleMap.put(ItemID.ZAMORAK_STAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.ZURIELS_STAFF, WeaponStyle.MAGIC); + StyleMap.put(ItemID.ZURIELS_STAFF_23617, WeaponStyle.MAGIC); + //what the fuck... + StyleMap.put(ItemID.GNOMEBALL, WeaponStyle.MAGIC); + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/com/openosrs/client/util/WeaponStyle.java b/runelite-client/src/main/java/com/openosrs/client/util/WeaponStyle.java new file mode 100644 index 0000000000..949fdda21f --- /dev/null +++ b/runelite-client/src/main/java/com/openosrs/client/util/WeaponStyle.java @@ -0,0 +1,6 @@ +package com.openosrs.client.util; + +public enum WeaponStyle +{ + MAGIC, RANGE, MELEE +} \ No newline at end of file diff --git a/runelite-client/src/main/java/com/openosrs/client/util/NonScheduledExecutorServiceExceptionLogger.java b/runelite-client/src/main/java/net/runelite/client/NonScheduledExecutorServiceExceptionLogger.java similarity index 65% rename from runelite-client/src/main/java/com/openosrs/client/util/NonScheduledExecutorServiceExceptionLogger.java rename to runelite-client/src/main/java/net/runelite/client/NonScheduledExecutorServiceExceptionLogger.java index 08436116a5..0f0986a703 100644 --- a/runelite-client/src/main/java/com/openosrs/client/util/NonScheduledExecutorServiceExceptionLogger.java +++ b/runelite-client/src/main/java/net/runelite/client/NonScheduledExecutorServiceExceptionLogger.java @@ -1,4 +1,29 @@ -package com.openosrs.client.util; +/* + * Copyright (c) 2020, SwazRGB + * 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; import java.util.Collection; import java.util.List; diff --git a/runelite-client/src/main/java/net/runelite/client/Notifier.java b/runelite-client/src/main/java/net/runelite/client/Notifier.java index 30a9ad4c3b..e36c43626b 100644 --- a/runelite-client/src/main/java/net/runelite/client/Notifier.java +++ b/runelite-client/src/main/java/net/runelite/client/Notifier.java @@ -59,6 +59,7 @@ import net.runelite.api.ChatMessageType; import net.runelite.api.Client; import net.runelite.api.Constants; import net.runelite.api.GameState; +import net.runelite.api.Player; import net.runelite.client.chat.ChatColorType; import net.runelite.client.chat.ChatMessageBuilder; import net.runelite.client.chat.ChatMessageManager; @@ -175,7 +176,7 @@ public class Notifier if (runeLiteConfig.enableTrayNotifications()) { - sendNotification(appName, message, type); + sendNotification(buildTitle(), message, type); } switch (runeLiteConfig.notificationSound()) @@ -210,6 +211,23 @@ public class Notifier log.debug(message); } + private String buildTitle() + { + Player player = client.getLocalPlayer(); + if (player == null) + { + return appName; + } + + String name = player.getName(); + if (Strings.isNullOrEmpty(name)) + { + return appName; + } + + return appName + " - " + name; + } + public void processFlash(final Graphics2D graphics) { FlashNotification flashNotification = runeLiteConfig.flashNotification(); diff --git a/runelite-client/src/main/java/net/runelite/client/RuneLite.java b/runelite-client/src/main/java/net/runelite/client/RuneLite.java index 1309cba17e..23376ad4f0 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLite.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLite.java @@ -46,6 +46,8 @@ import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import javax.swing.SwingUtilities; + +import com.openosrs.client.OpenOSRS; import joptsimple.ArgumentAcceptingOptionSpec; import joptsimple.OptionParser; import joptsimple.OptionSet; @@ -68,6 +70,7 @@ import net.runelite.client.game.ItemManager; import net.runelite.client.game.LootManager; import net.runelite.client.game.chatbox.ChatboxPanelManager; import net.runelite.client.menus.MenuManager; +import net.runelite.client.plugins.OPRSExternalPluginManager; import net.runelite.client.rs.ClientLoader; import net.runelite.client.rs.ClientUpdateCheckMode; import net.runelite.client.ui.ClientUI; @@ -91,9 +94,9 @@ import org.slf4j.LoggerFactory; @Slf4j public class RuneLite { - public static final File RUNELITE_DIR = new File(System.getProperty("user.home"), ".runelite"); + public static final File RUNELITE_DIR = new File(System.getProperty("user.home"), ".openosrs"); public static final File CACHE_DIR = new File(RUNELITE_DIR, "cache"); - public static final File PLUGINS_DIR = new File(RUNELITE_DIR, "plugins"); + public static final File PLUGINS_DIR = new File(RUNELITE_DIR, "plugin-hub"); public static final File PROFILES_DIR = new File(RUNELITE_DIR, "profiles"); public static final File SCREENSHOT_DIR = new File(RUNELITE_DIR, "screenshots"); public static final File LOGS_DIR = new File(RUNELITE_DIR, "logs"); @@ -112,7 +115,7 @@ public class RuneLite private ExternalPluginManager externalPluginManager; @Inject - private com.openosrs.client.plugins.ExternalPluginManager oprsExternalPluginManager; + private OPRSExternalPluginManager oprsExternalPluginManager; @Inject private EventBus eventBus; @@ -239,6 +242,8 @@ public class RuneLite } }); + OpenOSRS.preload(); + OkHttpClient.Builder okHttpClientBuilder = RuneLiteAPI.CLIENT.newBuilder() .cache(new Cache(new File(CACHE_DIR, "okhttp"), MAX_OKHTTP_CACHE_SIZE)); @@ -329,7 +334,7 @@ public class RuneLite oprsExternalPluginManager.startExternalPluginManager(); // Update external plugins - //oprsExternalPluginManager.update(); //TODO: Re-enable after fixing actions for new repo + oprsExternalPluginManager.update(); //TODO: Re-enable after fixing actions for new repo // Load the plugins, but does not start them yet. // This will initialize configuration diff --git a/runelite-client/src/main/java/net/runelite/client/RuneLiteModule.java b/runelite-client/src/main/java/net/runelite/client/RuneLiteModule.java index c20df7d8e5..19dd5c0c65 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLiteModule.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLiteModule.java @@ -25,11 +25,11 @@ package net.runelite.client; import com.google.common.util.concurrent.ThreadFactoryBuilder; +import com.google.gson.Gson; import com.google.inject.AbstractModule; import com.google.inject.Provides; import com.google.inject.name.Names; import com.openosrs.client.config.OpenOSRSConfig; -import com.openosrs.client.util.NonScheduledExecutorServiceExceptionLogger; import java.applet.Applet; import java.io.File; import java.util.Properties; @@ -58,6 +58,7 @@ import net.runelite.client.plugins.PluginManager; import net.runelite.client.task.Scheduler; import net.runelite.client.util.DeferredEventBus; import net.runelite.client.util.ExecutorServiceExceptionLogger; +import net.runelite.http.api.RuneLiteAPI; import net.runelite.http.api.chat.ChatClient; import okhttp3.OkHttpClient; import org.slf4j.Logger; @@ -95,6 +96,8 @@ public class RuneLiteModule extends AbstractModule bind(PluginManager.class); bind(SessionManager.class); + bind(Gson.class).toInstance(RuneLiteAPI.GSON); + bind(Callbacks.class).to(Hooks.class); bind(EventBus.class) diff --git a/runelite-client/src/main/java/net/runelite/client/account/SessionManager.java b/runelite-client/src/main/java/net/runelite/client/account/SessionManager.java index cadf0b4562..4b6bf1674e 100644 --- a/runelite-client/src/main/java/net/runelite/client/account/SessionManager.java +++ b/runelite-client/src/main/java/net/runelite/client/account/SessionManager.java @@ -64,6 +64,7 @@ public class SessionManager private final WSClient wsClient; private final File sessionFile; private final AccountClient accountClient; + private final Gson gson; @Inject private SessionManager( @@ -71,13 +72,15 @@ public class SessionManager ConfigManager configManager, EventBus eventBus, WSClient wsClient, - OkHttpClient okHttpClient) + OkHttpClient okHttpClient, + Gson gson) { this.configManager = configManager; this.eventBus = eventBus; this.wsClient = wsClient; this.sessionFile = sessionfile; this.accountClient = new AccountClient(okHttpClient); + this.gson = gson; eventBus.register(this); } @@ -94,7 +97,7 @@ public class SessionManager try (FileInputStream in = new FileInputStream(sessionFile)) { - session = new Gson().fromJson(new InputStreamReader(in, StandardCharsets.UTF_8), AccountSession.class); + session = gson.fromJson(new InputStreamReader(in, StandardCharsets.UTF_8), AccountSession.class); log.debug("Loaded session for {}", session.getUsername()); } @@ -124,7 +127,7 @@ public class SessionManager try (Writer fw = new OutputStreamWriter(new FileOutputStream(sessionFile), StandardCharsets.UTF_8)) { - new Gson().toJson(accountSession, fw); + gson.toJson(accountSession, fw); log.debug("Saved session to {}", sessionFile); } diff --git a/runelite-client/src/main/java/net/runelite/client/chat/ChatCommandManager.java b/runelite-client/src/main/java/net/runelite/client/chat/ChatCommandManager.java index 03bc5960b6..0c3a0bfcbc 100644 --- a/runelite-client/src/main/java/net/runelite/client/chat/ChatCommandManager.java +++ b/runelite-client/src/main/java/net/runelite/client/chat/ChatCommandManager.java @@ -106,11 +106,6 @@ public class ChatCommandManager implements ChatboxInputListener String message = chatMessage.getMessage(); String command = extractCommand(message); - if (command == null) - { - return; - } - ChatCommand chatCommand = commands.get(command.toLowerCase()); if (chatCommand == null) { @@ -137,11 +132,6 @@ public class ChatCommandManager implements ChatboxInputListener } String command = extractCommand(message); - if (command == null) - { - return false; - } - ChatCommand chatCommand = commands.get(command.toLowerCase()); if (chatCommand == null) { @@ -163,11 +153,6 @@ public class ChatCommandManager implements ChatboxInputListener final String message = privateMessageInput.getMessage(); String command = extractCommand(message); - if (command == null) - { - return false; - } - ChatCommand chatCommand = commands.get(command.toLowerCase()); if (chatCommand == null) { diff --git a/runelite-client/src/main/java/net/runelite/client/chat/ChatMessageManager.java b/runelite-client/src/main/java/net/runelite/client/chat/ChatMessageManager.java index 7faa7ac564..6e888ce8f1 100644 --- a/runelite-client/src/main/java/net/runelite/client/chat/ChatMessageManager.java +++ b/runelite-client/src/main/java/net/runelite/client/chat/ChatMessageManager.java @@ -39,22 +39,22 @@ import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicReference; import javax.inject.Inject; import javax.inject.Singleton; -import net.runelite.api.ChatLineBuffer; import net.runelite.api.ChatMessageType; import net.runelite.api.Client; import net.runelite.api.MessageNode; import net.runelite.api.Player; import net.runelite.api.Varbits; import net.runelite.api.events.ChatMessage; -import net.runelite.client.events.ConfigChanged; import net.runelite.api.events.ResizeableChanged; import net.runelite.api.events.ScriptCallbackEvent; import net.runelite.api.events.VarbitChanged; import net.runelite.client.callback.ClientThread; import net.runelite.client.config.ChatColorConfig; import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.events.ConfigChanged; import net.runelite.client.ui.JagexColors; import net.runelite.client.util.ColorUtil; +import net.runelite.client.util.Text; @Singleton public class ChatMessageManager @@ -126,7 +126,8 @@ public class ChatMessageManager case PUBLICCHAT: case MODCHAT: { - boolean isFriend = client.isFriended(chatMessage.getName(), true) && !client.getLocalPlayer().getName().equals(chatMessage.getName()); + String sanitizedUsername = Text.removeTags(chatMessage.getName()); + boolean isFriend = client.isFriended(sanitizedUsername, true) && !client.getLocalPlayer().getName().equals(sanitizedUsername); if (isFriend) { @@ -571,18 +572,15 @@ public class ChatMessageManager return; } + final String formattedMessage = formatRuneLiteMessage(message.getRuneLiteFormattedMessage(), message.getType()); + // this updates chat cycle - client.addChatMessage( + final MessageNode line = client.addChatMessage( message.getType(), MoreObjects.firstNonNull(message.getName(), ""), - MoreObjects.firstNonNull(message.getValue(), message.getRuneLiteFormattedMessage()), + MoreObjects.firstNonNull(formattedMessage, message.getValue()), message.getSender()); - // Get last message from line buffer (the one we just added) - final ChatLineBuffer chatLineBuffer = client.getChatLineMap().get(message.getType().getType()); - final MessageNode[] lines = chatLineBuffer.getLines(); - final MessageNode line = lines[0]; - // Update the message with RuneLite additions line.setRuneLiteFormatMessage(message.getRuneLiteFormattedMessage()); @@ -590,34 +588,38 @@ public class ChatMessageManager { line.setTimestamp(message.getTimestamp()); } - - update(line); } - public void update(final MessageNode target) + /** + * Rebuild the message node message from the RuneLite format message + * + * @param messageNode message node + */ + public void update(final MessageNode messageNode) { - if (Strings.isNullOrEmpty(target.getRuneLiteFormatMessage())) + String message = formatRuneLiteMessage(messageNode.getRuneLiteFormatMessage(), messageNode.getType()); + if (message != null) { - return; + messageNode.setValue(message); + } + } + + private String formatRuneLiteMessage(String runeLiteFormatMessage, ChatMessageType type) + { + if (Strings.isNullOrEmpty(runeLiteFormatMessage)) + { + return null; } final boolean transparent = client.isResized() && transparencyVarbit != 0; - final Collection chatColors = colorCache.get(target.getType()); + final Collection chatColors = colorCache.get(type); - // If we do not have any colors cached, simply set clean message if (chatColors == null || chatColors.isEmpty()) { - target.setValue(target.getRuneLiteFormatMessage()); - return; + return runeLiteFormatMessage; } - target.setValue(recolorMessage(transparent, target.getRuneLiteFormatMessage(), target.getType())); - } - - private String recolorMessage(boolean transparent, String message, ChatMessageType messageType) - { - final Collection chatColors = colorCache.get(messageType); - final AtomicReference resultMessage = new AtomicReference<>(message); + final AtomicReference resultMessage = new AtomicReference<>(runeLiteFormatMessage); // Replace custom formatting with actual colors chatColors.stream() diff --git a/runelite-client/src/main/java/net/runelite/client/config/Button.java b/runelite-client/src/main/java/net/runelite/client/config/Button.java new file mode 100644 index 0000000000..591332ce05 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/config/Button.java @@ -0,0 +1,5 @@ +package net.runelite.client.config; + +public class Button +{ +} diff --git a/runelite-client/src/main/java/net/runelite/client/config/ConfigItem.java b/runelite-client/src/main/java/net/runelite/client/config/ConfigItem.java index a9a511cc08..17a8fbad51 100644 --- a/runelite-client/src/main/java/net/runelite/client/config/ConfigItem.java +++ b/runelite-client/src/main/java/net/runelite/client/config/ConfigItem.java @@ -24,6 +24,8 @@ */ package net.runelite.client.config; +import com.openosrs.client.OpenOSRS; + import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java b/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java index 01d8ebfe1d..549ef0b123 100644 --- a/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java +++ b/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java @@ -152,6 +152,11 @@ public class ConfigManager scheduledExecutorService.scheduleWithFixedDelay(this::sendConfig, 30, 30, TimeUnit.SECONDS); } + public String getRSProfileKey() + { + return rsProfileKey; + } + public final void switchSession(AccountSession session) { // Ensure existing config is saved @@ -394,7 +399,7 @@ public class ConfigManager parent.mkdirs(); - File tempFile = new File(parent, RuneLite.DEFAULT_CONFIG_FILE.getName() + ".tmp"); + File tempFile = File.createTempFile("runelite", null, parent); try (FileOutputStream out = new FileOutputStream(tempFile)) { @@ -507,6 +512,11 @@ public class ConfigManager public void setConfiguration(String groupName, String profile, String key, String value) { + if (Strings.isNullOrEmpty(groupName) || Strings.isNullOrEmpty(key)) + { + throw new IllegalArgumentException(); + } + assert !key.startsWith(RSPROFILE_GROUP + "."); String wholeKey = getWholeKey(groupName, profile, key); String oldValue = (String) properties.setProperty(wholeKey, value); diff --git a/runelite-client/src/main/java/net/runelite/client/config/ConfigSection.java b/runelite-client/src/main/java/net/runelite/client/config/ConfigSection.java index 4a0f722d3f..282855920a 100644 --- a/runelite-client/src/main/java/net/runelite/client/config/ConfigSection.java +++ b/runelite-client/src/main/java/net/runelite/client/config/ConfigSection.java @@ -40,4 +40,12 @@ public @interface ConfigSection int position(); boolean closedByDefault() default false; + + /* + OpenOSRS Lazy Helpers tm + */ + String keyName() default ""; + String section() default ""; + boolean hidden() default false; + String unhide() default ""; } diff --git a/runelite-client/src/main/java/net/runelite/client/config/Keybind.java b/runelite-client/src/main/java/net/runelite/client/config/Keybind.java index e7e338a6b3..eba500b859 100644 --- a/runelite-client/src/main/java/net/runelite/client/config/Keybind.java +++ b/runelite-client/src/main/java/net/runelite/client/config/Keybind.java @@ -159,7 +159,7 @@ public class Keybind String mod = ""; if (modifiers != 0) { - mod = getModifiersExText(modifiers); + mod = InputEvent.getModifiersExText(modifiers); } if (mod.isEmpty() && key.isEmpty()) @@ -177,33 +177,6 @@ public class Keybind return mod; } - public static String getModifiersExText(int modifiers) - { - StringBuilder buf = new StringBuilder(); - if ((modifiers & InputEvent.META_DOWN_MASK) != 0) - { - buf.append("Meta+"); - } - if ((modifiers & InputEvent.CTRL_DOWN_MASK) != 0) - { - buf.append("Ctrl+"); - } - if ((modifiers & InputEvent.ALT_DOWN_MASK) != 0) - { - buf.append("Alt+"); - } - if ((modifiers & InputEvent.SHIFT_DOWN_MASK) != 0) - { - buf.append("Shift+"); - } - - if (buf.length() > 0) - { - buf.setLength(buf.length() - 1); // remove trailing '+' - } - return buf.toString(); - } - @Nullable public static Integer getModifierForKeyCode(int keyCode) { diff --git a/runelite-client/src/main/java/net/runelite/client/config/RuneLiteConfig.java b/runelite-client/src/main/java/net/runelite/client/config/RuneLiteConfig.java index dfa1583135..36b3084946 100644 --- a/runelite-client/src/main/java/net/runelite/client/config/RuneLiteConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/config/RuneLiteConfig.java @@ -32,6 +32,7 @@ import net.runelite.api.Constants; import net.runelite.client.Notifier; import net.runelite.client.ui.ContainableFrame; import net.runelite.client.ui.overlay.components.ComponentConstants; +import net.runelite.client.util.OSType; @ConfigGroup(RuneLiteConfig.GROUP_NAME) public interface RuneLiteConfig extends Config @@ -122,14 +123,14 @@ public interface RuneLiteConfig extends Config @ConfigItem( keyName = "uiEnableCustomChrome", name = "Enable custom window chrome", - description = "Use Runelite's custom window title and borders.", + description = "Use RuneLite's custom window title and borders.", warning = "Please restart your client after changing this setting", position = 15, section = windowSettings ) default boolean enableCustomChrome() { - return true; + return OSType.getOSType() == OSType.Windows; } @Range( @@ -150,7 +151,7 @@ public interface RuneLiteConfig extends Config @ConfigItem( keyName = "gameAlwaysOnTop", - name = "Enable client always on top", + name = "Always on top", description = "The game will always be on the top of the screen", position = 17, section = windowSettings @@ -162,8 +163,8 @@ public interface RuneLiteConfig extends Config @ConfigItem( keyName = "warningOnExit", - name = "Display warning on exit", - description = "Toggles a warning popup when trying to exit the client", + name = "Exit warning", + description = "Shows a warning popup when trying to exit the client", position = 18, section = windowSettings ) @@ -198,7 +199,7 @@ public interface RuneLiteConfig extends Config @ConfigItem( keyName = "notificationRequestFocus", - name = "Request focus on notification", + name = "Request focus", description = "Configures the window focus request type on notification", position = 21, section = notificationSettings @@ -222,8 +223,8 @@ public interface RuneLiteConfig extends Config @ConfigItem( keyName = "notificationGameMessage", - name = "Enable game message notifications", - description = "Puts a notification message in the chatbox", + name = "Game message notifications", + description = "Adds a notification message to the chatbox", position = 23, section = notificationSettings ) @@ -234,7 +235,7 @@ public interface RuneLiteConfig extends Config @ConfigItem( keyName = "flashNotification", - name = "Flash notification", + name = "Flash", description = "Flashes the game frame as a notification", position = 24, section = notificationSettings @@ -259,7 +260,7 @@ public interface RuneLiteConfig extends Config @Alpha @ConfigItem( keyName = "notificationFlashColor", - name = "Notification Flash Color", + name = "Notification Flash", description = "Sets the color of the notification flashes.", position = 26, section = notificationSettings @@ -295,7 +296,7 @@ public interface RuneLiteConfig extends Config @ConfigItem( keyName = "interfaceFontType", - name = "Interface Overlay Font", + name = "Interface Font", description = "Configures what font type is used for in-game interface overlays such as panels, opponent info, clue scrolls etc.", position = 32, section = overlaySettings diff --git a/runelite-client/src/main/java/net/runelite/client/config/Units.java b/runelite-client/src/main/java/net/runelite/client/config/Units.java index 45d54df164..ca872bfa80 100644 --- a/runelite-client/src/main/java/net/runelite/client/config/Units.java +++ b/runelite-client/src/main/java/net/runelite/client/config/Units.java @@ -42,8 +42,12 @@ public @interface Units String MINUTES = " mins"; String PERCENT = "%"; String PIXELS = "px"; + String POINTS = "pt"; String SECONDS = "s"; String TICKS = " ticks"; + String LEVELS = " lvls"; + String FPS = " fps"; + String GP = " GP"; String value(); } diff --git a/runelite-client/src/main/java/net/runelite/client/eventbus/EventBus.java b/runelite-client/src/main/java/net/runelite/client/eventbus/EventBus.java index 2340e306dd..4195484553 100644 --- a/runelite-client/src/main/java/net/runelite/client/eventbus/EventBus.java +++ b/runelite-client/src/main/java/net/runelite/client/eventbus/EventBus.java @@ -138,7 +138,10 @@ public class EventBus } final String preferredName = "on" + parameterClazz.getSimpleName(); - Preconditions.checkArgument(method.getName().equals(preferredName), "Subscribed method " + method + " should be named " + preferredName); + if (!method.getName().equals(preferredName)) + { + log.warn("Subscribed method {} should be named {}", method, preferredName); + } method.setAccessible(true); SubscriberMethod lambda = null; diff --git a/runelite-client/src/main/java/net/runelite/client/externalplugins/ExternalPluginClassLoader.java b/runelite-client/src/main/java/net/runelite/client/externalplugins/ExternalPluginClassLoader.java index 054a7779b5..5690c3d61e 100644 --- a/runelite-client/src/main/java/net/runelite/client/externalplugins/ExternalPluginClassLoader.java +++ b/runelite-client/src/main/java/net/runelite/client/externalplugins/ExternalPluginClassLoader.java @@ -24,18 +24,32 @@ */ package net.runelite.client.externalplugins; +import java.lang.invoke.MethodHandles; import java.net.URL; import java.net.URLClassLoader; import lombok.Getter; +import lombok.Setter; +import net.runelite.client.util.ReflectUtil; -class ExternalPluginClassLoader extends URLClassLoader +class ExternalPluginClassLoader extends URLClassLoader implements ReflectUtil.PrivateLookupableClassLoader { @Getter private final ExternalPluginManifest manifest; + @Getter + @Setter + private MethodHandles.Lookup lookup; + ExternalPluginClassLoader(ExternalPluginManifest manifest, URL[] urls) { super(urls, ExternalPluginClassLoader.class.getClassLoader()); this.manifest = manifest; + ReflectUtil.installLookupHelper(this); + } + + @Override + public Class defineClass0(String name, byte[] b, int off, int len) throws ClassFormatError + { + return super.defineClass(name, b, off, len); } } diff --git a/runelite-client/src/main/java/net/runelite/client/externalplugins/ExternalPluginClient.java b/runelite-client/src/main/java/net/runelite/client/externalplugins/ExternalPluginClient.java index 0df12bf1ed..ccf4b9fad3 100644 --- a/runelite-client/src/main/java/net/runelite/client/externalplugins/ExternalPluginClient.java +++ b/runelite-client/src/main/java/net/runelite/client/externalplugins/ExternalPluginClient.java @@ -25,9 +25,12 @@ package net.runelite.client.externalplugins; import com.google.common.reflect.TypeToken; +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; @@ -37,6 +40,7 @@ import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.util.List; +import java.util.Map; import javax.imageio.ImageIO; import javax.inject.Inject; import lombok.extern.slf4j.Slf4j; @@ -56,11 +60,13 @@ import okio.BufferedSource; public class ExternalPluginClient { private final OkHttpClient okHttpClient; + private final Gson gson; @Inject - private ExternalPluginClient(OkHttpClient okHttpClient) + private ExternalPluginClient(OkHttpClient okHttpClient, Gson gson) { this.okHttpClient = okHttpClient; + this.gson = gson; } public List downloadManifest() throws IOException, VerificationException @@ -91,7 +97,7 @@ public class ExternalPluginClient throw new VerificationException("Unable to verify external plugin manifest"); } - return RuneLiteAPI.GSON.fromJson(new String(data, StandardCharsets.UTF_8), + return gson.fromJson(new String(data, StandardCharsets.UTF_8), new TypeToken>() { }.getType()); @@ -153,7 +159,7 @@ public class ExternalPluginClient Request request = new Request.Builder() .url(url) - .post(RequestBody.create(RuneLiteAPI.JSON, RuneLiteAPI.GSON.toJson(plugins))) + .post(RequestBody.create(RuneLiteAPI.JSON, gson.toJson(plugins))) .build(); okHttpClient.newCall(request).enqueue(new Callback() @@ -172,4 +178,27 @@ public class ExternalPluginClient } }); } + + public Map getPluginCounts() throws IOException + { + HttpUrl url = RuneLiteAPI.getApiBase() + .newBuilder() + .addPathSegments("pluginhub") + .build(); + try (Response res = okHttpClient.newCall(new Request.Builder().url(url).build()).execute()) + { + if (res.code() != 200) + { + throw new IOException("Non-OK response code: " + res.code()); + } + + // CHECKSTYLE:OFF + return gson.fromJson(new InputStreamReader(res.body().byteStream()), new TypeToken>(){}.getType()); + // CHECKSTYLE:ON + } + catch (JsonSyntaxException ex) + { + throw new IOException(ex); + } + } } diff --git a/runelite-client/src/main/java/net/runelite/client/game/AgilityShortcut.java b/runelite-client/src/main/java/net/runelite/client/game/AgilityShortcut.java index ad6c5e0925..5833b05a37 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/AgilityShortcut.java +++ b/runelite-client/src/main/java/net/runelite/client/game/AgilityShortcut.java @@ -93,6 +93,9 @@ public enum AgilityShortcut YANILLE_UNDERWALL_TUNNEL(16, "Underwall Tunnel", new WorldPoint(2574, 3109, 0), HOLE_16520, CASTLE_WALL), KOUREND_CATACOMBS_SOUTH_WEST_CREVICE_NORTH(17, "Crevice", new WorldPoint(1647, 10008, 0), CRACK_28892), KOUREND_CATACOMBS_SOUTH_WEST_CREVICE_SOUTH(17, "Crevice", new WorldPoint(1645, 10001, 0), CRACK_28892), + CRABCLAW_CAVES_CREVICE(18, "Crevice", new WorldPoint(1710, 9822, 0), CREVICE_31695, CREVICE_31696), + CRABCLAW_CAVES_ROCKS(18, "Rocks", new WorldPoint(1687, 9802, 0), ROCKS_31697), + CRABCLAW_CAVES_STEPPING_STONES(18, "Stepping Stones", new WorldPoint(1704, 9800, 0), STEPPING_STONE_31699), YANILLE_WATCHTOWER_TRELLIS(18, "Trellis", null, TRELLIS_20056), COAL_TRUCKS_LOG_BALANCE(20, "Log Balance", new WorldPoint(2598, 3475, 0), LOG_BALANCE_23274), GRAND_EXCHANGE_UNDERWALL_TUNNEL(21, "Underwall Tunnel", new WorldPoint(3139, 3515, 0), UNDERWALL_TUNNEL_16529, UNDERWALL_TUNNEL_16530), @@ -234,7 +237,7 @@ public enum AgilityShortcut @Getter private final int level; /** - * Brief description of the shortcut (e.g. 'Rocks', 'Stepping Stones', 'Jump') + * Brief description of the shortcut. (e.g. 'Rocks', 'Stepping Stones', 'Jump') */ @Getter private final String description; diff --git a/runelite-client/src/main/java/net/runelite/client/game/FishingSpot.java b/runelite-client/src/main/java/net/runelite/client/game/FishingSpot.java index 14d7b96316..a3de9412a2 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/FishingSpot.java +++ b/runelite-client/src/main/java/net/runelite/client/game/FishingSpot.java @@ -29,6 +29,9 @@ import java.util.Map; import lombok.Getter; import net.runelite.api.ItemID; import static net.runelite.api.NpcID.FISHING_SPOT; +import static net.runelite.api.NpcID.FISHING_SPOT_10513; +import static net.runelite.api.NpcID.FISHING_SPOT_10514; +import static net.runelite.api.NpcID.FISHING_SPOT_10515; import static net.runelite.api.NpcID.FISHING_SPOT_1497; import static net.runelite.api.NpcID.FISHING_SPOT_1498; import static net.runelite.api.NpcID.FISHING_SPOT_1499; @@ -132,13 +135,14 @@ public enum FishingSpot FISHING_SPOT_1525, FISHING_SPOT_1528, FISHING_SPOT_1530, FISHING_SPOT_1544, FISHING_SPOT_3913, FISHING_SPOT_7155, FISHING_SPOT_7459, FISHING_SPOT_7462, FISHING_SPOT_7467, - FISHING_SPOT_7469, FISHING_SPOT_7947 + FISHING_SPOT_7469, FISHING_SPOT_7947, FISHING_SPOT_10513 ), LOBSTER("Lobster, Swordfish, Tuna", "Lobster", ItemID.RAW_LOBSTER, FISHING_SPOT_1510, FISHING_SPOT_1519, FISHING_SPOT_1522, FISHING_SPOT_3914, FISHING_SPOT_5820, FISHING_SPOT_7199, FISHING_SPOT_7460, FISHING_SPOT_7465, FISHING_SPOT_7470, - FISHING_SPOT_7946, FISHING_SPOT_9173, FISHING_SPOT_9174 + FISHING_SPOT_7946, FISHING_SPOT_9173, FISHING_SPOT_9174, + FISHING_SPOT_10515 ), SHARK("Shark, Bass", "Shark", ItemID.RAW_SHARK, FISHING_SPOT_1511, FISHING_SPOT_1520, FISHING_SPOT_3419, @@ -146,7 +150,7 @@ public enum FishingSpot FISHING_SPOT_5233, FISHING_SPOT_5234, FISHING_SPOT_5821, FISHING_SPOT_7200, FISHING_SPOT_7461, FISHING_SPOT_7466, FISHING_SPOT_8525, FISHING_SPOT_8526, FISHING_SPOT_8527, - FISHING_SPOT_9171, FISHING_SPOT_9172 + FISHING_SPOT_9171, FISHING_SPOT_9172, FISHING_SPOT_10514 ), MONKFISH("Monkfish", ItemID.RAW_MONKFISH, FISHING_SPOT_4316 diff --git a/runelite-client/src/main/java/net/runelite/client/game/ItemManager.java b/runelite-client/src/main/java/net/runelite/client/game/ItemManager.java index 21769f98a1..9518ed82d0 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/ItemManager.java +++ b/runelite-client/src/main/java/net/runelite/client/game/ItemManager.java @@ -151,6 +151,12 @@ public class ItemManager put(GRACEFUL_LEGS_24754, GRACEFUL_LEGS_24752). put(GRACEFUL_GLOVES_24757, GRACEFUL_GLOVES_24755). put(GRACEFUL_BOOTS_24760, GRACEFUL_BOOTS_24758). + put(GRACEFUL_HOOD_25071, GRACEFUL_HOOD_25069). + put(GRACEFUL_CAPE_25074, GRACEFUL_CAPE_25072). + put(GRACEFUL_TOP_25077, GRACEFUL_TOP_25075). + put(GRACEFUL_LEGS_25080, GRACEFUL_LEGS_25078). + put(GRACEFUL_GLOVES_25083, GRACEFUL_GLOVES_25081). + put(GRACEFUL_BOOTS_25086, GRACEFUL_BOOTS_25084). put(MAX_CAPE_13342, MAX_CAPE). diff --git a/runelite-client/src/main/java/net/runelite/client/game/ItemMapping.java b/runelite-client/src/main/java/net/runelite/client/game/ItemMapping.java index 725fabb239..58f9a917a5 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/ItemMapping.java +++ b/runelite-client/src/main/java/net/runelite/client/game/ItemMapping.java @@ -68,8 +68,17 @@ public enum ItemMapping ITEM_DRAGON_SCIMITAR(DRAGON_SCIMITAR, DRAGON_SCIMITAR_OR), ITEM_DRAGON_SCIMITAR_ORNAMENT_KIT(DRAGON_SCIMITAR_ORNAMENT_KIT, DRAGON_SCIMITAR_OR), ITEM_DRAGON_DEFENDER(DRAGON_DEFENDER_ORNAMENT_KIT, DRAGON_DEFENDER_T), - ITEM_DRAGON_PICKAXE(DRAGON_PICKAXE, DRAGON_PICKAXE_12797, DRAGON_PICKAXE_OR), + ITEM_DRAGON_PICKAXE(DRAGON_PICKAXE, DRAGON_PICKAXE_12797, DRAGON_PICKAXE_OR, DRAGON_PICKAXE_OR_25376), ITEM_DRAGON_PICKAXE_OR(ZALCANO_SHARD, DRAGON_PICKAXE_OR), + ITEM_DRAGON_AXE(DRAGON_AXE, DRAGON_AXE_OR), + ITEM_DRAGON_HARPOON(DRAGON_HARPOON, DRAGON_HARPOON_OR), + ITEM_INFERNAL_PICKAXE_OR(INFERNAL_PICKAXE, INFERNAL_PICKAXE_OR), + ITEM_INFERNAL_PICKAXE_OR_UNCHARGED(INFERNAL_PICKAXE_UNCHARGED, INFERNAL_PICKAXE_UNCHARGED_25369), + ITEM_INFERNAL_AXE_OR(INFERNAL_AXE, INFERNAL_AXE_OR), + ITEM_INFERNAL_AXE_OR_UNCHARGED(INFERNAL_AXE_UNCHARGED, INFERNAL_AXE_UNCHARGED_25371), + ITEM_INFERNAL_HARPOON_OR(INFERNAL_HARPOON, INFERNAL_HARPOON_OR), + ITEM_INFERNAL_HARPOON_OR_UNCHARGED(INFERNAL_HARPOON_UNCHARGED, INFERNAL_HARPOON_UNCHARGED_25367), + ITEM_TRAILBLAZER_TOOL_ORNAMENT_KIT(TRAILBLAZER_TOOL_ORNAMENT_KIT, DRAGON_PICKAXE_OR_25376, DRAGON_AXE_OR, DRAGON_HARPOON_OR, INFERNAL_PICKAXE_OR, INFERNAL_AXE_OR, INFERNAL_HARPOON_OR, INFERNAL_PICKAXE_UNCHARGED_25369, INFERNAL_AXE_UNCHARGED_25371, INFERNAL_HARPOON_UNCHARGED_25367), ITEM_DRAGON_KITESHIELD(DRAGON_KITESHIELD, DRAGON_KITESHIELD_G), ITEM_DRAGON_KITESHIELD_ORNAMENT_KIT(DRAGON_KITESHIELD_ORNAMENT_KIT, DRAGON_KITESHIELD_G), ITEM_DRAGON_FULL_HELM(DRAGON_FULL_HELM, DRAGON_FULL_HELM_G), diff --git a/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextInput.java b/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextInput.java index a11aad1e1c..6ed4be3409 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextInput.java +++ b/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextInput.java @@ -689,6 +689,11 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse log.warn("Unable to get clipboard", ex); } return; + case KeyEvent.VK_A: + selectionStart = 0; + selectionEnd = value.length(); + cursorAt(0, selectionEnd); + return; } return; } @@ -753,11 +758,25 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse return; case KeyEvent.VK_LEFT: ev.consume(); - newPos--; + if (cursorStart != cursorEnd) + { + newPos = cursorStart; + } + else + { + newPos--; + } break; case KeyEvent.VK_RIGHT: ev.consume(); - newPos++; + if (cursorStart != cursorEnd) + { + newPos = cursorEnd; + } + else + { + newPos++; + } break; case KeyEvent.VK_UP: ev.consume(); diff --git a/runelite-client/src/main/java/net/runelite/client/menus/MenuManager.java b/runelite-client/src/main/java/net/runelite/client/menus/MenuManager.java index 67129b0ba5..c2231233db 100644 --- a/runelite-client/src/main/java/net/runelite/client/menus/MenuManager.java +++ b/runelite-client/src/main/java/net/runelite/client/menus/MenuManager.java @@ -26,33 +26,25 @@ package net.runelite.client.menus; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; -import com.google.common.collect.HashMultimap; +import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.Multimap; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; -import java.util.Set; -import java.util.regex.Pattern; import javax.inject.Inject; import javax.inject.Singleton; import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; -import net.runelite.api.IconID; import net.runelite.api.MenuAction; import net.runelite.api.MenuEntry; -import net.runelite.api.NPCComposition; import net.runelite.api.events.MenuEntryAdded; import net.runelite.api.events.MenuOptionClicked; -import net.runelite.api.events.NpcActionChanged; -import net.runelite.api.events.PlayerMenuOptionClicked; import net.runelite.api.events.PlayerMenuOptionsChanged; import net.runelite.api.events.WidgetMenuOptionClicked; import net.runelite.api.widgets.WidgetInfo; import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.util.Text; @Singleton @Slf4j @@ -64,16 +56,13 @@ public class MenuManager private static final int IDX_LOWER = 4; private static final int IDX_UPPER = 8; - private static final Pattern BOUNTY_EMBLEM_TAG_AND_TIER_REGEXP = Pattern.compile(String.format("%s[1-9]0?", IconID.BOUNTY_HUNTER_EMBLEM.toString())); - private final Client client; private final EventBus eventBus; //Maps the indexes that are being used to the menu option. private final Map playerMenuIndexMap = new HashMap<>(); //Used to manage custom non-player menu options - private final Multimap managedMenuOptions = HashMultimap.create(); - private final Set npcMenuOptions = new HashSet<>(); + private final Multimap managedMenuOptions = LinkedHashMultimap.create(); @Inject @VisibleForTesting @@ -123,7 +112,7 @@ public class MenuManager @Subscribe public void onMenuEntryAdded(MenuEntryAdded event) { - if (client.getSpellSelected()) + if (client.getSpellSelected() || event.getType() != MenuAction.CC_OP.getId()) { return; } @@ -200,45 +189,12 @@ public class MenuManager addPlayerMenuItem(newIdx, menuText); } - @Subscribe - public void onNpcActionChanged(NpcActionChanged event) - { - NPCComposition composition = event.getNpcComposition(); - for (String npcOption : npcMenuOptions) - { - addNpcOption(composition, npcOption); - } - } - - private void addNpcOption(NPCComposition composition, String npcOption) - { - String[] actions = composition.getActions(); - int unused = -1; - for (int i = 0; i < actions.length; ++i) - { - if (actions[i] == null && unused == -1) - { - unused = i; - } - else if (actions[i] != null && actions[i].equals(npcOption)) - { - return; - } - } - if (unused == -1) - { - return; - } - actions[unused] = npcOption; - } - @Subscribe public void onMenuOptionClicked(MenuOptionClicked event) { - if (event.getMenuAction() != MenuAction.RUNELITE - && event.getMenuAction() != MenuAction.RUNELITE_PLAYER) + if (event.getMenuAction() != MenuAction.RUNELITE) { - return; // not a managed widget option or custom player option + return; } int widgetId = event.getWidgetId(); @@ -254,23 +210,9 @@ public class MenuManager customMenu.setMenuTarget(event.getMenuTarget()); customMenu.setWidget(curMenuOption.getWidget()); eventBus.post(customMenu); - return; // don't continue because it's not a player option + return; } } - - // removes bounty hunter emblem tag and tier from player name, e.g: - // "username5 (level-42)" -> "username (level-42)" - String target = BOUNTY_EMBLEM_TAG_AND_TIER_REGEXP.matcher(event.getMenuTarget()).replaceAll(""); - - // removes tags and level from player names for example: - // username (level-42) or username - String username = Text.removeTags(target).split("[(]")[0].trim(); - - PlayerMenuOptionClicked playerMenuOptionClicked = new PlayerMenuOptionClicked(); - playerMenuOptionClicked.setMenuOption(event.getMenuOption()); - playerMenuOptionClicked.setMenuTarget(username); - - eventBus.post(playerMenuOptionClicked); } private void addPlayerMenuItem(int playerOptionIndex, String menuText) diff --git a/runelite-client/src/main/java/net/runelite/client/menus/WidgetMenuOption.java b/runelite-client/src/main/java/net/runelite/client/menus/WidgetMenuOption.java index 307551542c..d24ae1d18d 100644 --- a/runelite-client/src/main/java/net/runelite/client/menus/WidgetMenuOption.java +++ b/runelite-client/src/main/java/net/runelite/client/menus/WidgetMenuOption.java @@ -33,11 +33,11 @@ import net.runelite.client.util.ColorUtil; public final class WidgetMenuOption { /** - * The left hand text to be displayed on the menu option. Ex. the menuOption of "Drop Bones" is "Drop" + * The left hand text to be displayed on the menu option. (ex. the menuOption of "Drop Bones" is "Drop") */ private String menuOption; /** - * The right hand text to be displayed on the menu option Ex. the menuTarget of "Drop Bones" is "Bones" + * The right hand text to be displayed on the menu option. (ex. the menuTarget of "Drop Bones" is "Bones") */ private String menuTarget; /** diff --git a/runelite-client/src/main/java/com/openosrs/client/plugins/ExternalPf4jPluginManager.java b/runelite-client/src/main/java/net/runelite/client/plugins/OPRSExternalPf4jPluginManager.java similarity index 95% rename from runelite-client/src/main/java/com/openosrs/client/plugins/ExternalPf4jPluginManager.java rename to runelite-client/src/main/java/net/runelite/client/plugins/OPRSExternalPf4jPluginManager.java index e151ba3df2..30abbfa8eb 100644 --- a/runelite-client/src/main/java/com/openosrs/client/plugins/ExternalPf4jPluginManager.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/OPRSExternalPf4jPluginManager.java @@ -1,4 +1,4 @@ -package com.openosrs.client.plugins; +package net.runelite.client.plugins; import com.openosrs.client.OpenOSRS; import java.io.Closeable; @@ -33,11 +33,11 @@ import org.pf4j.PluginWrapper; import org.pf4j.RuntimeMode; @Slf4j -class ExternalPf4jPluginManager extends DefaultPluginManager +class OPRSExternalPf4jPluginManager extends DefaultPluginManager { - private final ExternalPluginManager externalPluginManager; + private final OPRSExternalPluginManager externalPluginManager; - public ExternalPf4jPluginManager(ExternalPluginManager externalPluginManager) + public OPRSExternalPf4jPluginManager(OPRSExternalPluginManager externalPluginManager) { super(OpenOSRS.EXTERNALPLUGIN_DIR.toPath()); this.externalPluginManager = externalPluginManager; @@ -55,7 +55,7 @@ class ExternalPf4jPluginManager extends DefaultPluginManager // The superclass performs a find, which is slow in development mode since we're pointing // at a sources directory, which can have a lot of files. The external plugin template // will always output the manifest at the following location, so we can hardcode this path. - return pluginPath.resolve(ExternalPluginManager.DEVELOPMENT_MANIFEST_PATH); + return pluginPath.resolve(OPRSExternalPluginManager.DEVELOPMENT_MANIFEST_PATH); } return super.getManifestPath(pluginPath); @@ -78,7 +78,7 @@ class ExternalPf4jPluginManager extends DefaultPluginManager protected PluginLoader createPluginLoader() { return new CompoundPluginLoader() - .add(new BasePluginLoader(this, new ExternalPluginClasspath()), this::isDevelopment) + .add(new BasePluginLoader(this, new OPRSExternalPluginClasspath()), this::isDevelopment) .add(new JarPluginLoader(this), this::isNotDevelopment); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/OPRSExternalPluginClasspath.java b/runelite-client/src/main/java/net/runelite/client/plugins/OPRSExternalPluginClasspath.java new file mode 100644 index 0000000000..9415590a95 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/OPRSExternalPluginClasspath.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020, SwazRGB + * 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; + +import org.pf4j.DevelopmentPluginClasspath; + +class OPRSExternalPluginClasspath extends DevelopmentPluginClasspath +{ + static final String GRADLE_DEPS_PATH = "build/deps"; + + OPRSExternalPluginClasspath() + { + addJarsDirectories(GRADLE_DEPS_PATH); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/OPRSExternalPluginFileFilter.java b/runelite-client/src/main/java/net/runelite/client/plugins/OPRSExternalPluginFileFilter.java new file mode 100644 index 0000000000..c9f44068e9 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/OPRSExternalPluginFileFilter.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2020, SwazRGB + * 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; + +import java.io.File; +import java.io.FileFilter; +import java.util.Arrays; +import java.util.List; + +/** + * Determines whether a {@link File} is an external plugin folder. To be considered a plugin a folder must: + *

+ * * Must not be a blacklisted name + * * Have a {@code .gradle.kts} file in the root named after the folder + * * Have a {@code MANIFEST.MF} located at {@code build/tmp/jar/MANIFEST.MF} + */ +public class OPRSExternalPluginFileFilter implements FileFilter +{ + private static final List blacklist = Arrays.asList( + ".git", + "build", + "target", + "release" + ); + + private static final List buildFiles = Arrays.asList( + "%s.gradle.kts", + "%s.gradle" + ); + + @Override + public boolean accept(File pathName) + { + // Check if this path looks like a plugin development directory + if (!pathName.isDirectory()) + { + return false; + } + + String dirName = pathName.getName(); + if (blacklist.contains(dirName)) + { + return false; + } + + // Check if the plugin directory has a MANIFEST.MF which si required for loading + if (!new File(pathName, OPRSExternalPluginManager.DEVELOPMENT_MANIFEST_PATH).exists()) + { + return false; + } + + // By convention plugins their directory is $name and they have a $name.gradle.kts or $name.gradle file in their root + for (String buildFile : buildFiles) + { + if (new File(pathName, String.format(buildFile, dirName)).exists()) + { + return true; + } + } + + return false; + } +} diff --git a/runelite-client/src/main/java/com/openosrs/client/plugins/ExternalPluginManager.java b/runelite-client/src/main/java/net/runelite/client/plugins/OPRSExternalPluginManager.java similarity index 93% rename from runelite-client/src/main/java/com/openosrs/client/plugins/ExternalPluginManager.java rename to runelite-client/src/main/java/net/runelite/client/plugins/OPRSExternalPluginManager.java index add932f725..3512d1a859 100644 --- a/runelite-client/src/main/java/com/openosrs/client/plugins/ExternalPluginManager.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/OPRSExternalPluginManager.java @@ -22,7 +22,7 @@ * (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 com.openosrs.client.plugins; +package net.runelite.client.plugins; import com.google.common.collect.Lists; import com.google.common.graph.GraphBuilder; @@ -36,15 +36,15 @@ import com.google.inject.Module; import static com.openosrs.client.OpenOSRS.EXTERNALPLUGIN_DIR; import static com.openosrs.client.OpenOSRS.SYSTEM_VERSION; import com.openosrs.client.config.OpenOSRSConfig; -import com.openosrs.client.events.ExternalPluginChanged; -import com.openosrs.client.events.ExternalRepositoryChanged; +import com.openosrs.client.events.OPRSPluginChanged; +import com.openosrs.client.events.OPRSRepositoryChanged; import com.openosrs.client.ui.OpenOSRSSplashScreen; import com.openosrs.client.util.Groups; -import com.openosrs.client.util.MiscUtils; -import com.openosrs.client.util.SwingUtil; import java.lang.reflect.InvocationTargetException; import java.net.MalformedURLException; import java.net.URL; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.ArrayList; import java.util.HashMap; @@ -75,10 +75,9 @@ import net.runelite.client.config.ConfigManager; import net.runelite.client.config.RuneLiteConfig; import net.runelite.client.eventbus.EventBus; import net.runelite.client.events.ConfigChanged; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.plugins.PluginInstantiationException; -import net.runelite.client.plugins.PluginManager; +import net.runelite.client.events.ExternalPluginsChanged; import net.runelite.client.ui.ClientUI; +import net.runelite.client.util.SwingUtil; import org.jgroups.Message; import org.pf4j.DefaultPluginManager; import org.pf4j.DependencyResolver; @@ -92,9 +91,9 @@ import org.pf4j.update.UpdateRepository; @Slf4j @Singleton -public class ExternalPluginManager +public class OPRSExternalPluginManager { - public static final String DEFAULT_PLUGIN_REPOS = "OpenOSRS:https://raw.githubusercontent.com/zeruth/runelite-plugins-release/master/"; + public static final String DEFAULT_PLUGIN_REPOS = ""; static final String DEVELOPMENT_MANIFEST_PATH = "build/tmp/jar/MANIFEST.MF"; public static ArrayList pluginClassLoaders = new ArrayList<>(); @@ -115,7 +114,7 @@ public class ExternalPluginManager private final boolean safeMode; @Inject - public ExternalPluginManager( + public OPRSExternalPluginManager( @Named("safeMode") final boolean safeMode, PluginManager pluginManager, OpenOSRSConfig openOSRSConfig, @@ -143,7 +142,7 @@ public class ExternalPluginManager private void initPluginManager() { - externalPluginManager = new ExternalPf4jPluginManager(this); + externalPluginManager = new OPRSExternalPf4jPluginManager(this); externalPluginManager.setSystemVersion(SYSTEM_VERSION); } @@ -327,14 +326,14 @@ public class ExternalPluginManager { DefaultUpdateRepository respository = new DefaultUpdateRepository(key, url); updateManager.addRepository(respository); - eventBus.post(new ExternalRepositoryChanged(key, true)); + eventBus.post(new OPRSRepositoryChanged(key, true)); saveConfig(); } public void removeRepository(String owner) { updateManager.removeRepository(owner); - eventBus.post(new ExternalRepositoryChanged(owner, false)); + eventBus.post(new OPRSRepositoryChanged(owner, false)); saveConfig(); } @@ -346,7 +345,7 @@ public class ExternalPluginManager { config.append(repository.getId()); config.append("|"); - config.append(MiscUtils.urlToStringEncoded(repository.getUrl())); + config.append(urlToStringEncoded(repository.getUrl())); config.append(";"); } config.deleteCharAt(config.lastIndexOf(";")); @@ -629,7 +628,7 @@ public class ExternalPluginManager { runelitePluginManager.add(plugin); runelitePluginManager.startPlugin(plugin); - eventBus.post(new ExternalPluginChanged(pluginsMap.get(plugin.getClass().getSimpleName()), + eventBus.post(new OPRSPluginChanged(pluginsMap.get(plugin.getClass().getSimpleName()), plugin, true)); } catch (PluginInstantiationException e) @@ -796,7 +795,7 @@ public class ExternalPluginManager runelitePluginManager.remove(plugin); pluginClassLoaders.remove(plugin.getClass().getClassLoader()); - eventBus.post(new ExternalPluginChanged(pluginId, plugin, false)); + eventBus.post(new OPRSPluginChanged(pluginId, plugin, false)); return pluginWrapper.getPluginPath(); } @@ -820,6 +819,8 @@ public class ExternalPluginManager groups.broadcastSring("STARTEXTERNAL;" + pluginId); scanAndInstantiate(loadPlugin(pluginId), true, false); + ExternalPluginsChanged event = new ExternalPluginsChanged(null); + eventBus.post(event); return true; } @@ -853,9 +854,9 @@ public class ExternalPluginManager } updateManager.installPlugin(pluginId, null); - scanAndInstantiate(loadPlugin(pluginId), true, true); - + ExternalPluginsChanged event = new ExternalPluginsChanged(null); + eventBus.post(event); groups.broadcastSring("STARTEXTERNAL;" + pluginId); } catch (DependencyResolver.DependenciesNotFoundException ex) @@ -1069,4 +1070,27 @@ public class ExternalPluginManager } } + /** + * Mostly stolen from {@link java.net.URLStreamHandler#toExternalForm(URL)} + * + * @param url URL to encode + * @return URL, with path, query and ref encoded + */ + private 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); + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/Plugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/Plugin.java index a36a1f40e6..80aafcc860 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/Plugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/Plugin.java @@ -27,9 +27,13 @@ package net.runelite.client.plugins; import com.google.inject.Binder; import com.google.inject.Injector; import com.google.inject.Module; +import lombok.Getter; +import org.pf4j.ExtensionPoint; +import net.runelite.client.RuneLite; -public abstract class Plugin implements Module +public abstract class Plugin implements Module, ExtensionPoint { + @Getter protected Injector injector; @Override @@ -49,11 +53,6 @@ public abstract class Plugin implements Module { } - public final Injector getInjector() - { - return injector; - } - public String getName() { return getClass().getAnnotation(PluginDescriptor.class).name(); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/PluginManager.java b/runelite-client/src/main/java/net/runelite/client/plugins/PluginManager.java index b4d5934f2f..500bd48000 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/PluginManager.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/PluginManager.java @@ -87,7 +87,6 @@ public class PluginManager * Base package where the core plugins are */ private static final String PLUGIN_PACKAGE = "net.runelite.client.plugins"; - private static final String OPENOSRS_PACKAGE = "com.openosrs.client.plugins"; private final boolean developerMode; private final boolean safeMode; @@ -164,8 +163,21 @@ public class PluginManager { try { - final Injector injector = plugin.getInjector(); - + Injector injector = plugin.getInjector(); + if (injector == null) + { + // Create injector for the module + Module pluginModule = (Binder binder) -> + { + // Since the plugin itself is a module, it won't bind itself, so we'll bind it here + binder.bind((Class) plugin.getClass()).toInstance(plugin); + binder.install(plugin); + }; + Injector pluginInjector = RuneLite.getInjector().createChildInjector(pluginModule); + pluginInjector.injectMembers(plugin); + plugin.injector = pluginInjector; + injector = pluginInjector; + } for (Key key : injector.getBindings().keySet()) { Class type = key.getTypeLiteral().getRawType(); @@ -291,10 +303,6 @@ public class PluginManager .map(ClassInfo::load) .collect(Collectors.toList()); - plugins.addAll(classPath.getTopLevelClassesRecursive(OPENOSRS_PACKAGE).stream() - .map(ClassInfo::load) - .collect(Collectors.toList())); - loadPlugins(plugins, (loaded, total) -> SplashScreen.stage(.60, .70, null, "Loading Plugins", loaded, total, false)); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/achievementdiary/diaries/KaramjaDiaryRequirement.java b/runelite-client/src/main/java/net/runelite/client/plugins/achievementdiary/diaries/KaramjaDiaryRequirement.java index fc906cccb4..acdae10ce3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/achievementdiary/diaries/KaramjaDiaryRequirement.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/achievementdiary/diaries/KaramjaDiaryRequirement.java @@ -50,9 +50,9 @@ public class KaramjaDiaryRequirement extends GenericDiaryRequirement add("Claim a ticket from the Agility Arena in Brimhaven.", new SkillRequirement(Skill.AGILITY, 30)); add("Discover hidden wall in the dungeon below the volcano.", - new QuestRequirement(Quest.DRAGON_SLAYER, true)); + new QuestRequirement(Quest.DRAGON_SLAYER_I, true)); add("Visit the Isle of Crandor via the dungeon below the volcano.", - new QuestRequirement(Quest.DRAGON_SLAYER, true)); + new QuestRequirement(Quest.DRAGON_SLAYER_I, true)); add("Use Vigroy and Hajedy's cart service.", new QuestRequirement(Quest.SHILO_VILLAGE)); add("Earn 100% favour in the village of Tai Bwo Wannai.", diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityConfig.java index a5ba1dca42..c68530ec95 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityConfig.java @@ -147,7 +147,7 @@ public interface AgilityConfig extends Config @Alpha @ConfigItem( keyName = "portalsHighlight", - name = "Portals Highlight Color", + name = "Portals Color", description = "Color of highlighted Prifddinas portals", position = 9 ) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/bank/BankPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/bank/BankPlugin.java index 5b8ea483d6..e0161503ae 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/bank/BankPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/bank/BankPlugin.java @@ -275,7 +275,7 @@ public class BankPlugin extends Plugin final Widget[] children = bankItemContainer.getChildren(); long geTotal = 0, haTotal = 0; - if (children != null) + if (bankContainer != null && children != null) { log.debug("Computing bank price of {} items", bankContainer.size()); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/MinigamePoint.java b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTag.java similarity index 78% rename from runelite-client/src/main/java/net/runelite/client/plugins/worldmap/MinigamePoint.java rename to runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTag.java index bd670aa023..74926bc292 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/MinigamePoint.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Magic fTail + * Copyright (c) 2021, Adam * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,16 +23,9 @@ * 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.worldmap; +package net.runelite.client.plugins.banktags; -import java.awt.image.BufferedImage; -import net.runelite.client.ui.overlay.worldmap.WorldMapPoint; - -class MinigamePoint extends WorldMapPoint +public interface BankTag { - MinigamePoint(MinigameLocation data, BufferedImage icon) - { - super(data.getLocation(), icon); - setTooltip(data.getTooltip()); - } -} \ No newline at end of file + boolean contains(int itemId); +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTagsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTagsPlugin.java index 1cffe75379..4e56358252 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTagsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTagsPlugin.java @@ -75,13 +75,11 @@ import net.runelite.client.game.chatbox.ChatboxPanelManager; import net.runelite.client.input.MouseManager; import net.runelite.client.input.MouseWheelListener; import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDependency; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.banktags.tabs.TabInterface; import static net.runelite.client.plugins.banktags.tabs.TabInterface.FILTERED_CHARS; import net.runelite.client.plugins.banktags.tabs.TabSprites; import net.runelite.client.plugins.banktags.tabs.TagTab; -import net.runelite.client.plugins.cluescrolls.ClueScrollPlugin; import net.runelite.client.util.Text; @PluginDescriptor( @@ -89,7 +87,6 @@ import net.runelite.client.util.Text; description = "Enable tagging of bank items and searching of bank tags", tags = {"searching", "tagging"} ) -@PluginDependency(ClueScrollPlugin.class) public class BankTagsPlugin extends Plugin implements MouseWheelListener { public static final String CONFIG_GROUP = "banktags"; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/TagManager.java b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/TagManager.java index fe697034d0..3cfac27242 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/TagManager.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/TagManager.java @@ -27,24 +27,17 @@ package net.runelite.client.plugins.banktags; import com.google.common.base.Strings; import java.util.Collection; +import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; import javax.inject.Inject; import javax.inject.Singleton; -import net.runelite.api.ItemID; import net.runelite.client.config.ConfigManager; import net.runelite.client.game.ItemManager; import net.runelite.client.game.ItemVariationMapping; import static net.runelite.client.plugins.banktags.BankTagsPlugin.CONFIG_GROUP; -import net.runelite.client.plugins.cluescrolls.ClueScrollService; -import net.runelite.client.plugins.cluescrolls.clues.ClueScroll; -import net.runelite.client.plugins.cluescrolls.clues.CoordinateClue; -import net.runelite.client.plugins.cluescrolls.clues.EmoteClue; -import net.runelite.client.plugins.cluescrolls.clues.FairyRingClue; -import net.runelite.client.plugins.cluescrolls.clues.HotColdClue; -import net.runelite.client.plugins.cluescrolls.clues.MapClue; -import net.runelite.client.plugins.cluescrolls.clues.item.ItemRequirement; import net.runelite.client.util.Text; @Singleton @@ -53,17 +46,15 @@ public class TagManager static final String ITEM_KEY_PREFIX = "item_"; private final ConfigManager configManager; private final ItemManager itemManager; - private final ClueScrollService clueScrollService; + private final Map customTags = new HashMap<>(); @Inject private TagManager( final ItemManager itemManager, - final ConfigManager configManager, - final ClueScrollService clueScrollService) + final ConfigManager configManager) { this.itemManager = itemManager; this.configManager = configManager; - this.clueScrollService = clueScrollService; } String getTagString(int itemId, boolean variation) @@ -123,7 +114,8 @@ public class TagManager boolean findTag(int itemId, String search) { - if (search.equals("clue") && testClue(itemId)) + BankTag bankTag = customTags.get(search); + if (bankTag != null && bankTag.contains(itemId)) { return true; } @@ -194,38 +186,13 @@ public class TagManager return itemId; } - private boolean testClue(int itemId) + public void registerTag(String name, BankTag tag) { - ClueScroll c = clueScrollService.getClue(); + customTags.put(name, tag); + } - if (c == null) - { - return false; - } - - if (c instanceof EmoteClue) - { - EmoteClue emote = (EmoteClue) c; - - for (ItemRequirement ir : emote.getItemRequirements()) - { - if (ir.fulfilledBy(itemId)) - { - return true; - } - } - } - else if (c instanceof CoordinateClue || c instanceof HotColdClue || c instanceof FairyRingClue) - { - return itemId == ItemID.SPADE; - } - else if (c instanceof MapClue) - { - MapClue mapClue = (MapClue) c; - - return mapClue.getObjectId() == -1 && itemId == ItemID.SPADE; - } - - return false; + public void unregisterTag(String name) + { + customTags.remove(name); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/Role.java b/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/Role.java index a8fd8b656c..609322eac5 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/Role.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/Role.java @@ -32,13 +32,11 @@ import net.runelite.api.widgets.WidgetInfo; @Getter enum Role { - ATTACKER(WidgetInfo.BA_ATK_LISTEN_TEXT, WidgetInfo.BA_ATK_CALL_TEXT, WidgetInfo.BA_ATK_ROLE_TEXT, WidgetInfo.BA_ATK_ROLE_SPRITE), - DEFENDER(WidgetInfo.BA_DEF_LISTEN_TEXT, WidgetInfo.BA_DEF_CALL_TEXT, WidgetInfo.BA_DEF_ROLE_TEXT, WidgetInfo.BA_DEF_ROLE_SPRITE), - COLLECTOR(WidgetInfo.BA_COLL_LISTEN_TEXT, WidgetInfo.BA_COLL_CALL_TEXT, WidgetInfo.BA_COLL_ROLE_TEXT, WidgetInfo.BA_COLL_ROLE_SPRITE), - HEALER(WidgetInfo.BA_HEAL_LISTEN_TEXT, WidgetInfo.BA_HEAL_CALL_TEXT, WidgetInfo.BA_HEAL_ROLE_TEXT, WidgetInfo.BA_HEAL_ROLE_SPRITE); + ATTACKER(WidgetInfo.BA_ATK_ROLE_TEXT, WidgetInfo.BA_ATK_ROLE_SPRITE), + DEFENDER(WidgetInfo.BA_DEF_ROLE_TEXT, WidgetInfo.BA_DEF_ROLE_SPRITE), + COLLECTOR(WidgetInfo.BA_COLL_ROLE_TEXT, WidgetInfo.BA_COLL_ROLE_SPRITE), + HEALER(WidgetInfo.BA_HEAL_ROLE_TEXT, WidgetInfo.BA_HEAL_ROLE_SPRITE); - private final WidgetInfo listen; - private final WidgetInfo call; private final WidgetInfo roleText; private final WidgetInfo roleSprite; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsBrotherSlainOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsBrotherSlainOverlay.java index c7cdef0058..4e4eba0175 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsBrotherSlainOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsBrotherSlainOverlay.java @@ -34,6 +34,7 @@ import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG; import net.runelite.api.Varbits; import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.ui.FontManager; import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE; import net.runelite.client.ui.overlay.OverlayMenuEntry; import net.runelite.client.ui.overlay.OverlayPanel; @@ -82,6 +83,7 @@ public class BarrowsBrotherSlainOverlay extends OverlayPanel panelComponent.getChildren().add(LineComponent.builder() .left(brother.getName()) .right(slain) + .rightFont(FontManager.getDefaultFont()) .rightColor(brotherSlain ? Color.GREEN : Color.RED) .build()); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsConfig.java index dbb0d6d731..91cec5c09c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsConfig.java @@ -81,7 +81,7 @@ public interface BoostsConfig extends Config @ConfigItem( keyName = "displayNextBuffChange", - name = "Display next buff change", + name = "Next buff change", description = "Configures whether or not to display when the next buffed stat change will be", position = 4 ) @@ -92,7 +92,7 @@ public interface BoostsConfig extends Config @ConfigItem( keyName = "displayNextDebuffChange", - name = "Display next debuff change", + name = "Next debuff change", description = "Configures whether or not to display when the next debuffed stat change will be", position = 5 ) @@ -103,7 +103,7 @@ public interface BoostsConfig extends Config @ConfigItem( keyName = "boostThreshold", - name = "Boost amount threshold", + name = "Boost threshold", description = "The threshold at which boosted levels will be displayed in a different color. A value of 0 will disable the feature.", position = 6 ) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonConfig.java index 05ba93da2e..3ae29b0338 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonConfig.java @@ -51,7 +51,7 @@ public interface CannonConfig extends Config ) @ConfigItem( keyName = "lowWarningThreshold", - name = "Low Warning Threshold", + name = "Low warning threshold", description = "Configures the number of cannonballs remaining before a notification is sent.
Regardless of this value, a notification will still be sent when your cannon is empty.", position = 2 ) @@ -62,7 +62,7 @@ public interface CannonConfig extends Config @ConfigItem( keyName = "showInfobox", - name = "Show Cannonball infobox", + name = "Show cannonball infobox", description = "Configures whether to show the cannonballs in an infobox", position = 3 ) @@ -85,7 +85,7 @@ public interface CannonConfig extends Config @Alpha @ConfigItem( keyName = "highlightDoubleHitColor", - name = "Color of double hit spots", + name = "Double hit spots", description = "Configures the highlight color of double hit spots", position = 5 ) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonPlugin.java index 4d426ae9b6..1f9aeeaa25 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonPlugin.java @@ -304,7 +304,8 @@ public class CannonPlugin extends Plugin } if (event.getMessage().contains("You pick up the cannon") - || event.getMessage().contains("Your cannon has decayed. Speak to Nulodion to get a new one!")) + || event.getMessage().contains("Your cannon has decayed. Speak to Nulodion to get a new one!") + || event.getMessage().contains("Your cannon has been destroyed!")) { cannonPlaced = false; cballsLeft = 0; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonSpots.java b/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonSpots.java index f5b6f4a4a2..4596cd4e35 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonSpots.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonSpots.java @@ -49,7 +49,7 @@ enum CannonSpots DUST_DEVIL(new WorldPoint(3218, 9366, 0)), EARTH_WARRIOR(new WorldPoint(3120, 9987, 0)), ELDER_CHAOS_DRUID(new WorldPoint(3237, 3622, 0)), - ELVES(new WorldPoint(2044, 4635, 0), new WorldPoint(3278, 6098, 0)), + ELVES(new WorldPoint(3278, 6098, 0)), FIRE_GIANTS(new WorldPoint(2393, 9782, 0), new WorldPoint(2412, 9776, 0), new WorldPoint(2401, 9780, 0), new WorldPoint(3047, 10340, 0)), GREATER_DEMONS(new WorldPoint(1435, 10086, 2), new WorldPoint(3224, 10132, 0)), GREEN_DRAGON(new WorldPoint(3225, 10068, 0)), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsConfig.java index 4a8d46bd4e..a7213a33f1 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsConfig.java @@ -168,6 +168,17 @@ public interface ChatCommandsConfig extends Config @ConfigItem( position = 12, + keyName = "sw", + name = "SW Command", + description = "Configures whether the Soul Wars Zeal command is enabled
!sw" + ) + default boolean sw() + { + return true; + } + + @ConfigItem( + position = 13, keyName = "clearSingleWord", name = "Clear Single Word", description = "Enable hot key to clear single word at a time" @@ -178,7 +189,7 @@ public interface ChatCommandsConfig extends Config } @ConfigItem( - position = 13, + position = 14, keyName = "clearEntireChatBox", name = "Clear Chat Box", description = "Enable hotkey to clear entire chat box" diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java index 4259d0ee75..8c06945a66 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java @@ -127,6 +127,7 @@ public class ChatCommandsPlugin extends Plugin private static final String GC_COMMAND_STRING = "!gc"; private static final String DUEL_ARENA_COMMAND = "!duels"; private static final String LEAGUE_POINTS_COMMAND = "!lp"; + private static final String SOUL_WARS_ZEAL_COMMAND = "!sw"; @VisibleForTesting static final int ADV_LOG_EXPLOITS_TEXT_INDEX = 1; @@ -192,6 +193,7 @@ public class ChatCommandsPlugin extends Plugin chatCommandManager.registerCommandAsync(PB_COMMAND, this::personalBestLookup, this::personalBestSubmit); chatCommandManager.registerCommandAsync(GC_COMMAND_STRING, this::gambleCountLookup, this::gambleCountSubmit); chatCommandManager.registerCommandAsync(DUEL_ARENA_COMMAND, this::duelArenaLookup, this::duelArenaSubmit); + chatCommandManager.registerCommandAsync(SOUL_WARS_ZEAL_COMMAND, this::soulWarsZealLookup); } @Override @@ -216,6 +218,7 @@ public class ChatCommandsPlugin extends Plugin chatCommandManager.unregisterCommand(PB_COMMAND); chatCommandManager.unregisterCommand(GC_COMMAND_STRING); chatCommandManager.unregisterCommand(DUEL_ARENA_COMMAND); + chatCommandManager.unregisterCommand(SOUL_WARS_ZEAL_COMMAND); } @Provides @@ -663,7 +666,7 @@ public class ChatCommandsPlugin extends Plugin .append(ChatColorType.NORMAL) .append(" kill count: ") .append(ChatColorType.HIGHLIGHT) - .append(Integer.toString(kc)) + .append(String.format("%,d", kc)) .build(); log.debug("Setting response {}", response); @@ -745,15 +748,15 @@ public class ChatCommandsPlugin extends Plugin .append(ChatColorType.NORMAL) .append("Duel Arena wins: ") .append(ChatColorType.HIGHLIGHT) - .append(Integer.toString(wins)) + .append(String.format("%,d", wins)) .append(ChatColorType.NORMAL) .append(" losses: ") .append(ChatColorType.HIGHLIGHT) - .append(Integer.toString(losses)) + .append(String.format("%,d", losses)) .append(ChatColorType.NORMAL) .append(" streak: ") .append(ChatColorType.HIGHLIGHT) - .append(Integer.toString((winningStreak != 0 ? winningStreak : -losingStreak))) + .append(String.format("%,d", winningStreak != 0 ? winningStreak : -losingStreak)) .build(); log.debug("Setting response {}", response); @@ -954,7 +957,7 @@ public class ChatCommandsPlugin extends Plugin .append(ChatColorType.NORMAL) .append("Barbarian Assault High-level gambles: ") .append(ChatColorType.HIGHLIGHT) - .append(Integer.toString(gc)) + .append(String.format("%,d", gc)) .build(); log.debug("Setting response {}", response); @@ -1259,6 +1262,16 @@ public class ChatCommandsPlugin extends Plugin minigameLookup(chatMessage, HiscoreSkill.LAST_MAN_STANDING); } + private void soulWarsZealLookup(ChatMessage chatMessage, String message) + { + if (!config.sw()) + { + return; + } + + minigameLookup(chatMessage, HiscoreSkill.SOUL_WARS_ZEAL); + } + private void minigameLookup(ChatMessage chatMessage, HiscoreSkill minigame) { try @@ -1293,6 +1306,9 @@ public class ChatCommandsPlugin extends Plugin case LEAGUE_POINTS: hiscoreSkill = result.getLeaguePoints(); break; + case SOUL_WARS_ZEAL: + hiscoreSkill = result.getSoulWarsZeal(); + break; default: log.warn("error looking up {} score: not implemented", minigame.getName().toLowerCase()); return; @@ -1404,7 +1420,7 @@ public class ChatCommandsPlugin extends Plugin .append(ChatColorType.NORMAL) .append("Clue scroll (" + level + ")").append(": ") .append(ChatColorType.HIGHLIGHT) - .append(Integer.toString(quantity)); + .append(String.format("%,d", quantity)); if (rank != -1) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatfilter/ChatFilterConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatfilter/ChatFilterConfig.java index 2b9a45c2e9..0ad1071f9d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chatfilter/ChatFilterConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatfilter/ChatFilterConfig.java @@ -156,7 +156,7 @@ public interface ChatFilterConfig extends Config @ConfigItem( keyName = "maxRepeatedPublicChats", - name = "Max repeated public chats", + name = "Repeat filter", description = "Block player chat message if repeated this many times. 0 is off", position = 11 ) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatHistoryPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatHistoryPlugin.java index 8305c40bde..cc94cfc801 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatHistoryPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatHistoryPlugin.java @@ -56,8 +56,6 @@ import net.runelite.api.widgets.WidgetInfo; import static net.runelite.api.widgets.WidgetInfo.TO_CHILD; import static net.runelite.api.widgets.WidgetInfo.TO_GROUP; import net.runelite.client.callback.ClientThread; -import net.runelite.client.chat.ChatMessageManager; -import net.runelite.client.chat.QueuedMessage; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.input.KeyListener; @@ -82,7 +80,7 @@ public class ChatHistoryPlugin extends Plugin implements KeyListener private static final int CYCLE_HOTKEY = KeyEvent.VK_TAB; private static final int FRIENDS_MAX_SIZE = 5; - private Queue messageQueue; + private Queue messageQueue; private Deque friends; private String currentMessage = null; @@ -99,9 +97,6 @@ public class ChatHistoryPlugin extends Plugin implements KeyListener @Inject private KeyManager keyManager; - @Inject - private ChatMessageManager chatMessageManager; - @Provides ChatHistoryConfig getConfig(ConfigManager configManager) { @@ -111,6 +106,9 @@ public class ChatHistoryPlugin extends Plugin implements KeyListener @Override protected void startUp() { + // The client reuses MessageNodes after 100 chat messages of + // the same type, so this must be 100 (or maybe a map of + // size 100 evicting queues) messageQueue = EvictingQueue.create(100); friends = new ArrayDeque<>(FRIENDS_MAX_SIZE + 1); keyManager.registerKeyListener(this); @@ -140,11 +138,16 @@ public class ChatHistoryPlugin extends Plugin implements KeyListener return; } - QueuedMessage queuedMessage; - - while ((queuedMessage = messageQueue.poll()) != null) + for (MessageNode queuedMessage : messageQueue) { - chatMessageManager.queue(queuedMessage); + final MessageNode node = client.addChatMessage( + queuedMessage.getType(), + queuedMessage.getName(), + queuedMessage.getValue(), + queuedMessage.getSender(), + false); + node.setRuneLiteFormatMessage(queuedMessage.getRuneLiteFormatMessage()); + node.setTimestamp(queuedMessage.getTimestamp()); } return; @@ -171,19 +174,7 @@ public class ChatHistoryPlugin extends Plugin implements KeyListener case MODCHAT: case FRIENDSCHAT: case CONSOLE: - final QueuedMessage queuedMessage = QueuedMessage.builder() - .type(chatMessageType) - .name(chatMessage.getName()) - .sender(chatMessage.getSender()) - .value(nbsp(chatMessage.getMessage())) - .runeLiteFormattedMessage(nbsp(chatMessage.getMessageNode().getRuneLiteFormatMessage())) - .timestamp(chatMessage.getTimestamp()) - .build(); - - if (!messageQueue.contains(queuedMessage)) - { - messageQueue.offer(queuedMessage); - } + messageQueue.offer(chatMessage.getMessageNode()); } } @@ -348,21 +339,6 @@ public class ChatHistoryPlugin extends Plugin implements KeyListener clearMessageQueue(tab); } - /** - * Small hack to prevent plugins checking for specific messages to match - * @param message message - * @return message with nbsp - */ - private static String nbsp(final String message) - { - if (message != null) - { - return message.replace(' ', '\u00A0'); - } - - return null; - } - @Override public void keyPressed(KeyEvent e) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatnotifications/ChatNotificationsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatnotifications/ChatNotificationsConfig.java index 80044fc340..8c254a2c2a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chatnotifications/ChatNotificationsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatnotifications/ChatNotificationsConfig.java @@ -108,4 +108,15 @@ public interface ChatNotificationsConfig extends Config { return false; } + + @ConfigItem( + position = 7, + keyName = "notifyOnPM", + name = "Notify on private message", + description = "Notifies you whenever you receive a private message" + ) + default boolean notifyOnPM() + { + return false; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatnotifications/ChatNotificationsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatnotifications/ChatNotificationsPlugin.java index 4ccfd1925e..092b8cf376 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chatnotifications/ChatNotificationsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatnotifications/ChatNotificationsPlugin.java @@ -26,6 +26,7 @@ package net.runelite.client.plugins.chatnotifications; import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.MoreObjects; import com.google.common.base.Strings; import com.google.inject.Provides; import java.util.Arrays; @@ -76,7 +77,6 @@ public class ChatNotificationsPlugin extends Plugin //Custom Highlights private Pattern usernameMatcher = null; - private String usernameReplacer = ""; private Pattern highlightMatcher = null; @Provides @@ -165,6 +165,13 @@ public class ChatNotificationsPlugin extends Plugin notifier.notify(Text.removeFormattingTags(broadcast)); } break; + case PRIVATECHAT: + case MODPRIVATECHAT: + if (config.notifyOnPM()) + { + notifier.notify(Text.removeTags(chatMessage.getName()) + ": " + chatMessage.getMessage()); + } + break; case CONSOLE: // Don't notify for notification messages if (chatMessage.getName().equals(runeliteTitle)) @@ -181,15 +188,19 @@ public class ChatNotificationsPlugin extends Plugin .map(s -> s.isEmpty() ? "" : Pattern.quote(s)) .collect(Collectors.joining("[\u00a0\u0020]")); // space or nbsp usernameMatcher = Pattern.compile("\\b" + pattern + "\\b", Pattern.CASE_INSENSITIVE); - usernameReplacer = "" + username + ""; } if (config.highlightOwnName() && usernameMatcher != null) { - Matcher matcher = usernameMatcher.matcher(messageNode.getValue()); + final String message = messageNode.getValue(); + Matcher matcher = usernameMatcher.matcher(message); if (matcher.find()) { - messageNode.setValue(matcher.replaceAll(usernameReplacer)); + final int start = matcher.start(); + final String username = client.getLocalPlayer().getName(); + final String closeColor = MoreObjects.firstNonNull(getLastColor(message.substring(0, start)), ""); + final String replacement = "" + username + "" + closeColor; + messageNode.setValue(matcher.replaceAll(replacement)); update = true; if (config.notifyOnOwnName() && (chatMessage.getType() == ChatMessageType.PUBLICCHAT || chatMessage.getType() == ChatMessageType.PRIVATECHAT diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/ClueScrollPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/ClueScrollPlugin.java index 06dee6142a..d33a0e6b29 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/ClueScrollPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/ClueScrollPlugin.java @@ -96,7 +96,10 @@ import net.runelite.client.events.ConfigChanged; import net.runelite.client.events.OverlayMenuClicked; import net.runelite.client.game.ItemManager; import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDependency; import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.banktags.BankTagsPlugin; +import net.runelite.client.plugins.banktags.TagManager; import net.runelite.client.plugins.cluescrolls.clues.AnagramClue; import net.runelite.client.plugins.cluescrolls.clues.BeginnerMapClue; import net.runelite.client.plugins.cluescrolls.clues.CipherClue; @@ -117,6 +120,7 @@ import net.runelite.client.plugins.cluescrolls.clues.ObjectClueScroll; import net.runelite.client.plugins.cluescrolls.clues.SkillChallengeClue; import net.runelite.client.plugins.cluescrolls.clues.TextClueScroll; import net.runelite.client.plugins.cluescrolls.clues.ThreeStepCrypticClue; +import net.runelite.client.plugins.cluescrolls.clues.item.ItemRequirement; import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.ui.overlay.OverlayMenuEntry; import net.runelite.client.ui.overlay.OverlayUtil; @@ -131,6 +135,7 @@ import org.apache.commons.lang3.ArrayUtils; description = "Show answers to clue scroll riddles, anagrams, ciphers, and cryptic clues", tags = {"arrow", "hints", "world", "map", "coordinates", "emotes"} ) +@PluginDependency(BankTagsPlugin.class) @Slf4j public class ClueScrollPlugin extends Plugin { @@ -144,6 +149,7 @@ public class ClueScrollPlugin extends Plugin 13150, 9011, 13151, 9012 }; + private static final String CLUE_TAG_NAME = "clue"; @Getter private ClueScroll clue; @@ -191,6 +197,9 @@ public class ClueScrollPlugin extends Plugin @Inject private WorldMapPointManager worldMapPointManager; + @Inject + private TagManager tagManager; + @Inject @Named("developerMode") boolean developerMode; @@ -227,11 +236,13 @@ public class ClueScrollPlugin extends Plugin overlayManager.add(clueScrollEmoteOverlay); overlayManager.add(clueScrollWorldOverlay); overlayManager.add(clueScrollMusicOverlay); + tagManager.registerTag(CLUE_TAG_NAME, this::testClueTag); } @Override protected void shutDown() throws Exception { + tagManager.unregisterTag(CLUE_TAG_NAME); overlayManager.remove(clueScrollOverlay); overlayManager.remove(clueScrollEmoteOverlay); overlayManager.remove(clueScrollWorldOverlay); @@ -484,6 +495,10 @@ public class ClueScrollPlugin extends Plugin { resetClue(true); } + else if (state == GameState.HOPPING) + { + namedObjectCheckThisTick = true; + } } @Subscribe @@ -550,6 +565,7 @@ public class ClueScrollPlugin extends Plugin } // Load the current plane's tiles if a tick has elapsed since the player has changed planes + // or upon reaching a logged in state after hopping worlds if (namedObjectCheckThisTick) { namedObjectCheckThisTick = false; @@ -569,7 +585,7 @@ public class ClueScrollPlugin extends Plugin if (chatDialogClueItem != null && (chatDialogClueItem.getItemId() == ItemID.CLUE_SCROLL_BEGINNER || chatDialogClueItem.getItemId() == ItemID.CLUE_SCROLL_MASTER)) { - resetClue(true); + resetClue(false); } final Widget clueScrollText = client.getWidget(WidgetInfo.CLUE_SCROLL_TEXT); @@ -1109,4 +1125,38 @@ public class ClueScrollPlugin extends Plugin } return worldPoint; } + + private boolean testClueTag(int itemId) + { + ClueScroll c = clue; + if (c == null) + { + return false; + } + + if (c instanceof EmoteClue) + { + EmoteClue emote = (EmoteClue) c; + + for (ItemRequirement ir : emote.getItemRequirements()) + { + if (ir.fulfilledBy(itemId)) + { + return true; + } + } + } + else if (c instanceof CoordinateClue || c instanceof HotColdClue || c instanceof FairyRingClue) + { + return itemId == ItemID.SPADE; + } + else if (c instanceof MapClue) + { + MapClue mapClue = (MapClue) c; + + return mapClue.getObjectId() == -1 && itemId == ItemID.SPADE; + } + + return false; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java index 8d9a462118..5c0e093b6c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java @@ -205,6 +205,8 @@ public class CoordinateClue extends ClueScroll implements TextClueScroll, Locati .put(new WorldPoint(2484, 4016, 0), new CoordinateClueInfo("Northeast corner of the Island of Stone.", ARMADYLIAN_OR_BANDOSIAN_GUARD)) .put(new WorldPoint(2222, 3331, 0), new CoordinateClueInfo("Prifddinas, west of the Tower of Voices", ARMADYLIAN_OR_BANDOSIAN_GUARD)) .put(new WorldPoint(3560, 3987, 0), new CoordinateClueInfo("Lithkren. Digsite pendant teleport if unlocked, otherwise take rowboat from west of Mushroom Meadow Mushtree.", ARMADYLIAN_OR_BANDOSIAN_GUARD)) + .put(new WorldPoint(2318, 2954, 0), new CoordinateClueInfo("North-east corner of the Isle of Souls.", ARMADYLIAN_OR_BANDOSIAN_GUARD)) + .put(new WorldPoint(2094, 2889, 0), new CoordinateClueInfo("West side of the Isle of Souls.", ARMADYLIAN_OR_BANDOSIAN_GUARD)) // Master .put(new WorldPoint(2178, 3209, 0), new CoordinateClueInfo("South of Iorwerth Camp.", BRASSICAN_MAGE)) .put(new WorldPoint(2155, 3100, 0), new CoordinateClueInfo("South of Port Tyras (BJS if 76 Agility).", BRASSICAN_MAGE)) @@ -227,7 +229,7 @@ public class CoordinateClue extends ClueScroll implements TextClueScroll, Locati .put(new WorldPoint(2202, 3825, 0), new CoordinateClueInfo("Pirates' Cove, between Lunar Isle and Rellekka.", ANCIENT_WIZARDS)) .put(new WorldPoint(1761, 3853, 0), new CoordinateClueInfo("Arceuus essence mine (CIS).", BRASSICAN_MAGE)) .put(new WorldPoint(2090, 3863, 0), new CoordinateClueInfo("South of Lunar Isle, west of Astral altar.", ANCIENT_WIZARDS)) - .put(new WorldPoint(1442, 3878, 0), new CoordinateClueInfo("Sulphur Mine.", BRASSICAN_MAGE)) + .put(new WorldPoint(1442, 3878, 0), new CoordinateClueInfo("Northern area of the Lovakengj Sulphur Mine. Facemask or Slayer Helmet recommended.", BRASSICAN_MAGE)) .put(new WorldPoint(3380, 3929, 0), new CoordinateClueInfo("Wilderness. Near Volcano.", ANCIENT_WIZARDS)) .put(new WorldPoint(3188, 3939, 0), new CoordinateClueInfo("Wilderness. Resource Area.", BRASSICAN_MAGE)) .put(new WorldPoint(3304, 3941, 0), new CoordinateClueInfo("Wilderness. East of Rogues' Castle.", ANCIENT_WIZARDS)) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CrypticClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CrypticClue.java index 9360b6aa33..b263571fee 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CrypticClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CrypticClue.java @@ -105,7 +105,7 @@ public class CrypticClue extends ClueScroll implements TextClueScroll, NpcClueSc new CrypticClue("A crate found in the tower of a church is your next location.", CRATE_357, new WorldPoint(2612, 3304, 1), "Climb the ladder and search the crates on the first floor in the Church in Ardougne."), new CrypticClue("Covered in shadows, the centre of the circle is where you will find the answer.", new WorldPoint(3488, 3289, 0), "Dig in the centre of Mort'ton, where the roads intersect."), new CrypticClue("I lie lonely and forgotten in mid wilderness, where the dead rise from their beds. Feel free to quarrel and wind me up, and dig while you shoot their heads.", new WorldPoint(3174, 3663, 0), "Directly under the crossbow respawn in the Graveyard of Shadows in level 18 Wilderness."), - new CrypticClue("In the city where merchants are said to have lived, talk to a man with a splendid cape, but a hat dropped by goblins.", "Head chef", new WorldPoint(3143, 3445, 0), "Talk to the Head chef in Cooks' Guild west of Varrock. You will need a chef hat or cooking cape to enter."), + new CrypticClue("In the city where merchants are said to have lived, talk to a man with a splendid cape, but a hat dropped by goblins.", "Head chef", new WorldPoint(3143, 3445, 0), "Talk to the Head chef in Cooks' Guild west of Varrock. You will need a chef's hat, Varrock armour 3 or 4, or the Cooking cape to enter."), new CrypticClue("The mother of the reptilian sacrifice.", "Zul-Cheray", new WorldPoint(2204, 3050, 0), "Talk to Zul-Cheray in a house near the sacrificial boat at Zul-Andra."), new CrypticClue("I watch the sea. I watch you fish. I watch your tree.", "Ellena", new WorldPoint(2860, 3431, 0), "Speak to Ellena at Catherby fruit tree patch."), new CrypticClue("Dig between some ominous stones in Falador.", new WorldPoint(3040, 3399, 0), "Three standing stones inside a walled area. East of the northern Falador gate."), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java index d18aa4d6f2..ab3ac38982 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java @@ -45,6 +45,7 @@ import net.runelite.api.coords.LocalPoint; import net.runelite.api.coords.WorldPoint; import static net.runelite.client.plugins.cluescrolls.ClueScrollOverlay.TITLED_CONTENT_COLOR; import net.runelite.client.plugins.cluescrolls.ClueScrollPlugin; +import static net.runelite.client.plugins.cluescrolls.clues.Enemy.*; import net.runelite.client.plugins.cluescrolls.clues.emote.Emote; import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.*; import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.BULL_ROARER; @@ -53,7 +54,7 @@ import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.*; import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.SHANTAY_PASS; import net.runelite.client.plugins.cluescrolls.clues.item.ItemRequirement; import static net.runelite.client.plugins.cluescrolls.clues.item.ItemRequirements.*; -import static net.runelite.client.plugins.cluescrolls.clues.Enemy.*; +import net.runelite.client.ui.FontManager; import net.runelite.client.ui.overlay.OverlayUtil; import net.runelite.client.ui.overlay.components.LineComponent; import net.runelite.client.ui.overlay.components.PanelComponent; @@ -154,11 +155,11 @@ public class EmoteClue extends ClueScroll implements TextClueScroll, LocationClu new EmoteClue("Slap your head in the centre of the Kourend catacombs. Beware of double agents! Equip the arclight and the amulet of the damned.", "Kourend catacombs", CENTRE_OF_THE_CATACOMBS_OF_KOUREND, new WorldPoint(1663, 10045, 0), DOUBLE_AGENT_141, SLAP_HEAD, item(ARCLIGHT), any("Amulet of the damned", item(AMULET_OF_THE_DAMNED), item(AMULET_OF_THE_DAMNED_FULL))), new EmoteClue("Spin at the crossroads north of Rimmington. Equip a green gnome hat, cream gnome top and leather chaps.", "Rimmington", ROAD_JUNCTION_NORTH_OF_RIMMINGTON, new WorldPoint(2981, 3276, 0), SPIN, item(GREEN_HAT), item(CREAM_ROBE_TOP), item(LEATHER_CHAPS)), new EmoteClue("Spin in Draynor Manor by the fountain. Equip an iron platebody, studded leather chaps and a bronze full helmet.", "Draynor Manor", DRAYNOR_MANOR_BY_THE_FOUNTAIN, new WorldPoint(3088, 3336, 0), SPIN, item(IRON_PLATEBODY), item(STUDDED_CHAPS), item(BRONZE_FULL_HELM)), - new EmoteClue("Spin in front of the Soul altar. Beware of double agents! Equip a dragon pickaxe, helm of neitiznot and a pair of rune boots.", "Soul altar", SOUL_ALTAR, new WorldPoint(1815, 3856, 0), DOUBLE_AGENT_141, SPIN, any("Dragon or Crystal pickaxe", item(DRAGON_PICKAXE), item(DRAGON_PICKAXE_12797), item(INFERNAL_PICKAXE), item(INFERNAL_PICKAXE_UNCHARGED), item(DRAGON_PICKAXE_OR), item(CRYSTAL_PICKAXE), item(CRYSTAL_PICKAXE_INACTIVE)), item(HELM_OF_NEITIZNOT), item(RUNE_BOOTS)), + new EmoteClue("Spin in front of the Soul altar. Beware of double agents! Equip a dragon pickaxe, helm of neitiznot and a pair of rune boots.", "Soul altar", SOUL_ALTAR, new WorldPoint(1815, 3856, 0), DOUBLE_AGENT_141, SPIN, any("Dragon or Crystal pickaxe", item(DRAGON_PICKAXE), item(DRAGON_PICKAXE_12797), item(INFERNAL_PICKAXE), item(INFERNAL_PICKAXE_UNCHARGED), item(DRAGON_PICKAXE_OR), item(DRAGON_PICKAXE_OR_25376), item(CRYSTAL_PICKAXE), item(CRYSTAL_PICKAXE_INACTIVE), item(INFERNAL_PICKAXE_OR), item(INFERNAL_PICKAXE_UNCHARGED_25369)), item(HELM_OF_NEITIZNOT), item(RUNE_BOOTS)), new EmoteClue("Spin in the Varrock Castle courtyard. Equip a black axe, a coif and a ruby ring.", "Varrock Castle", OUTSIDE_VARROCK_PALACE_COURTYARD, new WorldPoint(3213, 3463, 0), SPIN, item(BLACK_AXE), item(COIF), item(RUBY_RING)), new EmoteClue("Spin in West Ardougne Church. Equip a dragon spear and red dragonhide chaps.", "West Ardougne Church", CHAPEL_IN_WEST_ARDOUGNE, new WorldPoint(2530, 3290, 0), SPIN, item(DRAGON_SPEAR), item(RED_DHIDE_CHAPS)), new EmoteClue("Spin on the bridge by the Barbarian Village. Salute before you talk to me. Equip purple gloves, a steel kiteshield and a mithril full helmet.", "Barbarian Village", EAST_OF_THE_BARBARIAN_VILLAGE_BRIDGE, new WorldPoint(3105, 3420, 0), SPIN, SALUTE, item(PURPLE_GLOVES), item(STEEL_KITESHIELD), item(MITHRIL_FULL_HELM)), - new EmoteClue("Stamp in the Enchanted valley west of the waterfall. Beware of double agents! Equip a dragon axe.", "Enchanted Valley (BKQ)", NORTHWESTERN_CORNER_OF_THE_ENCHANTED_VALLEY, new WorldPoint(3030, 4522, 0), DOUBLE_AGENT_141, STAMP, any("Dragon or Crystal axe", item(DRAGON_AXE), item(CRYSTAL_AXE), item(CRYSTAL_AXE_INACTIVE), item(INFERNAL_AXE), item(INFERNAL_AXE_UNCHARGED))), + new EmoteClue("Stamp in the Enchanted valley west of the waterfall. Beware of double agents! Equip a dragon axe.", "Enchanted Valley (BKQ)", NORTHWESTERN_CORNER_OF_THE_ENCHANTED_VALLEY, new WorldPoint(3030, 4522, 0), DOUBLE_AGENT_141, STAMP, any("Dragon or Crystal axe", item(DRAGON_AXE), item(DRAGON_AXE_OR), item(CRYSTAL_AXE), item(CRYSTAL_AXE_INACTIVE), item(INFERNAL_AXE), item(INFERNAL_AXE_UNCHARGED), item(INFERNAL_AXE_OR), item(INFERNAL_AXE_UNCHARGED_25371))), new EmoteClue("Think in middle of the wheat field by the Lumbridge mill. Equip a blue gnome robetop, a turquoise gnome robe bottom and an oak shortbow.", "Lumbridge mill", WHEAT_FIELD_NEAR_THE_LUMBRIDGE_WINDMILL, new WorldPoint(3159, 3298, 0), THINK, item(BLUE_ROBE_TOP), item(TURQUOISE_ROBE_BOTTOMS), item(OAK_SHORTBOW)), new EmoteClue("Think in the centre of the Observatory. Spin before you talk to me. Equip a mithril chain body, green dragonhide chaps and a ruby amulet.", "Observatory", OBSERVATORY, new WorldPoint(2439, 3161, 0), THINK, SPIN, item(MITHRIL_CHAINBODY), item(GREEN_DHIDE_CHAPS), item(RUBY_AMULET)), new EmoteClue("Wave along the south fence of the Lumber Yard. Equip a hard leather body, leather chaps and a bronze axe.", "Lumber Yard", NEAR_THE_SAWMILL_OPERATORS_BOOTH, new WorldPoint(3307, 3491, 0), WAVE, item(HARDLEATHER_BODY), item(LEATHER_CHAPS), item(BRONZE_AXE)), @@ -258,6 +259,7 @@ public class EmoteClue extends ClueScroll implements TextClueScroll, LocationClu panelComponent.getChildren().add(LineComponent.builder() .left("STASH Unit:") .right(stashUnitBuilt ? UNICODE_CHECK_MARK : UNICODE_BALLOT_X) + .rightFont(FontManager.getDefaultFont()) .rightColor(stashUnitBuilt ? Color.GREEN : Color.RED) .build()); } @@ -292,6 +294,7 @@ public class EmoteClue extends ClueScroll implements TextClueScroll, LocationClu .left(requirement.getCollectiveName(client)) .leftColor(TITLED_CONTENT_COLOR) .right(combinedFulfilled ? UNICODE_CHECK_MARK : UNICODE_BALLOT_X) + .rightFont(FontManager.getDefaultFont()) .rightColor(equipmentFulfilled ? Color.GREEN : (combinedFulfilled ? Color.ORANGE : Color.RED)) .build()); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/FaloTheBardClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/FaloTheBardClue.java index 77910ab61d..c208d5238f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/FaloTheBardClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/FaloTheBardClue.java @@ -41,6 +41,7 @@ import net.runelite.client.plugins.cluescrolls.clues.item.AnyRequirementCollecti import net.runelite.client.plugins.cluescrolls.clues.item.ItemRequirement; import net.runelite.client.plugins.cluescrolls.clues.item.RangeItemRequirement; import net.runelite.client.plugins.cluescrolls.clues.item.SingleItemRequirement; +import net.runelite.client.ui.FontManager; import net.runelite.client.ui.overlay.OverlayUtil; import net.runelite.client.ui.overlay.components.LineComponent; import net.runelite.client.ui.overlay.components.PanelComponent; @@ -50,10 +51,10 @@ import net.runelite.client.ui.overlay.components.TitleComponent; public class FaloTheBardClue extends ClueScroll implements TextClueScroll, NpcClueScroll { private static final List CLUES = ImmutableList.of( - new FaloTheBardClue("A blood red weapon, a strong curved sword, found on the island of primate lords.", item(DRAGON_SCIMITAR)), + new FaloTheBardClue("A blood red weapon, a strong curved sword, found on the island of primate lords.", any("Dragon scimitar", item(DRAGON_SCIMITAR), item(DRAGON_SCIMITAR_OR))), new FaloTheBardClue("A book that preaches of some great figure, lending strength, might and vigour.", any("Any god book (must be complete)", item(HOLY_BOOK), item(BOOK_OF_BALANCE), item(UNHOLY_BOOK), item(BOOK_OF_LAW), item(BOOK_OF_WAR), item(BOOK_OF_DARKNESS))), new FaloTheBardClue("A bow of elven craft was made, it shimmers bright, but will soon fade.", any("Crystal Bow", item(CRYSTAL_BOW), item(CRYSTAL_BOW_24123))), - new FaloTheBardClue("A fiery axe of great inferno, when you use it, you'll wonder where the logs go.", item(INFERNAL_AXE)), + new FaloTheBardClue("A fiery axe of great inferno, when you use it, you'll wonder where the logs go.", any("Infernal axe", item(INFERNAL_AXE), item(INFERNAL_AXE_OR))), new FaloTheBardClue("A mark used to increase one's grace, found atop a seer's place.", item(MARK_OF_GRACE)), new FaloTheBardClue("A molten beast with fiery breath, you acquire these with its death.", item(LAVA_DRAGON_BONES)), new FaloTheBardClue("A shiny helmet of flight, to obtain this with melee, struggle you might.", item(ARMADYL_HELMET)), @@ -134,6 +135,7 @@ public class FaloTheBardClue extends ClueScroll implements TextClueScroll, NpcCl .left(requirement.getCollectiveName(plugin.getClient())) .leftColor(TITLED_CONTENT_COLOR) .right(inventoryFulfilled ? "\u2713" : "\u2717") + .rightFont(FontManager.getDefaultFont()) .rightColor(inventoryFulfilled ? Color.GREEN : Color.RED) .build()); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/MapClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/MapClue.java index 2800580294..fa32e1533b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/MapClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/MapClue.java @@ -79,7 +79,7 @@ public class MapClue extends ClueScroll implements ObjectClueScroll new MapClue(CLUE_SCROLL_MEDIUM_7294, new WorldPoint(2666, 3562, 0), "Between Seers' Village and Rellekka. South-west of Fairy ring CJR"), new MapClue(CLUE_SCROLL_HARD, new WorldPoint(3309, 3503, 0), CRATE_2620, "A crate in the Lumber Yard, north-east of Varrock."), new MapClue(CLUE_SCROLL_HARD_2729, new WorldPoint(3190, 3963, 0), "Behind the Magic axe hut in level 56 Wilderness."), - new MapClue(CLUE_SCROLL_HARD_3520, new WorldPoint(2615, 3078, 0), "Yanille anvils, south of the bank."), + new MapClue(CLUE_SCROLL_HARD_3520, new WorldPoint(2615, 3078, 0), "Yanille anvils, south of the bank. You can dig from inside the building."), new MapClue(CLUE_SCROLL_HARD_3522, new WorldPoint(2488, 3308, 0), "In the western section of West Ardougne."), new MapClue(CLUE_SCROLL_HARD_3524, new WorldPoint(2457, 3182, 0), CRATE_18506, "In a crate by the stairs to the Observatory Dungeon."), new MapClue(CLUE_SCROLL_HARD_3525, new WorldPoint(3026, 3628, 0), CRATE_354, "In a crate at the Dark Warriors' Fortress in level 14 Wilderness."), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/SkillChallengeClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/SkillChallengeClue.java index 4f7adb6db6..41f6f283cb 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/SkillChallengeClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/SkillChallengeClue.java @@ -25,6 +25,11 @@ package net.runelite.client.plugins.cluescrolls.clues; import com.google.common.collect.ImmutableSet; +import java.awt.Color; +import java.awt.Graphics2D; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; @@ -34,25 +39,21 @@ import net.runelite.api.ItemID; import net.runelite.api.NPC; import net.runelite.api.Point; import net.runelite.api.TileObject; +import static net.runelite.client.plugins.cluescrolls.ClueScrollOverlay.TITLED_CONTENT_COLOR; import net.runelite.client.plugins.cluescrolls.ClueScrollPlugin; import static net.runelite.client.plugins.cluescrolls.ClueScrollWorldOverlay.CLICKBOX_BORDER_COLOR; import static net.runelite.client.plugins.cluescrolls.ClueScrollWorldOverlay.CLICKBOX_FILL_COLOR; import static net.runelite.client.plugins.cluescrolls.ClueScrollWorldOverlay.CLICKBOX_HOVER_BORDER_COLOR; +import static net.runelite.client.plugins.cluescrolls.ClueScrollWorldOverlay.IMAGE_Z_OFFSET; import net.runelite.client.plugins.cluescrolls.clues.item.AnyRequirementCollection; -import static net.runelite.client.plugins.cluescrolls.clues.item.ItemRequirements.*; import net.runelite.client.plugins.cluescrolls.clues.item.ItemRequirement; +import static net.runelite.client.plugins.cluescrolls.clues.item.ItemRequirements.*; import net.runelite.client.plugins.cluescrolls.clues.item.SingleItemRequirement; +import net.runelite.client.ui.FontManager; import net.runelite.client.ui.overlay.OverlayUtil; import net.runelite.client.ui.overlay.components.LineComponent; import net.runelite.client.ui.overlay.components.PanelComponent; import net.runelite.client.ui.overlay.components.TitleComponent; -import java.awt.Color; -import java.awt.Graphics2D; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import static net.runelite.client.plugins.cluescrolls.ClueScrollOverlay.TITLED_CONTENT_COLOR; -import static net.runelite.client.plugins.cluescrolls.ClueScrollWorldOverlay.IMAGE_Z_OFFSET; @Getter public class SkillChallengeClue extends ClueScroll implements NpcClueScroll, NamedObjectClueScroll @@ -79,8 +80,11 @@ public class SkillChallengeClue extends ClueScroll implements NpcClueScroll, Nam item(ItemID.DRAGON_PICKAXE), item(ItemID.DRAGON_PICKAXE_12797), item(ItemID.DRAGON_PICKAXE_OR), + item(ItemID.DRAGON_PICKAXE_OR_25376), item(ItemID.INFERNAL_PICKAXE), + item(ItemID.INFERNAL_PICKAXE_OR), item(ItemID.INFERNAL_PICKAXE_UNCHARGED), + item(ItemID.INFERNAL_PICKAXE_UNCHARGED_25369), item(ItemID.GILDED_PICKAXE), item(ItemID._3RD_AGE_PICKAXE), item(ItemID.CRYSTAL_PICKAXE) @@ -95,8 +99,11 @@ public class SkillChallengeClue extends ClueScroll implements NpcClueScroll, Nam item(ItemID.ADAMANT_AXE), item(ItemID.RUNE_AXE), item(ItemID.DRAGON_AXE), + item(ItemID.DRAGON_AXE_OR), item(ItemID.INFERNAL_AXE), + item(ItemID.INFERNAL_AXE_OR), item(ItemID.INFERNAL_AXE_UNCHARGED), + item(ItemID.INFERNAL_AXE_UNCHARGED_25371), item(ItemID.GILDED_AXE), item(ItemID._3RD_AGE_AXE), item(ItemID.CRYSTAL_AXE) @@ -106,8 +113,11 @@ public class SkillChallengeClue extends ClueScroll implements NpcClueScroll, Nam item(ItemID.HARPOON), item(ItemID.BARBTAIL_HARPOON), item(ItemID.DRAGON_HARPOON), + item(ItemID.DRAGON_HARPOON_OR), item(ItemID.INFERNAL_HARPOON), + item(ItemID.INFERNAL_HARPOON_OR), item(ItemID.INFERNAL_HARPOON_UNCHARGED), + item(ItemID.INFERNAL_HARPOON_UNCHARGED_25367), item(ItemID.CRYSTAL_HARPOON) ); @@ -162,12 +172,12 @@ public class SkillChallengeClue extends ClueScroll implements NpcClueScroll, Nam new SkillChallengeClue("Burn a redwood log.", item(ItemID.REDWOOD_LOGS), item(ItemID.TINDERBOX)), new SkillChallengeClue("Complete a lap of Rellekka's Rooftop Agility Course", "complete a lap of the rellekka rooftop agility course whilst sporting the finest amount of grace.", true, all("A full Graceful set", - any("", item(ItemID.GRACEFUL_HOOD), item(ItemID.GRACEFUL_HOOD_11851), item(ItemID.GRACEFUL_HOOD_13579), item(ItemID.GRACEFUL_HOOD_13580), item(ItemID.GRACEFUL_HOOD_13591), item(ItemID.GRACEFUL_HOOD_13592), item(ItemID.GRACEFUL_HOOD_13603), item(ItemID.GRACEFUL_HOOD_13604), item(ItemID.GRACEFUL_HOOD_13615), item(ItemID.GRACEFUL_HOOD_13616), item(ItemID.GRACEFUL_HOOD_13627), item(ItemID.GRACEFUL_HOOD_13628), item(ItemID.GRACEFUL_HOOD_13667), item(ItemID.GRACEFUL_HOOD_13668), item(ItemID.GRACEFUL_HOOD_21061), item(ItemID.GRACEFUL_HOOD_21063), item(ItemID.GRACEFUL_HOOD_24743), item(ItemID.GRACEFUL_HOOD_24745)), - any("", item(ItemID.GRACEFUL_CAPE), item(ItemID.GRACEFUL_CAPE_11853), item(ItemID.GRACEFUL_CAPE_13581), item(ItemID.GRACEFUL_CAPE_13582), item(ItemID.GRACEFUL_CAPE_13593), item(ItemID.GRACEFUL_CAPE_13594), item(ItemID.GRACEFUL_CAPE_13605), item(ItemID.GRACEFUL_CAPE_13606), item(ItemID.GRACEFUL_CAPE_13617), item(ItemID.GRACEFUL_CAPE_13618), item(ItemID.GRACEFUL_CAPE_13629), item(ItemID.GRACEFUL_CAPE_13630), item(ItemID.GRACEFUL_CAPE_13669), item(ItemID.GRACEFUL_CAPE_13670), item(ItemID.GRACEFUL_CAPE_21064), item(ItemID.GRACEFUL_CAPE_21066), item(ItemID.GRACEFUL_CAPE_24746), item(ItemID.GRACEFUL_CAPE_24748), item(ItemID.AGILITY_CAPE), item(ItemID.AGILITY_CAPE_13340), item(ItemID.AGILITY_CAPET), item(ItemID.AGILITY_CAPET_13341), item(ItemID.MAX_CAPE), item(ItemID.MAX_CAPE_13342)), - any("", item(ItemID.GRACEFUL_TOP), item(ItemID.GRACEFUL_TOP_11855), item(ItemID.GRACEFUL_TOP_13583), item(ItemID.GRACEFUL_TOP_13584), item(ItemID.GRACEFUL_TOP_13595), item(ItemID.GRACEFUL_TOP_13596), item(ItemID.GRACEFUL_TOP_13607), item(ItemID.GRACEFUL_TOP_13608), item(ItemID.GRACEFUL_TOP_13619), item(ItemID.GRACEFUL_TOP_13620), item(ItemID.GRACEFUL_TOP_13631), item(ItemID.GRACEFUL_TOP_13632), item(ItemID.GRACEFUL_TOP_13671), item(ItemID.GRACEFUL_TOP_13672), item(ItemID.GRACEFUL_TOP_21067), item(ItemID.GRACEFUL_TOP_21069), item(ItemID.GRACEFUL_TOP_24749), item(ItemID.GRACEFUL_TOP_24751)), - any("", item(ItemID.GRACEFUL_LEGS), item(ItemID.GRACEFUL_LEGS_11857), item(ItemID.GRACEFUL_LEGS_13585), item(ItemID.GRACEFUL_LEGS_13586), item(ItemID.GRACEFUL_LEGS_13597), item(ItemID.GRACEFUL_LEGS_13598), item(ItemID.GRACEFUL_LEGS_13609), item(ItemID.GRACEFUL_LEGS_13610), item(ItemID.GRACEFUL_LEGS_13621), item(ItemID.GRACEFUL_LEGS_13622), item(ItemID.GRACEFUL_LEGS_13633), item(ItemID.GRACEFUL_LEGS_13634), item(ItemID.GRACEFUL_LEGS_13673), item(ItemID.GRACEFUL_LEGS_13674), item(ItemID.GRACEFUL_LEGS_21070), item(ItemID.GRACEFUL_LEGS_21072), item(ItemID.GRACEFUL_LEGS_24752), item(ItemID.GRACEFUL_LEGS_24754)), - any("", item(ItemID.GRACEFUL_GLOVES), item(ItemID.GRACEFUL_GLOVES_11859), item(ItemID.GRACEFUL_GLOVES_13587), item(ItemID.GRACEFUL_GLOVES_13588), item(ItemID.GRACEFUL_GLOVES_13599), item(ItemID.GRACEFUL_GLOVES_13600), item(ItemID.GRACEFUL_GLOVES_13611), item(ItemID.GRACEFUL_GLOVES_13612), item(ItemID.GRACEFUL_GLOVES_13623), item(ItemID.GRACEFUL_GLOVES_13624), item(ItemID.GRACEFUL_GLOVES_13635), item(ItemID.GRACEFUL_GLOVES_13636), item(ItemID.GRACEFUL_GLOVES_13675), item(ItemID.GRACEFUL_GLOVES_13676), item(ItemID.GRACEFUL_GLOVES_21073), item(ItemID.GRACEFUL_GLOVES_21075), item(ItemID.GRACEFUL_GLOVES_24755), item(ItemID.GRACEFUL_GLOVES_24757)), - any("", item(ItemID.GRACEFUL_BOOTS), item(ItemID.GRACEFUL_BOOTS_11861), item(ItemID.GRACEFUL_BOOTS_13589), item(ItemID.GRACEFUL_BOOTS_13590), item(ItemID.GRACEFUL_BOOTS_13601), item(ItemID.GRACEFUL_BOOTS_13602), item(ItemID.GRACEFUL_BOOTS_13613), item(ItemID.GRACEFUL_BOOTS_13614), item(ItemID.GRACEFUL_BOOTS_13625), item(ItemID.GRACEFUL_BOOTS_13626), item(ItemID.GRACEFUL_BOOTS_13637), item(ItemID.GRACEFUL_BOOTS_13638), item(ItemID.GRACEFUL_BOOTS_13677), item(ItemID.GRACEFUL_BOOTS_13678), item(ItemID.GRACEFUL_BOOTS_21076), item(ItemID.GRACEFUL_BOOTS_21078), item(ItemID.GRACEFUL_BOOTS_24758), item(ItemID.GRACEFUL_BOOTS_24760)))), + any("", item(ItemID.GRACEFUL_HOOD), item(ItemID.GRACEFUL_HOOD_11851), item(ItemID.GRACEFUL_HOOD_13579), item(ItemID.GRACEFUL_HOOD_13580), item(ItemID.GRACEFUL_HOOD_13591), item(ItemID.GRACEFUL_HOOD_13592), item(ItemID.GRACEFUL_HOOD_13603), item(ItemID.GRACEFUL_HOOD_13604), item(ItemID.GRACEFUL_HOOD_13615), item(ItemID.GRACEFUL_HOOD_13616), item(ItemID.GRACEFUL_HOOD_13627), item(ItemID.GRACEFUL_HOOD_13628), item(ItemID.GRACEFUL_HOOD_13667), item(ItemID.GRACEFUL_HOOD_13668), item(ItemID.GRACEFUL_HOOD_21061), item(ItemID.GRACEFUL_HOOD_21063), item(ItemID.GRACEFUL_HOOD_24743), item(ItemID.GRACEFUL_HOOD_24745), item(ItemID.GRACEFUL_HOOD_25069), item(ItemID.GRACEFUL_HOOD_25071)), + any("", item(ItemID.GRACEFUL_CAPE), item(ItemID.GRACEFUL_CAPE_11853), item(ItemID.GRACEFUL_CAPE_13581), item(ItemID.GRACEFUL_CAPE_13582), item(ItemID.GRACEFUL_CAPE_13593), item(ItemID.GRACEFUL_CAPE_13594), item(ItemID.GRACEFUL_CAPE_13605), item(ItemID.GRACEFUL_CAPE_13606), item(ItemID.GRACEFUL_CAPE_13617), item(ItemID.GRACEFUL_CAPE_13618), item(ItemID.GRACEFUL_CAPE_13629), item(ItemID.GRACEFUL_CAPE_13630), item(ItemID.GRACEFUL_CAPE_13669), item(ItemID.GRACEFUL_CAPE_13670), item(ItemID.GRACEFUL_CAPE_21064), item(ItemID.GRACEFUL_CAPE_21066), item(ItemID.GRACEFUL_CAPE_24746), item(ItemID.GRACEFUL_CAPE_24748), item(ItemID.GRACEFUL_CAPE_25072), item(ItemID.GRACEFUL_CAPE_25074), item(ItemID.AGILITY_CAPE), item(ItemID.AGILITY_CAPE_13340), item(ItemID.AGILITY_CAPET), item(ItemID.AGILITY_CAPET_13341), item(ItemID.MAX_CAPE), item(ItemID.MAX_CAPE_13342)), + any("", item(ItemID.GRACEFUL_TOP), item(ItemID.GRACEFUL_TOP_11855), item(ItemID.GRACEFUL_TOP_13583), item(ItemID.GRACEFUL_TOP_13584), item(ItemID.GRACEFUL_TOP_13595), item(ItemID.GRACEFUL_TOP_13596), item(ItemID.GRACEFUL_TOP_13607), item(ItemID.GRACEFUL_TOP_13608), item(ItemID.GRACEFUL_TOP_13619), item(ItemID.GRACEFUL_TOP_13620), item(ItemID.GRACEFUL_TOP_13631), item(ItemID.GRACEFUL_TOP_13632), item(ItemID.GRACEFUL_TOP_13671), item(ItemID.GRACEFUL_TOP_13672), item(ItemID.GRACEFUL_TOP_21067), item(ItemID.GRACEFUL_TOP_21069), item(ItemID.GRACEFUL_TOP_24749), item(ItemID.GRACEFUL_TOP_24751), item(ItemID.GRACEFUL_TOP_25075), item(ItemID.GRACEFUL_TOP_25077)), + any("", item(ItemID.GRACEFUL_LEGS), item(ItemID.GRACEFUL_LEGS_11857), item(ItemID.GRACEFUL_LEGS_13585), item(ItemID.GRACEFUL_LEGS_13586), item(ItemID.GRACEFUL_LEGS_13597), item(ItemID.GRACEFUL_LEGS_13598), item(ItemID.GRACEFUL_LEGS_13609), item(ItemID.GRACEFUL_LEGS_13610), item(ItemID.GRACEFUL_LEGS_13621), item(ItemID.GRACEFUL_LEGS_13622), item(ItemID.GRACEFUL_LEGS_13633), item(ItemID.GRACEFUL_LEGS_13634), item(ItemID.GRACEFUL_LEGS_13673), item(ItemID.GRACEFUL_LEGS_13674), item(ItemID.GRACEFUL_LEGS_21070), item(ItemID.GRACEFUL_LEGS_21072), item(ItemID.GRACEFUL_LEGS_24752), item(ItemID.GRACEFUL_LEGS_24754), item(ItemID.GRACEFUL_LEGS_25078), item(ItemID.GRACEFUL_LEGS_25080)), + any("", item(ItemID.GRACEFUL_GLOVES), item(ItemID.GRACEFUL_GLOVES_11859), item(ItemID.GRACEFUL_GLOVES_13587), item(ItemID.GRACEFUL_GLOVES_13588), item(ItemID.GRACEFUL_GLOVES_13599), item(ItemID.GRACEFUL_GLOVES_13600), item(ItemID.GRACEFUL_GLOVES_13611), item(ItemID.GRACEFUL_GLOVES_13612), item(ItemID.GRACEFUL_GLOVES_13623), item(ItemID.GRACEFUL_GLOVES_13624), item(ItemID.GRACEFUL_GLOVES_13635), item(ItemID.GRACEFUL_GLOVES_13636), item(ItemID.GRACEFUL_GLOVES_13675), item(ItemID.GRACEFUL_GLOVES_13676), item(ItemID.GRACEFUL_GLOVES_21073), item(ItemID.GRACEFUL_GLOVES_21075), item(ItemID.GRACEFUL_GLOVES_24755), item(ItemID.GRACEFUL_GLOVES_24757), item(ItemID.GRACEFUL_GLOVES_25081), item(ItemID.GRACEFUL_GLOVES_25083)), + any("", item(ItemID.GRACEFUL_BOOTS), item(ItemID.GRACEFUL_BOOTS_11861), item(ItemID.GRACEFUL_BOOTS_13589), item(ItemID.GRACEFUL_BOOTS_13590), item(ItemID.GRACEFUL_BOOTS_13601), item(ItemID.GRACEFUL_BOOTS_13602), item(ItemID.GRACEFUL_BOOTS_13613), item(ItemID.GRACEFUL_BOOTS_13614), item(ItemID.GRACEFUL_BOOTS_13625), item(ItemID.GRACEFUL_BOOTS_13626), item(ItemID.GRACEFUL_BOOTS_13637), item(ItemID.GRACEFUL_BOOTS_13638), item(ItemID.GRACEFUL_BOOTS_13677), item(ItemID.GRACEFUL_BOOTS_13678), item(ItemID.GRACEFUL_BOOTS_21076), item(ItemID.GRACEFUL_BOOTS_21078), item(ItemID.GRACEFUL_BOOTS_24758), item(ItemID.GRACEFUL_BOOTS_24760), item(ItemID.GRACEFUL_BOOTS_25084), item(ItemID.GRACEFUL_BOOTS_25086)))), new SkillChallengeClue("Mix an anti-venom potion.", item(ItemID.ANTIDOTE4_5952), xOfItem(ItemID.ZULRAHS_SCALES, 20)), new SkillChallengeClue("Mine a piece of Runite ore", "mine a piece of runite ore whilst sporting the finest mining gear.", true, ANY_PICKAXE, all("Prospector kit", item(ItemID.PROSPECTOR_HELMET), any("", item(ItemID.PROSPECTOR_JACKET), item(ItemID.VARROCK_ARMOUR_4)), item(ItemID.PROSPECTOR_LEGS), item(ItemID.PROSPECTOR_BOOTS))), new SkillChallengeClue("Steal a gem from the Ardougne market."), @@ -370,6 +380,7 @@ public class SkillChallengeClue extends ClueScroll implements NpcClueScroll, Nam .left(requirement.getCollectiveName(plugin.getClient())) .leftColor(TITLED_CONTENT_COLOR) .right(combinedFulfilled ? "\u2713" : "\u2717") + .rightFont(FontManager.getDefaultFont()) .rightColor(equipmentFulfilled || (combinedFulfilled && !requireEquipped) ? Color.GREEN : (combinedFulfilled ? Color.ORANGE : Color.RED)) .build()); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/hotcold/HotColdLocation.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/hotcold/HotColdLocation.java index b624e206a2..74e71b934d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/hotcold/HotColdLocation.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/hotcold/HotColdLocation.java @@ -91,11 +91,12 @@ public enum HotColdLocation FREMENNIK_PROVINCE_FREMMY_ISLES_MINE(new WorldPoint(2374, 3850, 0), FREMENNIK_PROVINCE, "Central Fremennik Isles mine.", ANCIENT_WIZARDS), FREMENNIK_PROVINCE_WEST_ISLES_MINE(new WorldPoint(2313, 3850, 0), FREMENNIK_PROVINCE, "West Fremennik Isles mine.", ANCIENT_WIZARDS), FREMENNIK_PROVINCE_WEST_JATIZSO_ENTRANCE(new WorldPoint(2393, 3812, 0), FREMENNIK_PROVINCE, "West of the Jatizso mine entrance.", BRASSICAN_MAGE), - FREMENNIK_PROVINCE_PIRATES_COVE(new WorldPoint(2210, 3814, 0), FREMENNIK_PROVINCE, "Pirates' Cove", ANCIENT_WIZARDS), + FREMENNIK_PROVINCE_PIRATES_COVE(new WorldPoint(2211, 3817, 0), FREMENNIK_PROVINCE, "Pirates' Cove", ANCIENT_WIZARDS), FREMENNIK_PROVINCE_ASTRAL_ALTER(new WorldPoint(2149, 3865, 0), FREMENNIK_PROVINCE, "Astral altar", ANCIENT_WIZARDS), FREMENNIK_PROVINCE_LUNAR_VILLAGE(new WorldPoint(2084, 3916, 0), FREMENNIK_PROVINCE, "Lunar Isle, inside the village.", ANCIENT_WIZARDS), FREMENNIK_PROVINCE_LUNAR_NORTH(new WorldPoint(2106, 3949, 0), FREMENNIK_PROVINCE, "Lunar Isle, north of the village.", ANCIENT_WIZARDS), ICE_MOUNTAIN(new WorldPoint(3007, 3475, 0), MISTHALIN, "Atop Ice Mountain"), + ISLE_OF_SOULS_MINE(new WorldPoint(2189, 2794, 0), KANDARIN, "Isle of Souls Mine, south of the Soul Wars lobby"), KANDARIN_SINCLAR_MANSION(new WorldPoint(2730, 3588, 0), KANDARIN, "North-west of the Sinclair Mansion, near the log balance shortcut.", BRASSICAN_MAGE), KANDARIN_CATHERBY(new WorldPoint(2774, 3436, 0), KANDARIN, "Catherby, between the bank and the beehives, near small rock formation.", BRASSICAN_MAGE), KANDARIN_GRAND_TREE(new WorldPoint(2448, 3503, 0), KANDARIN, "Grand Tree, just east of the terrorchick gnome enclosure.", BRASSICAN_MAGE), @@ -164,7 +165,7 @@ public enum HotColdLocation ZEAH_BLASTMINE_NORTH(new WorldPoint(1488, 3881, 0), ZEAH, "Northern part of the Lovakengj blast mine.", BRASSICAN_MAGE), ZEAH_LOVAKITE_FURNACE(new WorldPoint(1507, 3819, 0), ZEAH, "Next to the lovakite furnace in Lovakengj.", ANCIENT_WIZARDS), ZEAH_LOVAKENGJ_MINE(new WorldPoint(1477, 3778, 0), ZEAH, "Next to mithril rock in the Lovakengj mine.", ANCIENT_WIZARDS), - ZEAH_SULPHR_MINE(new WorldPoint(1428, 3869, 0), ZEAH, "Western entrance in the Lovakengj sulphur mine.", BRASSICAN_MAGE), + ZEAH_SULPHR_MINE(new WorldPoint(1428, 3869, 0), ZEAH, "Western entrance in the Lovakengj sulphur mine. Facemask or Slayer Helmet recommended.", BRASSICAN_MAGE), ZEAH_SHAYZIEN_BANK(new WorldPoint(1517, 3603, 0), ZEAH, "South-east of the bank in Shayzien.", ANCIENT_WIZARDS), ZEAH_OVERPASS(new WorldPoint(1467, 3714, 0), ZEAH, "Overpass between Lovakengj and Shayzien.", BRASSICAN_MAGE), ZEAH_LIZARDMAN(new WorldPoint(1490, 3698, 0), ZEAH, "Within Lizardman Canyon, east of the ladder. Requires 5% favour with Shayzien.", ANCIENT_WIZARDS), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java index fe6a5b54a2..b176bf154b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java @@ -66,6 +66,8 @@ import javax.swing.border.MatteBorder; import javax.swing.event.ChangeListener; import javax.swing.text.JTextComponent; import lombok.extern.slf4j.Slf4j; +import net.runelite.api.events.ConfigButtonClicked; +import net.runelite.client.config.Button; import net.runelite.client.config.ConfigDescriptor; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; @@ -78,6 +80,7 @@ import net.runelite.client.config.Keybind; import net.runelite.client.config.ModifierlessKeybind; import net.runelite.client.config.Range; import net.runelite.client.config.Units; +import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.events.ExternalPluginsChanged; import net.runelite.client.events.PluginChanged; @@ -130,6 +133,9 @@ class ConfigPanel extends PluginPanel @Inject private ColorPickerManager colorPickerManager; + @Inject + private EventBus eventBus; + private PluginConfigurationDescriptor pluginConfig = null; static @@ -334,6 +340,28 @@ class ConfigPanel extends PluginPanel PluginListItem.addLabelPopupMenu(configEntryName, createResetMenuItem(pluginConfig, cid)); item.add(configEntryName, BorderLayout.CENTER); + if (cid.getType() == Button.class) + { + try + { + ConfigItem cidItem = cid.getItem(); + JButton button = new JButton(cidItem.name()); + button.addActionListener((e) -> + { + ConfigButtonClicked event = new ConfigButtonClicked(); + event.setGroup(cd.getGroup().value()); + event.setKey(cid.getItem().keyName()); + eventBus.post(event); + }); + item.add(button); + } + catch (Exception ex) + { + log.error("Adding action listener failed: {}", ex.getMessage()); + ex.printStackTrace(); + } + } + if (cid.getType() == boolean.class) { JCheckBox checkbox = new JCheckBox(); @@ -487,15 +515,19 @@ class ConfigPanel extends PluginPanel if (cid.getType().isEnum()) { Class type = (Class) cid.getType(); - JComboBox box = new JComboBox(type.getEnumConstants()); + + JComboBox> box = new JComboBox>(type.getEnumConstants()); // NOPMD: UseDiamondOperator + // set renderer prior to calling box.getPreferredSize(), since it will invoke the renderer + // to build components for each combobox element in order to compute the display size of the + // combobox + box.setRenderer(new ComboBoxListRenderer<>()); box.setPreferredSize(new Dimension(box.getPreferredSize().width, 25)); - box.setRenderer(new ComboBoxListRenderer()); box.setForeground(Color.WHITE); box.setFocusable(false); - box.setPrototypeDisplayValue("XXXXXXXX"); //sorry but this is the way to keep the size of the combobox in check. + try { - Enum selectedItem = Enum.valueOf(type, configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName())); + Enum selectedItem = Enum.valueOf(type, configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName())); box.setSelectedItem(selectedItem); box.setToolTipText(Text.titleCase(selectedItem)); } @@ -508,7 +540,7 @@ class ConfigPanel extends PluginPanel if (e.getStateChange() == ItemEvent.SELECTED) { changeConfiguration(box, cd, cid); - box.setToolTipText(Text.titleCase((Enum) box.getSelectedItem())); + box.setToolTipText(Text.titleCase((Enum) box.getSelectedItem())); } }); item.add(box, BorderLayout.EAST); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/config/HotkeyButton.java b/runelite-client/src/main/java/net/runelite/client/plugins/config/HotkeyButton.java index 55b9160c5b..131aef04bc 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/config/HotkeyButton.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/config/HotkeyButton.java @@ -32,6 +32,7 @@ import javax.swing.JButton; import lombok.Getter; import net.runelite.client.config.Keybind; import net.runelite.client.config.ModifierlessKeybind; +import net.runelite.client.ui.FontManager; class HotkeyButton extends JButton { @@ -40,6 +41,7 @@ class HotkeyButton extends JButton public HotkeyButton(Keybind value, boolean modifierless) { + setFont(FontManager.getDefaultFont().deriveFont(12.f)); setValue(value); addMouseListener(new MouseAdapter() { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginHubPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginHubPanel.java index 562a8517e2..7f9bbceb05 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginHubPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginHubPanel.java @@ -125,10 +125,13 @@ class PluginHubPanel extends PluginPanel @Getter private final List keywords = new ArrayList<>(); + @Getter + private final int userCount; + @Getter private final boolean installed; - PluginItem(ExternalPluginManifest newManifest, Collection loadedPlugins, boolean installed) + PluginItem(ExternalPluginManifest newManifest, Collection loadedPlugins, int userCount, boolean installed) { ExternalPluginManifest loaded = null; if (!loadedPlugins.isEmpty()) @@ -137,6 +140,7 @@ class PluginHubPanel extends PluginPanel } manifest = newManifest == null ? loaded : newManifest; + this.userCount = userCount; this.installed = installed; if (manifest != null) @@ -194,10 +198,7 @@ class PluginHubPanel extends PluginPanel { BufferedImage img = externalPluginClient.downloadIcon(manifest); - SwingUtilities.invokeLater(() -> - { - icon.setIcon(new ImageIcon(img)); - }); + SwingUtilities.invokeLater(() -> icon.setIcon(new ImageIcon(img))); } catch (IOException e) { @@ -521,11 +522,21 @@ class PluginHubPanel extends PluginPanel return; } - reloadPluginList(manifest); + Map pluginCounts = Collections.emptyMap(); + try + { + pluginCounts = externalPluginClient.getPluginCounts(); + } + catch (IOException e) + { + log.warn("unable to download plugin counts", e); + } + + reloadPluginList(manifest, pluginCounts); }); } - private void reloadPluginList(List manifest) + private void reloadPluginList(List manifest, Map pluginCounts) { Map manifests = manifest.stream() .collect(ImmutableMap.toImmutableMap(ExternalPluginManifest::getInternalName, Function.identity())); @@ -547,7 +558,8 @@ class PluginHubPanel extends PluginPanel { plugins = Sets.union(manifests.keySet(), loadedPlugins.keySet()) .stream() - .map(id -> new PluginItem(manifests.get(id), loadedPlugins.get(id), installed.contains(id))) + .map(id -> new PluginItem(manifests.get(id), loadedPlugins.get(id), + pluginCounts.getOrDefault(id, -1), installed.contains(id))) .collect(Collectors.toList()); refreshing.setVisible(false); @@ -575,7 +587,11 @@ class PluginHubPanel extends PluginPanel else { stream - .sorted(Comparator.comparing(PluginItem::isInstalled).thenComparing(p -> p.manifest.getDisplayName())) + .sorted(Comparator.comparing(PluginItem::isInstalled) + .thenComparingInt(PluginItem::getUserCount) + .reversed() + .thenComparing(p -> p.manifest.getDisplayName()) + ) .forEach(mainPanel::add); } @@ -594,6 +610,13 @@ class PluginHubPanel extends PluginPanel @Subscribe private void onExternalPluginsChanged(ExternalPluginsChanged ev) { - SwingUtilities.invokeLater(() -> reloadPluginList(ev.getLoadedManifest())); + Map pluginCounts = Collections.emptyMap(); + if (plugins != null) + { + pluginCounts = plugins.stream() + .collect(Collectors.toMap(pi -> pi.manifest.getInternalName(), PluginItem::getUserCount)); + } + + reloadPluginList(ev.getLoadedManifest(), pluginCounts); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginListPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginListPanel.java index 382282b92e..286b534877 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginListPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginListPanel.java @@ -32,7 +32,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; -import java.util.concurrent.ScheduledExecutorService; import java.util.stream.Collectors; import java.util.stream.Stream; import javax.inject.Inject; @@ -108,7 +107,6 @@ class PluginListPanel extends PluginPanel ConfigManager configManager, PluginManager pluginManager, ExternalPluginManager externalPluginManager, - ScheduledExecutorService executorService, EventBus eventBus, Provider configPanelProvider, Provider pluginHubPanelProvider) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginToggleButton.java b/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginToggleButton.java index 185a5e7ecc..60f6256048 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginToggleButton.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginToggleButton.java @@ -29,8 +29,8 @@ import java.awt.Dimension; import java.awt.image.BufferedImage; import javax.swing.ImageIcon; import javax.swing.JToggleButton; -import com.openosrs.client.util.ImageUtil; import net.runelite.client.ui.ColorScheme; +import net.runelite.client.util.ImageUtil; import net.runelite.client.util.SwingUtil; class PluginToggleButton extends JToggleButton diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cooking/CookingPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/cooking/CookingPlugin.java index a75aa8c2eb..cfed06e255 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cooking/CookingPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cooking/CookingPlugin.java @@ -124,9 +124,9 @@ public class CookingPlugin extends Plugin } Duration statTimeout = Duration.ofMinutes(config.statTimeout()); - Duration sinceCut = Duration.between(session.getLastCookingAction(), Instant.now()); + Duration sinceCooked = Duration.between(session.getLastCookingAction(), Instant.now()); - if (sinceCut.compareTo(statTimeout) >= 0) + if (sinceCooked.compareTo(statTimeout) >= 0) { session = null; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/crowdsourcing/CrowdsourcingManager.java b/runelite-client/src/main/java/net/runelite/client/plugins/crowdsourcing/CrowdsourcingManager.java index 661071a786..09d737c10f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/crowdsourcing/CrowdsourcingManager.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/crowdsourcing/CrowdsourcingManager.java @@ -32,7 +32,6 @@ import java.util.List; import javax.inject.Inject; import javax.inject.Singleton; import lombok.extern.slf4j.Slf4j; -import net.runelite.http.api.RuneLiteAPI; import okhttp3.Call; import okhttp3.Callback; import okhttp3.MediaType; @@ -47,11 +46,13 @@ public class CrowdsourcingManager { private static final String CROWDSOURCING_BASE = "https://crowdsource.runescape.wiki/runelite"; private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); - private static final Gson GSON = RuneLiteAPI.GSON; @Inject private OkHttpClient okHttpClient; + @Inject + private Gson gson; + private List data = new ArrayList<>(); public void storeEvent(Object event) @@ -77,7 +78,7 @@ public class CrowdsourcingManager Request r = new Request.Builder() .url(CROWDSOURCING_BASE) - .post(RequestBody.create(JSON, GSON.toJson(temp))) + .post(RequestBody.create(JSON, gson.toJson(temp))) .build(); okHttpClient.newCall(r).enqueue(new Callback() diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/crowdsourcing/woodcutting/CrowdsourcingWoodcutting.java b/runelite-client/src/main/java/net/runelite/client/plugins/crowdsourcing/woodcutting/CrowdsourcingWoodcutting.java index e61a017960..8defbe2b0d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/crowdsourcing/woodcutting/CrowdsourcingWoodcutting.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/crowdsourcing/woodcutting/CrowdsourcingWoodcutting.java @@ -85,6 +85,7 @@ public class CrowdsourcingWoodcutting put(AnimationID.WOODCUTTING_ADAMANT, ItemID.ADAMANT_AXE). put(AnimationID.WOODCUTTING_RUNE, ItemID.RUNE_AXE). put(AnimationID.WOODCUTTING_DRAGON, ItemID.DRAGON_AXE). + put(AnimationID.WOODCUTTING_DRAGON_OR, ItemID.DRAGON_AXE_OR). put(AnimationID.WOODCUTTING_INFERNAL, ItemID.INFERNAL_AXE). put(AnimationID.WOODCUTTING_3A_AXE, ItemID._3RD_AGE_AXE). put(AnimationID.WOODCUTTING_CRYSTAL, ItemID.CRYSTAL_AXE). diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/customcursor/CustomCursor.java b/runelite-client/src/main/java/net/runelite/client/plugins/customcursor/CustomCursor.java index 3baf137c96..f3ea32db28 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/customcursor/CustomCursor.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/customcursor/CustomCursor.java @@ -56,4 +56,11 @@ public enum CustomCursor this.name = name; this.cursorImage = ImageUtil.loadImageResource(CustomCursorPlugin.class, icon); } + + @Override + public String toString() + { + return name; + } } + diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsOverlay.java index b4a9f65337..208107e836 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsOverlay.java @@ -43,8 +43,6 @@ import net.runelite.api.Constants; import net.runelite.api.DecorativeObject; import net.runelite.api.GameObject; import net.runelite.api.GraphicsObject; -import net.runelite.api.TileItem; -import net.runelite.api.GroundObject; import net.runelite.api.ItemLayer; import net.runelite.api.NPC; import net.runelite.api.NPCComposition; @@ -55,7 +53,8 @@ import net.runelite.api.Point; import net.runelite.api.Projectile; import net.runelite.api.Scene; import net.runelite.api.Tile; -import net.runelite.api.WallObject; +import net.runelite.api.TileItem; +import net.runelite.api.TileObject; import net.runelite.api.coords.LocalPoint; import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.WidgetInfo; @@ -154,7 +153,6 @@ class DevToolsOverlay extends Overlay String text = local.getName() + " (A: " + local.getAnimation() + ") (P: " + local.getPoseAnimation() + ") (G: " + local.getGraphic() + ")"; OverlayUtil.renderActorOverlay(graphics, local, text, CYAN); - renderPlayerWireframe(graphics, local, CYAN); } private void renderNpcs(Graphics2D graphics) @@ -214,7 +212,7 @@ class DevToolsOverlay extends Overlay if (plugin.getGroundObjects().isActive()) { - renderGroundObject(graphics, tile, player); + renderTileObject(graphics, tile.getGroundObject(), player, PURPLE); } if (plugin.getGameObjects().isActive()) @@ -224,7 +222,7 @@ class DevToolsOverlay extends Overlay if (plugin.getWalls().isActive()) { - renderWallObject(graphics, tile, player); + renderTileObject(graphics, tile.getWallObject(), player, GRAY); } if (plugin.getDecorations().isActive()) @@ -309,45 +307,21 @@ class DevToolsOverlay extends Overlay { for (GameObject gameObject : gameObjects) { - if (gameObject != null) + if (gameObject != null && gameObject.getSceneMinLocation().equals(tile.getSceneLocation())) { - if (player.getLocalLocation().distanceTo(gameObject.getLocalLocation()) <= MAX_DISTANCE) - { - OverlayUtil.renderTileOverlay(graphics, gameObject, "ID: " + gameObject.getId(), GREEN); - } - - // Draw a polygon around the convex hull - // of the model vertices - Shape p = gameObject.getConvexHull(); - if (p != null) - { - graphics.draw(p); - } + renderTileObject(graphics, gameObject, player, GREEN); } } } } - private void renderGroundObject(Graphics2D graphics, Tile tile, Player player) + private void renderTileObject(Graphics2D graphics, TileObject tileObject, Player player, Color color) { - GroundObject groundObject = tile.getGroundObject(); - if (groundObject != null) + if (tileObject != null) { - if (player.getLocalLocation().distanceTo(groundObject.getLocalLocation()) <= MAX_DISTANCE) + if (player.getLocalLocation().distanceTo(tileObject.getLocalLocation()) <= MAX_DISTANCE) { - OverlayUtil.renderTileOverlay(graphics, groundObject, "ID: " + groundObject.getId(), PURPLE); - } - } - } - - private void renderWallObject(Graphics2D graphics, Tile tile, Player player) - { - WallObject wallObject = tile.getWallObject(); - if (wallObject != null) - { - if (player.getLocalLocation().distanceTo(wallObject.getLocalLocation()) <= MAX_DISTANCE) - { - OverlayUtil.renderTileOverlay(graphics, wallObject, "ID: " + wallObject.getId(), GRAY); + OverlayUtil.renderTileOverlay(graphics, tileObject, "ID: " + tileObject.getId(), color); } } } @@ -447,22 +421,4 @@ class DevToolsOverlay extends Overlay } } } - - private void renderPlayerWireframe(Graphics2D graphics, Player player, Color color) - { - Polygon[] polys = player.getPolygons(); - - if (polys == null) - { - return; - } - - graphics.setColor(color); - - for (Polygon p : polys) - { - graphics.drawPolygon(p); - } - } - } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordGameEventType.java b/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordGameEventType.java index 17b72b5d6e..4bfe4652ed 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordGameEventType.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordGameEventType.java @@ -26,16 +26,12 @@ */ package net.runelite.client.plugins.discord; -import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import java.util.List; import java.util.Map; import javax.annotation.Nullable; import lombok.AllArgsConstructor; import lombok.Getter; -import net.runelite.api.Client; import net.runelite.api.Skill; -import net.runelite.api.Varbits; @AllArgsConstructor @Getter @@ -187,6 +183,7 @@ enum DiscordGameEventType DUNGEON_CRABCLAW_CAVES("Crabclaw Caves", DiscordAreaType.DUNGEONS, 6553, 6809), DUNGEON_CRANDOR("Crandor Dungeon", DiscordAreaType.DUNGEONS, 11414), DUNGEON_CRASH_SITE_CAVERN("Crash Site Cavern", DiscordAreaType.DUNGEONS, 8280, 8536), + DUNGEON_CRUMBLING_TOWER("Crumbling Tower", DiscordAreaType.DUNGEONS, 7827), DUNGEON_DAEYALT_ESSENCE_MINE("Daeyalt Essence Mine", DiscordAreaType.DUNGEONS, 14744), DUNGEON_DIGSITE("Digsite Dungeon", DiscordAreaType.DUNGEONS, 13464, 13465), DUNGEON_DORGESHKAAN("Dorgesh-Kaan South Dungeon", DiscordAreaType.DUNGEONS, 10833), @@ -210,6 +207,7 @@ enum DiscordGameEventType DUNGEON_HAM_STORE_ROOM("H.A.M. Store room", DiscordAreaType.DUNGEONS, 10321), DUNGEON_HEROES_GUILD("Heroes' Guild Mine", DiscordAreaType.DUNGEONS, 11674), DUNGEON_IORWERTH("Iorwerth Dungeon", DiscordAreaType.DUNGEONS, 12737, 12738, 12993, 12994), + DUNGEON_ISLE_OF_SOULS("Isle of Souls Dungeon", DiscordAreaType.DUNGEONS, 8593), DUNGEON_JATIZSO_MINES("Jatizso Mines", DiscordAreaType.DUNGEONS, 9631), DUNGEON_JIGGIG_BURIAL_TOMB("Jiggig Burial Tomb", DiscordAreaType.DUNGEONS, 9875, 9874), DUNGEON_JOGRE("Jogre Dungeon", DiscordAreaType.DUNGEONS, 11412), @@ -307,8 +305,8 @@ enum DiscordGameEventType MG_VOLCANIC_MINE("Volcanic Mine", DiscordAreaType.MINIGAMES, 15263, 15262), // Raids - RAIDS_CHAMBERS_OF_XERIC("Chambers of Xeric", DiscordAreaType.RAIDS, Varbits.IN_RAID), - RAIDS_THEATRE_OF_BLOOD("Theatre of Blood", DiscordAreaType.RAIDS, Varbits.THEATRE_OF_BLOOD), + RAIDS_CHAMBERS_OF_XERIC("Chambers of Xeric", DiscordAreaType.RAIDS, 12889, 13136, 13137, 13138, 13139, 13140, 13141, 13145, 13393, 13394, 13395, 13396, 13397, 13401), + RAIDS_THEATRE_OF_BLOOD("Theatre of Blood", DiscordAreaType.RAIDS, 12611, 12612, 12613, 12867, 12869, 13122, 13123, 13125, 13379), // Other REGION_ABYSSAL_AREA("Abyssal Area", DiscordAreaType.REGIONS, 12108), @@ -367,6 +365,7 @@ enum DiscordGameEventType REGION_ICYENE_GRAVEYARD("Icyene Graveyard", DiscordAreaType.REGIONS, 14641, 14897, 14898), REGION_ISAFDAR("Isafdar", DiscordAreaType.REGIONS, 8497, 8753, 8754, 9009, 9010), REGION_ISLAND_OF_STONE("Island of Stone", DiscordAreaType.REGIONS, 9790), + REGION_ISLE_OF_SOULS("Isle of Souls", DiscordAreaType.REGIONS, 8236, 8237, 8238, 8491, 8492, 8494, 8747, 8750, 9003, 9004, 9006, 9260, 9261, 9262), REGION_JIGGIG("Jiggig" , DiscordAreaType.REGIONS, 9775), REGION_KANDARIN("Kandarin", DiscordAreaType.REGIONS, 9014, 9263, 9264, 9519, 9524, 9527, 9776, 9783, 10037, 10290, 10294, 10546, 10551, 10805), REGION_KARAMJA("Karamja" , DiscordAreaType.REGIONS, 10801, 10802, 11054, 11311, 11312, 11313, 11566, 11567, 11568, 11569, 11822), @@ -430,20 +429,12 @@ enum DiscordGameEventType REGION_WRATH_ALTAR("Wrath Altar", DiscordAreaType.REGIONS, 9291); private static final Map FROM_REGION; - private static final List FROM_VARBITS; static { ImmutableMap.Builder regionMapBuilder = new ImmutableMap.Builder<>(); - ImmutableList.Builder fromVarbitsBuilder = ImmutableList.builder(); for (DiscordGameEventType discordGameEventType : DiscordGameEventType.values()) { - if (discordGameEventType.getVarbits() != null) - { - fromVarbitsBuilder.add(discordGameEventType); - continue; - } - if (discordGameEventType.getRegionIds() == null) { continue; @@ -455,7 +446,6 @@ enum DiscordGameEventType } } FROM_REGION = regionMapBuilder.build(); - FROM_VARBITS = fromVarbitsBuilder.build(); } @Nullable @@ -470,7 +460,7 @@ enum DiscordGameEventType private int priority; /** - * Marks this event as root event, e.g event that should be used for total time tracking + * Marks this event as root event. (eg. event that should be used for total time tracking) */ private boolean root; @@ -497,9 +487,6 @@ enum DiscordGameEventType @Nullable private DiscordAreaType discordAreaType; - @Nullable - private Varbits varbits; - @Nullable private int[] regionIds; @@ -541,15 +528,6 @@ enum DiscordGameEventType this(state, priority, true, false, false, true, false); } - DiscordGameEventType(String areaName, DiscordAreaType areaType, Varbits varbits) - { - this.state = exploring(areaType, areaName); - this.priority = -2; - this.discordAreaType = areaType; - this.varbits = varbits; - this.shouldClear = true; - } - private static String training(final Skill skill) { return training(skill.getName()); @@ -609,17 +587,4 @@ enum DiscordGameEventType { return FROM_REGION.get(regionId); } - - public static DiscordGameEventType fromVarbit(final Client client) - { - for (DiscordGameEventType fromVarbit : FROM_VARBITS) - { - if (client.getVar(fromVarbit.getVarbits()) != 0) - { - return fromVarbit; - } - } - - return null; - } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordPlugin.java index 6f5ffbdcd1..cfc0aa80e9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordPlugin.java @@ -46,7 +46,6 @@ import net.runelite.api.WorldType; import net.runelite.api.coords.WorldPoint; import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.StatChanged; -import net.runelite.api.events.VarbitChanged; import net.runelite.client.config.ConfigManager; import net.runelite.client.discord.DiscordService; import net.runelite.client.discord.events.DiscordJoinGame; @@ -210,22 +209,6 @@ public class DiscordPlugin extends Plugin } } - @Subscribe - public void onVarbitChanged(VarbitChanged event) - { - if (!config.showRaidingActivity()) - { - return; - } - - final DiscordGameEventType discordGameEventType = DiscordGameEventType.fromVarbit(client); - - if (discordGameEventType != null) - { - discordState.triggerEvent(discordGameEventType); - } - } - @Subscribe public void onDiscordReady(DiscordReady event) { @@ -447,6 +430,7 @@ public class DiscordPlugin extends Plugin case DUNGEONS: return config.showDungeonActivity(); case MINIGAMES: return config.showMinigameActivity(); case REGIONS: return config.showRegionsActivity(); + case RAIDS: return config.showRaidingActivity(); } return false; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/driftnet/DriftNetConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/driftnet/DriftNetConfig.java index a977ab3890..c7462819c3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/driftnet/DriftNetConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/driftnet/DriftNetConfig.java @@ -99,7 +99,7 @@ public interface DriftNetConfig extends Config @ConfigItem( keyName = "tagAnnette", - name = "Tag Annette when no nets in inventory", + name = "Tag Annette", description = "Tag Annette when no nets in inventory", position = 6 ) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/emojis/Emoji.java b/runelite-client/src/main/java/net/runelite/client/plugins/emojis/Emoji.java index 37cc934ce2..8eb163ba53 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/emojis/Emoji.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/emojis/Emoji.java @@ -91,6 +91,8 @@ enum Emoji GORILLA(":G"), PLEADING("(n_n)"), XD("Xd"), + SPOON("--o"), + WEARY_FACE("Dx"), ; private static final Map emojiMap; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/emojis/EmojiPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/emojis/EmojiPlugin.java index e63a97c3cc..9fc33d8647 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/emojis/EmojiPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/emojis/EmojiPlugin.java @@ -40,7 +40,6 @@ import net.runelite.api.events.ChatMessage; import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.OverheadTextChanged; import net.runelite.client.callback.ClientThread; -import net.runelite.client.chat.ChatMessageManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; @@ -63,9 +62,6 @@ public class EmojiPlugin extends Plugin @Inject private ClientThread clientThread; - @Inject - private ChatMessageManager chatMessageManager; - private int modIconsStart = -1; @Override @@ -145,9 +141,7 @@ public class EmojiPlugin extends Plugin return; } - messageNode.setRuneLiteFormatMessage(updatedMessage); - chatMessageManager.update(messageNode); - client.refreshChat(); + messageNode.setValue(updatedMessage); } @Subscribe diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/entityhider/EntityHiderConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/entityhider/EntityHiderConfig.java index d3ee118b8c..a18c211da3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/entityhider/EntityHiderConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/entityhider/EntityHiderConfig.java @@ -29,16 +29,18 @@ import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; -@ConfigGroup("entityhider") +@ConfigGroup(EntityHiderConfig.GROUP) public interface EntityHiderConfig extends Config { + String GROUP = "entityhider"; + @ConfigItem( position = 1, keyName = "hidePlayers", - name = "Hide Players", - description = "Configures whether or not players are hidden" + name = "Hide Others", + description = "Configures whether or not other players are hidden" ) - default boolean hidePlayers() + default boolean hideOthers() { return true; } @@ -46,10 +48,10 @@ public interface EntityHiderConfig extends Config @ConfigItem( position = 2, keyName = "hidePlayers2D", - name = "Hide Players 2D", - description = "Configures whether or not players 2D elements are hidden" + name = "Hide Others 2D", + description = "Configures whether or not other players 2D elements are hidden" ) - default boolean hidePlayers2D() + default boolean hideOthers2D() { return true; } @@ -78,6 +80,17 @@ public interface EntityHiderConfig extends Config @ConfigItem( position = 5, + keyName = "hideIgnores", + name = "Hide Ignores", + description = "Configures whether or not ignored players are hidden" + ) + default boolean hideIgnores() + { + return false; + } + + @ConfigItem( + position = 6, keyName = "hideLocalPlayer", name = "Hide Local Player", description = "Configures whether or not the local player is hidden" @@ -88,7 +101,7 @@ public interface EntityHiderConfig extends Config } @ConfigItem( - position = 6, + position = 7, keyName = "hideLocalPlayer2D", name = "Hide Local Player 2D", description = "Configures whether or not the local player's 2D elements are hidden" @@ -99,7 +112,7 @@ public interface EntityHiderConfig extends Config } @ConfigItem( - position = 7, + position = 8, keyName = "hideNPCs", name = "Hide NPCs", description = "Configures whether or not NPCs are hidden" @@ -110,7 +123,7 @@ public interface EntityHiderConfig extends Config } @ConfigItem( - position = 8, + position = 9, keyName = "hideNPCs2D", name = "Hide NPCs 2D", description = "Configures whether or not NPCs 2D elements are hidden" @@ -121,7 +134,7 @@ public interface EntityHiderConfig extends Config } @ConfigItem( - position = 9, + position = 10, keyName = "hidePets", name = "Hide Pets", description = "Configures whether or not other player pets are hidden" @@ -132,7 +145,7 @@ public interface EntityHiderConfig extends Config } @ConfigItem( - position = 10, + position = 11, keyName = "hideAttackers", name = "Hide Attackers", description = "Configures whether or not NPCs/players attacking you are hidden" @@ -143,7 +156,7 @@ public interface EntityHiderConfig extends Config } @ConfigItem( - position = 11, + position = 12, keyName = "hideProjectiles", name = "Hide Projectiles", description = "Configures whether or not projectiles are hidden" diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/entityhider/EntityHiderPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/entityhider/EntityHiderPlugin.java index 155bc6cc38..79a9dc160f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/entityhider/EntityHiderPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/entityhider/EntityHiderPlugin.java @@ -28,13 +28,9 @@ package net.runelite.client.plugins.entityhider; import com.google.inject.Provides; import javax.inject.Inject; import net.runelite.api.Client; -import net.runelite.api.GameState; -import net.runelite.api.Player; -import net.runelite.api.coords.WorldPoint; -import net.runelite.client.events.ConfigChanged; -import net.runelite.api.events.GameStateChanged; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.events.ConfigChanged; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; @@ -67,27 +63,22 @@ public class EntityHiderPlugin extends Plugin @Subscribe public void onConfigChanged(ConfigChanged e) { - updateConfig(); - } - - @Subscribe - public void onGameStateChanged(GameStateChanged event) - { - if (event.getGameState() == GameState.LOGGED_IN) + if (e.getGroup().equals(EntityHiderConfig.GROUP)) { - client.setIsHidingEntities(isPlayerRegionAllowed()); + updateConfig(); } } private void updateConfig() { - client.setIsHidingEntities(isPlayerRegionAllowed()); + client.setIsHidingEntities(true); - client.setPlayersHidden(config.hidePlayers()); - client.setPlayersHidden2D(config.hidePlayers2D()); + client.setOthersHidden(config.hideOthers()); + client.setOthersHidden2D(config.hideOthers2D()); client.setFriendsHidden(config.hideFriends()); client.setFriendsChatMembersHidden(config.hideFriendsChatMembers()); + client.setIgnoresHidden(config.hideIgnores()); client.setLocalPlayerHidden(config.hideLocalPlayer()); client.setLocalPlayerHidden2D(config.hideLocalPlayer2D()); @@ -107,11 +98,12 @@ public class EntityHiderPlugin extends Plugin { client.setIsHidingEntities(false); - client.setPlayersHidden(false); - client.setPlayersHidden2D(false); + client.setOthersHidden(false); + client.setOthersHidden2D(false); client.setFriendsHidden(false); client.setFriendsChatMembersHidden(false); + client.setIgnoresHidden(false); client.setLocalPlayerHidden(false); client.setLocalPlayerHidden2D(false); @@ -125,19 +117,4 @@ public class EntityHiderPlugin extends Plugin client.setProjectilesHidden(false); } - - private boolean isPlayerRegionAllowed() - { - final Player localPlayer = client.getLocalPlayer(); - - if (localPlayer == null) - { - return true; - } - - final int playerRegionID = WorldPoint.fromLocalInstance(client, localPlayer.getLocalLocation()).getRegionID(); - - // 9520 = Castle Wars - return playerRegionID != 9520; - } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingConfig.java index e5a1bca65b..6e68c4270a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingConfig.java @@ -93,7 +93,7 @@ public interface FishingConfig extends Config @Alpha @ConfigItem( keyName = "minnowsOverlayColor", - name = "Minnows Overlay Color", + name = "Minnows Overlay", description = "Color of overlays for Minnows", position = 5 ) @@ -105,7 +105,7 @@ public interface FishingConfig extends Config @Alpha @ConfigItem( keyName = "aerialOverlayColor", - name = "Aerial Overlay Color", + name = "Aerial Overlay", description = "Color of overlays when 1-tick aerial fishing", position = 6 ) @@ -150,6 +150,17 @@ public interface FishingConfig extends Config @ConfigItem( position = 10, + keyName = "flyingFishNotification", + name = "Flying fish notification", + description = "Send a notification when a flying fish spawns on your fishing spot." + ) + default boolean flyingFishNotification() + { + return true; + } + + @ConfigItem( + position = 11, keyName = "trawlerNotification", name = "Trawler activity notification", description = "Send a notification when fishing trawler activity drops below 15%." @@ -160,7 +171,7 @@ public interface FishingConfig extends Config } @ConfigItem( - position = 11, + position = 12, keyName = "trawlerTimer", name = "Trawler timer in MM:SS", description = "Trawler Timer will display a more accurate timer in MM:SS format." diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingOverlay.java index 43853f95c7..6d2f06d473 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingOverlay.java @@ -64,10 +64,10 @@ class FishingOverlay extends OverlayPanel AnimationID.FISHING_CAGE, AnimationID.FISHING_CRYSTAL_HARPOON, AnimationID.FISHING_DRAGON_HARPOON, + AnimationID.FISHING_DRAGON_HARPOON_OR, AnimationID.FISHING_HARPOON, AnimationID.FISHING_INFERNAL_HARPOON, AnimationID.FISHING_TRAILBLAZER_HARPOON, - AnimationID.FISHING_TRAILBLAZER_HARPOON_2, AnimationID.FISHING_KARAMBWAN, AnimationID.FISHING_NET, AnimationID.FISHING_OILY_ROD, diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingPlugin.java index 4715450f79..e782b81428 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingPlugin.java @@ -215,6 +215,11 @@ public class FishingPlugin extends Plugin spotOverlay.setHidden(false); fishingSpotMinimapOverlay.setHidden(false); } + + if (event.getMessage().equals("A flying fish jumps up and eats some of your minnows!") && config.flyingFishNotification()) + { + notifier.notify("A flying fish is eating your minnows!"); + } } @Subscribe @@ -255,8 +260,10 @@ public class FishingPlugin extends Plugin switch (item.getId()) { case ItemID.DRAGON_HARPOON: + case ItemID.DRAGON_HARPOON_OR: case ItemID.INFERNAL_HARPOON: case ItemID.INFERNAL_HARPOON_UNCHARGED: + case ItemID.INFERNAL_HARPOON_UNCHARGED_25367: case ItemID.HARPOON: case ItemID.BARBTAIL_HARPOON: case ItemID.BIG_FISHING_NET: @@ -370,7 +377,7 @@ public class FishingPlugin extends Plugin { if (!trawlerNotificationSent) { - notifier.notify("[" + client.getLocalPlayer().getName() + "] has low Fishing Trawler activity!"); + notifier.notify("You have low Fishing Trawler activity!"); trawlerNotificationSent = true; } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/friendschat/FriendsChatPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/friendschat/FriendsChatPlugin.java index 8413c225e6..6263518015 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/friendschat/FriendsChatPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/friendschat/FriendsChatPlugin.java @@ -411,11 +411,7 @@ public class FriendsChatPlugin extends Plugin .append(textColor, member.getName() + activityMessage); final String messageString = message.build(); - client.addChatMessage(ChatMessageType.FRIENDSCHATNOTIFICATION, "", messageString, ""); - - final ChatLineBuffer chatLineBuffer = client.getChatLineMap().get(ChatMessageType.FRIENDSCHATNOTIFICATION.getType()); - final MessageNode[] lines = chatLineBuffer.getLines(); - final MessageNode line = lines[0]; + final MessageNode line = client.addChatMessage(ChatMessageType.FRIENDSCHATNOTIFICATION, "", messageString, ""); MemberJoinMessage joinMessage = new MemberJoinMessage(line, line.getId(), client.getTickCount()); joinMessages.addLast(joinMessage); diff --git a/runelite-client/src/main/java/com/openosrs/client/events/ExternalPluginsLoaded.java b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GLBuffer.java similarity index 82% rename from runelite-client/src/main/java/com/openosrs/client/events/ExternalPluginsLoaded.java rename to runelite-client/src/main/java/net/runelite/client/plugins/gpu/GLBuffer.java index 75f3910d81..cd3b7288ed 100644 --- a/runelite-client/src/main/java/com/openosrs/client/events/ExternalPluginsLoaded.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GLBuffer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Owain van Brakel + * Copyright (c) 2021, Adam * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -22,11 +22,19 @@ * (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 com.openosrs.client.events; +package net.runelite.client.plugins.gpu; -import lombok.Data; -import net.runelite.api.events.Event; +import org.jocl.Pointer; +import org.jocl.cl_mem; -@Data -public class ExternalPluginsLoaded implements Event -{} +class GLBuffer +{ + int glBufferId = -1; + int size = -1; + cl_mem cl_mem; + + Pointer ptr() + { + return cl_mem != null ? Pointer.to(cl_mem) : null; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java index a6be4e5872..8ba9db5a67 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java @@ -29,6 +29,11 @@ import com.google.inject.Provides; import com.jogamp.nativewindow.awt.AWTGraphicsConfiguration; import com.jogamp.nativewindow.awt.JAWTWindow; import com.jogamp.opengl.GL; +import static com.jogamp.opengl.GL.GL_ARRAY_BUFFER; +import static com.jogamp.opengl.GL.GL_DYNAMIC_DRAW; +import static com.jogamp.opengl.GL2ES2.GL_STREAM_DRAW; +import static com.jogamp.opengl.GL2ES3.GL_STATIC_COPY; +import static com.jogamp.opengl.GL2ES3.GL_UNIFORM_BUFFER; import com.jogamp.opengl.GL4; import com.jogamp.opengl.GLCapabilities; import com.jogamp.opengl.GLContext; @@ -45,6 +50,7 @@ import java.awt.Image; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.awt.image.DataBufferInt; +import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; @@ -93,6 +99,10 @@ import net.runelite.client.plugins.gpu.config.UIScalingMode; import net.runelite.client.plugins.gpu.template.Template; import net.runelite.client.ui.DrawManager; import net.runelite.client.util.OSType; +import org.jocl.CL; +import static org.jocl.CL.CL_MEM_READ_ONLY; +import static org.jocl.CL.CL_MEM_WRITE_ONLY; +import static org.jocl.CL.clCreateFromGLBuffer; @PluginDescriptor( name = "GPU", @@ -105,8 +115,8 @@ import net.runelite.client.util.OSType; public class GpuPlugin extends Plugin implements DrawCallbacks { // This is the maximum number of triangles the compute shaders support - private static final int MAX_TRIANGLE = 4096; - private static final int SMALL_TRIANGLE_COUNT = 512; + static final int MAX_TRIANGLE = 4096; + static final int SMALL_TRIANGLE_COUNT = 512; private static final int FLAG_SCENE_BUFFER = Integer.MIN_VALUE; private static final int DEFAULT_DISTANCE = 25; static final int MAX_DISTANCE = 90; @@ -115,6 +125,9 @@ public class GpuPlugin extends Plugin implements DrawCallbacks @Inject private Client client; + @Inject + private OpenCLManager openCLManager; + @Inject private ClientThread clientThread; @@ -133,7 +146,14 @@ public class GpuPlugin extends Plugin implements DrawCallbacks @Inject private PluginManager pluginManager; - private boolean useComputeShaders; + enum ComputeMode + { + NONE, + OPENGL, + OPENCL + } + + private ComputeMode computeMode = ComputeMode.NONE; private Canvas canvas; private JAWTWindow jawtWindow; @@ -182,23 +202,22 @@ public class GpuPlugin extends Plugin implements DrawCallbacks private int texSceneHandle; private int rboSceneHandle; - // scene vertex buffer id - private int bufferId; - // scene uv buffer id - private int uvBufferId; + // scene vertex buffer + private final GLBuffer sceneVertexBuffer = new GLBuffer(); + // scene uv buffer + private final GLBuffer sceneUvBuffer = new GLBuffer(); - private int tmpBufferId; // temporary scene vertex buffer - private int tmpUvBufferId; // temporary scene uv buffer - private int tmpModelBufferId; // scene model buffer, large - private int tmpModelBufferSmallId; // scene model buffer, small - private int tmpModelBufferUnorderedId; - private int tmpOutBufferId; // target vertex buffer for compute shaders - private int tmpOutUvBufferId; // target uv buffer for compute shaders + private final GLBuffer tmpVertexBuffer = new GLBuffer(); // temporary scene vertex buffer + private final GLBuffer tmpUvBuffer = new GLBuffer(); // temporary scene uv buffer + private final GLBuffer tmpModelBufferLarge = new GLBuffer(); // scene model buffer, large + private final GLBuffer tmpModelBufferSmall = new GLBuffer(); // scene model buffer, small + private final GLBuffer tmpModelBufferUnordered = new GLBuffer(); // scene model buffer, unordered + private final GLBuffer tmpOutBuffer = new GLBuffer(); // target vertex buffer for compute shaders + private final GLBuffer tmpOutUvBuffer = new GLBuffer(); // target uv buffer for compute shaders private int textureArrayId; - private int uniformBufferId; - private final IntBuffer uniformBuffer = GpuIntBuffer.allocateDirect(5 + 3 + 2048 * 4); + private final GLBuffer uniformBuffer = new GLBuffer(); private final float[] textureOffsets = new float[128]; private GpuIntBuffer vertexBuffer; @@ -278,7 +297,6 @@ public class GpuPlugin extends Plugin implements DrawCallbacks { try { - bufferId = uvBufferId = uniformBufferId = tmpBufferId = tmpUvBufferId = tmpModelBufferId = tmpModelBufferSmallId = tmpModelBufferUnorderedId = tmpOutBufferId = tmpOutUvBufferId = -1; texSceneHandle = fboSceneHandle = rboSceneHandle = -1; // AA FBO unorderedModels = smallModels = largeModels = 0; drawingModel = false; @@ -290,8 +308,9 @@ public class GpuPlugin extends Plugin implements DrawCallbacks return false; } - // OSX supports up to OpenGL 4.1, however 4.3 is required for compute shaders - useComputeShaders = config.useComputeShaders() && OSType.getOSType() != OSType.MacOS; + computeMode = config.useComputeShaders() + ? (OSType.getOSType() == OSType.MacOS ? ComputeMode.OPENCL : ComputeMode.OPENGL) + : ComputeMode.NONE; canvas.setIgnoreRepaint(true); @@ -397,7 +416,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks if (client.getGameState() == GameState.LOGGED_IN) { - uploadScene(); + invokeOnMainThread(this::uploadScene); } } catch (Throwable e) @@ -433,6 +452,8 @@ public class GpuPlugin extends Plugin implements DrawCallbacks invokeOnMainThread(() -> { + openCLManager.cleanup(); + if (gl != null) { if (textureArrayId != -1) @@ -441,11 +462,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks textureArrayId = -1; } - if (uniformBufferId != -1) - { - glDeleteBuffer(gl, uniformBufferId); - uniformBufferId = -1; - } + destroyGlBuffer(uniformBuffer); shutdownBuffers(); shutdownInterfaceTexture(); @@ -519,12 +536,16 @@ public class GpuPlugin extends Plugin implements DrawCallbacks glProgram = PROGRAM.compile(gl, template); glUiProgram = UI_PROGRAM.compile(gl, template); - if (useComputeShaders) + if (computeMode == ComputeMode.OPENGL) { glComputeProgram = COMPUTE_PROGRAM.compile(gl, template); glSmallComputeProgram = SMALL_COMPUTE_PROGRAM.compile(gl, template); glUnorderedComputeProgram = UNORDERED_COMPUTE_PROGRAM.compile(gl, template); } + else if (computeMode == ComputeMode.OPENCL) + { + openCLManager.init(gl); + } initUniforms(); } @@ -593,8 +614,8 @@ public class GpuPlugin extends Plugin implements DrawCallbacks -1f, 1f, 0.0f, 0.0f, 0f // top left }); vboUiBuf.rewind(); - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vboUiHandle); - gl.glBufferData(gl.GL_ARRAY_BUFFER, vboUiBuf.capacity() * Float.BYTES, vboUiBuf, gl.GL_STATIC_DRAW); + gl.glBindBuffer(GL_ARRAY_BUFFER, vboUiHandle); + gl.glBufferData(GL_ARRAY_BUFFER, vboUiBuf.capacity() * Float.BYTES, vboUiBuf, gl.GL_STATIC_DRAW); // position attribute gl.glVertexAttribPointer(0, 3, gl.GL_FLOAT, false, 5 * Float.BYTES, 0); @@ -605,7 +626,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks gl.glEnableVertexAttribArray(1); // unbind VBO - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0); + gl.glBindBuffer(GL_ARRAY_BUFFER, 0); } private void shutdownVao() @@ -622,71 +643,49 @@ public class GpuPlugin extends Plugin implements DrawCallbacks private void initBuffers() { - bufferId = glGenBuffers(gl); - uvBufferId = glGenBuffers(gl); - tmpBufferId = glGenBuffers(gl); - tmpUvBufferId = glGenBuffers(gl); - tmpModelBufferId = glGenBuffers(gl); - tmpModelBufferSmallId = glGenBuffers(gl); - tmpModelBufferUnorderedId = glGenBuffers(gl); - tmpOutBufferId = glGenBuffers(gl); - tmpOutUvBufferId = glGenBuffers(gl); + initGlBuffer(sceneVertexBuffer); + initGlBuffer(sceneUvBuffer); + initGlBuffer(tmpVertexBuffer); + initGlBuffer(tmpUvBuffer); + initGlBuffer(tmpModelBufferLarge); + initGlBuffer(tmpModelBufferSmall); + initGlBuffer(tmpModelBufferUnordered); + initGlBuffer(tmpOutBuffer); + initGlBuffer(tmpOutUvBuffer); + } + + private void initGlBuffer(GLBuffer glBuffer) + { + glBuffer.glBufferId = glGenBuffers(gl); } private void shutdownBuffers() { - if (bufferId != -1) - { - glDeleteBuffer(gl, bufferId); - bufferId = -1; - } + destroyGlBuffer(sceneVertexBuffer); + destroyGlBuffer(sceneUvBuffer); - if (uvBufferId != -1) - { - glDeleteBuffer(gl, uvBufferId); - uvBufferId = -1; - } + destroyGlBuffer(tmpVertexBuffer); + destroyGlBuffer(tmpUvBuffer); + destroyGlBuffer(tmpModelBufferLarge); + destroyGlBuffer(tmpModelBufferSmall); + destroyGlBuffer(tmpModelBufferUnordered); + destroyGlBuffer(tmpOutBuffer); + destroyGlBuffer(tmpOutUvBuffer); + } - if (tmpBufferId != -1) + private void destroyGlBuffer(GLBuffer glBuffer) + { + if (glBuffer.glBufferId != -1) { - glDeleteBuffer(gl, tmpBufferId); - tmpBufferId = -1; + glDeleteBuffer(gl, glBuffer.glBufferId); + glBuffer.glBufferId = -1; } + glBuffer.size = -1; - if (tmpUvBufferId != -1) + if (glBuffer.cl_mem != null) { - glDeleteBuffer(gl, tmpUvBufferId); - tmpUvBufferId = -1; - } - - if (tmpModelBufferId != -1) - { - glDeleteBuffer(gl, tmpModelBufferId); - tmpModelBufferId = -1; - } - - if (tmpModelBufferSmallId != -1) - { - glDeleteBuffer(gl, tmpModelBufferSmallId); - tmpModelBufferSmallId = -1; - } - - if (tmpModelBufferUnorderedId != -1) - { - glDeleteBuffer(gl, tmpModelBufferUnorderedId); - tmpModelBufferUnorderedId = -1; - } - - if (tmpOutBufferId != -1) - { - glDeleteBuffer(gl, tmpOutBufferId); - tmpOutBufferId = -1; - } - - if (tmpOutUvBufferId != -1) - { - glDeleteBuffer(gl, tmpOutUvBufferId); - tmpOutUvBufferId = -1; + CL.clReleaseMemObject(glBuffer.cl_mem); + glBuffer.cl_mem = null; } } @@ -709,21 +708,21 @@ public class GpuPlugin extends Plugin implements DrawCallbacks private void initUniformBuffer() { - uniformBufferId = glGenBuffers(gl); - gl.glBindBuffer(gl.GL_UNIFORM_BUFFER, uniformBufferId); - uniformBuffer.clear(); - uniformBuffer.put(new int[8]); + initGlBuffer(uniformBuffer); + + IntBuffer uniformBuf = GpuIntBuffer.allocateDirect(8 + 2048 * 4); + uniformBuf.put(new int[8]); // uniform block final int[] pad = new int[2]; for (int i = 0; i < 2048; i++) { - uniformBuffer.put(Perspective.SINE[i]); - uniformBuffer.put(Perspective.COSINE[i]); - uniformBuffer.put(pad); + uniformBuf.put(Perspective.SINE[i]); + uniformBuf.put(Perspective.COSINE[i]); + uniformBuf.put(pad); // ivec2 alignment in std140 is 16 bytes } - uniformBuffer.flip(); + uniformBuf.flip(); - gl.glBufferData(gl.GL_UNIFORM_BUFFER, uniformBuffer.limit() * Integer.BYTES, uniformBuffer, gl.GL_DYNAMIC_DRAW); - gl.glBindBuffer(gl.GL_UNIFORM_BUFFER, 0); + updateBuffer(uniformBuffer, GL_UNIFORM_BUFFER, uniformBuf.limit() * Integer.BYTES, uniformBuf, GL_DYNAMIC_DRAW, CL_MEM_READ_ONLY); + gl.glBindBuffer(GL_UNIFORM_BUFFER, 0); } private void initAAFbo(int width, int height, int aaSamples) @@ -785,9 +784,11 @@ public class GpuPlugin extends Plugin implements DrawCallbacks invokeOnMainThread(() -> { // UBO. Only the first 32 bytes get modified here, the rest is the constant sin/cos table. - gl.glBindBuffer(gl.GL_UNIFORM_BUFFER, uniformBufferId); - uniformBuffer.clear(); - uniformBuffer + // We can reuse the vertex buffer since it isn't used yet. + vertexBuffer.clear(); + vertexBuffer.ensureCapacity(32); + IntBuffer uniformBuf = vertexBuffer.getBuffer(); + uniformBuf .put(yaw) .put(pitch) .put(client.getCenterX()) @@ -796,12 +797,14 @@ public class GpuPlugin extends Plugin implements DrawCallbacks .put(cameraX) .put(cameraY) .put(cameraZ); - uniformBuffer.flip(); + uniformBuf.flip(); - gl.glBufferSubData(gl.GL_UNIFORM_BUFFER, 0, uniformBuffer.limit() * Integer.BYTES, uniformBuffer); - gl.glBindBuffer(gl.GL_UNIFORM_BUFFER, 0); + gl.glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer.glBufferId); + gl.glBufferSubData(GL_UNIFORM_BUFFER, 0, uniformBuf.limit() * Integer.BYTES, uniformBuf); + gl.glBindBuffer(GL_UNIFORM_BUFFER, 0); - gl.glBindBufferBase(gl.GL_UNIFORM_BUFFER, 0, uniformBufferId); + gl.glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer.glBufferId); + uniformBuf.clear(); }); } @@ -813,7 +816,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks private void postDraw() { - if (!useComputeShaders) + if (computeMode == ComputeMode.NONE) { // Upload buffers vertexBuffer.flip(); @@ -822,12 +825,8 @@ public class GpuPlugin extends Plugin implements DrawCallbacks IntBuffer vertexBuffer = this.vertexBuffer.getBuffer(); FloatBuffer uvBuffer = this.uvBuffer.getBuffer(); - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, tmpBufferId); - gl.glBufferData(gl.GL_ARRAY_BUFFER, vertexBuffer.limit() * Integer.BYTES, vertexBuffer, gl.GL_DYNAMIC_DRAW); - - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, tmpUvBufferId); - gl.glBufferData(gl.GL_ARRAY_BUFFER, uvBuffer.limit() * Float.BYTES, uvBuffer, gl.GL_DYNAMIC_DRAW); - + updateBuffer(tmpVertexBuffer, GL_ARRAY_BUFFER, vertexBuffer.limit() * Integer.BYTES, vertexBuffer, GL_DYNAMIC_DRAW, 0L); + updateBuffer(tmpUvBuffer, GL_ARRAY_BUFFER, uvBuffer.limit() * Float.BYTES, uvBuffer, GL_DYNAMIC_DRAW, 0L); return; } @@ -844,79 +843,91 @@ public class GpuPlugin extends Plugin implements DrawCallbacks IntBuffer modelBufferSmall = this.modelBufferSmall.getBuffer(); IntBuffer modelBufferUnordered = this.modelBufferUnordered.getBuffer(); - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, tmpBufferId); - gl.glBufferData(gl.GL_ARRAY_BUFFER, vertexBuffer.limit() * Integer.BYTES, vertexBuffer, gl.GL_DYNAMIC_DRAW); + // temp buffers + updateBuffer(tmpVertexBuffer, GL_ARRAY_BUFFER, vertexBuffer.limit() * Integer.BYTES, vertexBuffer, GL_DYNAMIC_DRAW, CL_MEM_READ_ONLY); + updateBuffer(tmpUvBuffer, GL_ARRAY_BUFFER, uvBuffer.limit() * Float.BYTES, uvBuffer, GL_DYNAMIC_DRAW, CL_MEM_READ_ONLY); - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, tmpUvBufferId); - gl.glBufferData(gl.GL_ARRAY_BUFFER, uvBuffer.limit() * Float.BYTES, uvBuffer, gl.GL_DYNAMIC_DRAW); - - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, tmpModelBufferId); - gl.glBufferData(gl.GL_ARRAY_BUFFER, modelBuffer.limit() * Integer.BYTES, modelBuffer, gl.GL_DYNAMIC_DRAW); - - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, tmpModelBufferSmallId); - gl.glBufferData(gl.GL_ARRAY_BUFFER, modelBufferSmall.limit() * Integer.BYTES, modelBufferSmall, gl.GL_DYNAMIC_DRAW); - - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, tmpModelBufferUnorderedId); - gl.glBufferData(gl.GL_ARRAY_BUFFER, modelBufferUnordered.limit() * Integer.BYTES, modelBufferUnordered, gl.GL_DYNAMIC_DRAW); + // model buffers + updateBuffer(tmpModelBufferLarge, GL_ARRAY_BUFFER, modelBuffer.limit() * Integer.BYTES, modelBuffer, GL_DYNAMIC_DRAW, CL_MEM_READ_ONLY); + updateBuffer(tmpModelBufferSmall, GL_ARRAY_BUFFER, modelBufferSmall.limit() * Integer.BYTES, modelBufferSmall, GL_DYNAMIC_DRAW, CL_MEM_READ_ONLY); + updateBuffer(tmpModelBufferUnordered, GL_ARRAY_BUFFER, modelBufferUnordered.limit() * Integer.BYTES, modelBufferUnordered, GL_DYNAMIC_DRAW, CL_MEM_READ_ONLY); // Output buffers - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, tmpOutBufferId); - gl.glBufferData(gl.GL_ARRAY_BUFFER, + updateBuffer(tmpOutBuffer, + GL_ARRAY_BUFFER, targetBufferOffset * 16, // each vertex is an ivec4, which is 16 bytes null, - gl.GL_STREAM_DRAW); - - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, tmpOutUvBufferId); - gl.glBufferData(gl.GL_ARRAY_BUFFER, - targetBufferOffset * 16, + GL_STREAM_DRAW, + CL_MEM_WRITE_ONLY); + updateBuffer(tmpOutUvBuffer, + GL_ARRAY_BUFFER, + targetBufferOffset * 16, // each vertex is an ivec4, which is 16 bytes null, - gl.GL_STREAM_DRAW); + GL_STREAM_DRAW, + CL_MEM_WRITE_ONLY); - // Bind UBO to compute programs - gl.glUniformBlockBinding(glSmallComputeProgram, uniBlockSmall, 0); - gl.glUniformBlockBinding(glComputeProgram, uniBlockLarge, 0); + if (computeMode == ComputeMode.OPENCL) + { + // The docs for clEnqueueAcquireGLObjects say all pending GL operations must be completed before calling + // clEnqueueAcquireGLObjects, and recommends calling glFinish() as the only portable way to do that. + // However no issues have been observed from not calling it, and so will leave disabled for now. + // gl.glFinish(); + + openCLManager.compute( + unorderedModels, smallModels, largeModels, + sceneVertexBuffer, sceneUvBuffer, + tmpVertexBuffer, tmpUvBuffer, + tmpModelBufferUnordered, tmpModelBufferSmall, tmpModelBufferLarge, + tmpOutBuffer, tmpOutUvBuffer, + uniformBuffer); + return; + } /* * Compute is split into three separate programs: 'unordered', 'small', and 'large' * to save on GPU resources. Small will sort <= 512 faces, large will do <= 4096. */ + // Bind UBO to compute programs + gl.glUniformBlockBinding(glSmallComputeProgram, uniBlockSmall, 0); + gl.glUniformBlockBinding(glComputeProgram, uniBlockLarge, 0); + // unordered gl.glUseProgram(glUnorderedComputeProgram); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 0, tmpModelBufferUnorderedId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 1, this.bufferId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 2, tmpBufferId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 3, tmpOutBufferId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 4, tmpOutUvBufferId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 5, this.uvBufferId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 6, tmpUvBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 0, tmpModelBufferUnordered.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 1, sceneVertexBuffer.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 2, tmpVertexBuffer.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 3, tmpOutBuffer.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 4, tmpOutUvBuffer.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 5, sceneUvBuffer.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 6, tmpUvBuffer.glBufferId); gl.glDispatchCompute(unorderedModels, 1, 1); // small gl.glUseProgram(glSmallComputeProgram); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 0, tmpModelBufferSmallId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 1, this.bufferId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 2, tmpBufferId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 3, tmpOutBufferId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 4, tmpOutUvBufferId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 5, this.uvBufferId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 6, tmpUvBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 0, tmpModelBufferSmall.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 1, sceneVertexBuffer.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 2, tmpVertexBuffer.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 3, tmpOutBuffer.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 4, tmpOutUvBuffer.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 5, sceneUvBuffer.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 6, tmpUvBuffer.glBufferId); gl.glDispatchCompute(smallModels, 1, 1); // large gl.glUseProgram(glComputeProgram); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 0, tmpModelBufferId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 1, this.bufferId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 2, tmpBufferId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 3, tmpOutBufferId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 4, tmpOutUvBufferId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 5, this.uvBufferId); - gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 6, tmpUvBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 0, tmpModelBufferLarge.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 1, sceneVertexBuffer.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 2, tmpVertexBuffer.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 3, tmpOutBuffer.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 4, tmpOutUvBuffer.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 5, sceneUvBuffer.glBufferId); + gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 6, tmpUvBuffer.glBufferId); gl.glDispatchCompute(largeModels, 1, 1); } @@ -926,7 +937,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks SceneTilePaint paint, int tileZ, int tileX, int tileY, int zoom, int centerX, int centerY) { - if (!useComputeShaders) + if (computeMode == ComputeMode.NONE) { targetBufferOffset += sceneUploader.upload(paint, tileZ, tileX, tileY, @@ -963,7 +974,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks SceneTileModel model, int tileZ, int tileX, int tileY, int zoom, int centerX, int centerY) { - if (!useComputeShaders) + if (computeMode == ComputeMode.NONE) { targetBufferOffset += sceneUploader.upload(model, tileX, tileY, @@ -1131,7 +1142,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks // Ceil the sizes because even if the size is 599.1 we want to treat it as size 600 (i.e. render to the x=599 pixel). renderViewportHeight = (int) Math.ceil(scaleFactorY * (renderViewportHeight)) + padding * 2; - renderViewportWidth = (int) Math.ceil(scaleFactorX * (renderViewportWidth )) + padding * 2; + renderViewportWidth = (int) Math.ceil(scaleFactorX * (renderViewportWidth )) + padding * 2; // Floor the offsets because even if the offset is 4.9, we want to render to the x=4 pixel anyway. renderHeightOff = (int) Math.floor(scaleFactorY * (renderHeightOff)) - padding; @@ -1195,27 +1206,36 @@ public class GpuPlugin extends Plugin implements DrawCallbacks gl.glBindVertexArray(vaoHandle); int vertexBuffer, uvBuffer; - if (useComputeShaders) + if (computeMode != ComputeMode.NONE) { - // Before reading the SSBOs written to from postDrawScene() we must insert a barrier - gl.glMemoryBarrier(gl.GL_SHADER_STORAGE_BARRIER_BIT); + if (computeMode == ComputeMode.OPENGL) + { + // Before reading the SSBOs written to from postDrawScene() we must insert a barrier + gl.glMemoryBarrier(gl.GL_SHADER_STORAGE_BARRIER_BIT); + } + else + { + // Wait for the command queue to finish, so that we know the compute is done + openCLManager.finish(); + } + // Draw using the output buffer of the compute - vertexBuffer = tmpOutBufferId; - uvBuffer = tmpOutUvBufferId; + vertexBuffer = tmpOutBuffer.glBufferId; + uvBuffer = tmpOutUvBuffer.glBufferId; } else { // Only use the temporary buffers, which will contain the full scene - vertexBuffer = tmpBufferId; - uvBuffer = tmpUvBufferId; + vertexBuffer = tmpVertexBuffer.glBufferId; + uvBuffer = tmpUvBuffer.glBufferId; } gl.glEnableVertexAttribArray(0); - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vertexBuffer); + gl.glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); gl.glVertexAttribIPointer(0, 4, gl.GL_INT, 0, 0); gl.glEnableVertexAttribArray(1); - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, uvBuffer); + gl.glBindBuffer(GL_ARRAY_BUFFER, uvBuffer); gl.glVertexAttribPointer(1, 4, gl.GL_FLOAT, false, 0, 0); gl.glDrawArrays(gl.GL_TRIANGLES, 0, targetBufferOffset); @@ -1400,12 +1420,12 @@ public class GpuPlugin extends Plugin implements DrawCallbacks @Subscribe public void onGameStateChanged(GameStateChanged gameStateChanged) { - if (!useComputeShaders || gameStateChanged.getGameState() != GameState.LOGGED_IN) + if (computeMode == ComputeMode.NONE || gameStateChanged.getGameState() != GameState.LOGGED_IN) { return; } - uploadScene(); + invokeOnMainThread(this::uploadScene); } private void uploadScene() @@ -1421,13 +1441,10 @@ public class GpuPlugin extends Plugin implements DrawCallbacks IntBuffer vertexBuffer = this.vertexBuffer.getBuffer(); FloatBuffer uvBuffer = this.uvBuffer.getBuffer(); - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, bufferId); - gl.glBufferData(gl.GL_ARRAY_BUFFER, vertexBuffer.limit() * Integer.BYTES, vertexBuffer, gl.GL_STATIC_COPY); + updateBuffer(sceneVertexBuffer, GL_ARRAY_BUFFER, vertexBuffer.limit() * Integer.BYTES, vertexBuffer, GL_STATIC_COPY, CL_MEM_READ_ONLY); + updateBuffer(sceneUvBuffer, GL_ARRAY_BUFFER, uvBuffer.limit() * Float.BYTES, uvBuffer, GL_STATIC_COPY, CL_MEM_READ_ONLY); - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, uvBufferId); - gl.glBufferData(gl.GL_ARRAY_BUFFER, uvBuffer.limit() * Float.BYTES, uvBuffer, gl.GL_STATIC_COPY); - - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0); + gl.glBindBuffer(GL_ARRAY_BUFFER, 0); vertexBuffer.clear(); uvBuffer.clear(); @@ -1492,7 +1509,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks @Override public void draw(Renderable renderable, int orientation, int pitchSin, int pitchCos, int yawSin, int yawCos, int x, int y, int z, long hash) { - if (!useComputeShaders) + if (computeMode == ComputeMode.NONE) { Model model = renderable instanceof Model ? (Model) renderable : renderable.getModel(); if (model != null) @@ -1673,7 +1690,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks private int getDrawDistance() { - final int limit = useComputeShaders ? MAX_DISTANCE : DEFAULT_DISTANCE; + final int limit = computeMode != ComputeMode.NONE ? MAX_DISTANCE : DEFAULT_DISTANCE; return Ints.constrainToRange(config.drawDistance(), 0, limit); } @@ -1688,4 +1705,36 @@ public class GpuPlugin extends Plugin implements DrawCallbacks runnable.run(); } } + + private void updateBuffer(GLBuffer glBuffer, int target, int size, Buffer data, int usage, long clFlags) + { + gl.glBindBuffer(target, glBuffer.glBufferId); + if (size > glBuffer.size) + { + log.trace("Buffer resize: {} {} -> {}", glBuffer, glBuffer.size, size); + + glBuffer.size = size; + gl.glBufferData(target, size, data, usage); + + if (computeMode == ComputeMode.OPENCL) + { + if (glBuffer.cl_mem != null) + { + CL.clReleaseMemObject(glBuffer.cl_mem); + } + if (size == 0) + { + glBuffer.cl_mem = null; + } + else + { + glBuffer.cl_mem = clCreateFromGLBuffer(openCLManager.context, clFlags, glBuffer.glBufferId, null); + } + } + } + else if (data != null) + { + gl.glBufferSubData(target, 0, size, data); + } + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/OpenCLManager.java b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/OpenCLManager.java new file mode 100644 index 0000000000..77c2f9b575 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/OpenCLManager.java @@ -0,0 +1,521 @@ +/* + * Copyright (c) 2021, Adam + * 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.gpu; + +import com.google.common.base.Charsets; +import com.jogamp.nativewindow.NativeSurface; +import com.jogamp.opengl.GL4; +import com.jogamp.opengl.GLContext; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Objects; +import javax.inject.Singleton; +import jogamp.opengl.GLContextImpl; +import jogamp.opengl.GLDrawableImpl; +import jogamp.opengl.egl.EGLContext; +import jogamp.opengl.macosx.cgl.CGL; +import jogamp.opengl.windows.wgl.WindowsWGLContext; +import jogamp.opengl.x11.glx.X11GLXContext; +import lombok.extern.slf4j.Slf4j; +import net.runelite.client.plugins.gpu.template.Template; +import net.runelite.client.util.OSType; +import org.jocl.CL; +import static org.jocl.CL.*; +import org.jocl.CLException; +import org.jocl.Pointer; +import org.jocl.Sizeof; +import org.jocl.cl_command_queue; +import org.jocl.cl_context; +import org.jocl.cl_context_properties; +import org.jocl.cl_device_id; +import org.jocl.cl_event; +import org.jocl.cl_kernel; +import org.jocl.cl_mem; +import org.jocl.cl_platform_id; +import org.jocl.cl_program; + +@Singleton +@Slf4j +class OpenCLManager +{ + private static final String GL_SHARING_PLATFORM_EXT = "cl_khr_gl_sharing"; + + private static final String KERNEL_NAME_UNORDERED = "computeUnordered"; + private static final String KERNEL_NAME_LARGE = "computeLarge"; + + private static final int MIN_WORK_GROUP_SIZE = 256; + private static final int SMALL_SIZE = GpuPlugin.SMALL_TRIANGLE_COUNT; + private static final int LARGE_SIZE = GpuPlugin.MAX_TRIANGLE; + // struct shared_data { + // int totalNum[12]; + // int totalDistance[12]; + // int totalMappedNum[18]; + // int min10; + // int dfs[0]; + // }; + private static final int SHARED_SIZE = 12 + 12 + 18 + 1; // in ints + + // The number of faces each worker processes in the two kernels + private int largeFaceCount; + private int smallFaceCount; + + private cl_platform_id platform; + private cl_device_id device; + cl_context context; + private cl_command_queue commandQueue; + + private cl_program programUnordered; + private cl_program programSmall; + private cl_program programLarge; + + private cl_kernel kernelUnordered; + private cl_kernel kernelSmall; + private cl_kernel kernelLarge; + + void init(GL4 gl) + { + CL.setExceptionsEnabled(true); + + switch (OSType.getOSType()) + { + case Windows: + case Linux: + initPlatform(); + initDevice(); + initContext(gl); + break; + case MacOS: + initMacOS(gl); + break; + default: + throw new RuntimeException("Unsupported OS Type " + OSType.getOSType().name()); + } + ensureMinWorkGroupSize(); + initQueue(); + compilePrograms(); + } + + void cleanup() + { + if (programUnordered != null) + { + CL.clReleaseProgram(programUnordered); + programUnordered = null; + } + + if (programSmall != null) + { + CL.clReleaseProgram(programSmall); + programSmall = null; + } + + if (programLarge != null) + { + CL.clReleaseProgram(programLarge); + programLarge = null; + } + + if (kernelUnordered != null) + { + CL.clReleaseKernel(kernelUnordered); + kernelUnordered = null; + } + + if (kernelSmall != null) + { + CL.clReleaseKernel(kernelSmall); + kernelSmall = null; + } + + if (kernelLarge != null) + { + CL.clReleaseKernel(kernelLarge); + kernelLarge = null; + } + + if (commandQueue != null) + { + CL.clReleaseCommandQueue(commandQueue); + commandQueue = null; + } + + if (context != null) + { + CL.clReleaseContext(context); + context = null; + } + + if (device != null) + { + CL.clReleaseDevice(device); + device = null; + } + } + + private String logPlatformInfo(cl_platform_id platform, int param) + { + long[] size = new long[1]; + clGetPlatformInfo(platform, param, 0, null, size); + + byte[] buffer = new byte[(int) size[0]]; + clGetPlatformInfo(platform, param, buffer.length, Pointer.to(buffer), null); + String platformInfo = new String(buffer, Charsets.UTF_8); + log.debug("Platform: {}, {}", stringFor_cl_platform_info(param), platformInfo); + return platformInfo; + } + + private void logBuildInfo(cl_program program, int param) + { + long[] size = new long[1]; + clGetProgramBuildInfo(program, device, param, 0, null, size); + + ByteBuffer buffer = ByteBuffer.allocateDirect((int) size[0]); + clGetProgramBuildInfo(program, device, param, buffer.limit(), Pointer.toBuffer(buffer), null); + + switch (param) + { + case CL_PROGRAM_BUILD_STATUS: + log.debug("Build status: {}, {}", stringFor_cl_program_build_info(param), stringFor_cl_build_status(buffer.getInt())); + break; + case CL_PROGRAM_BINARY_TYPE: + log.debug("Binary type: {}, {}", stringFor_cl_program_build_info(param), stringFor_cl_program_binary_type(buffer.getInt())); + break; + case CL_PROGRAM_BUILD_LOG: + String buildLog = StandardCharsets.US_ASCII.decode(buffer).toString(); + log.trace("Build log: {}, {}", stringFor_cl_program_build_info(param), buildLog); + break; + case CL_PROGRAM_BUILD_OPTIONS: + String message = StandardCharsets.US_ASCII.decode(buffer).toString(); + log.debug("Build options: {}, {}", stringFor_cl_program_build_info(param), message); + break; + default: + throw new IllegalArgumentException(); + } + } + + private void initPlatform() + { + int[] platformCount = new int[1]; + clGetPlatformIDs(0, null, platformCount); + if (platformCount[0] == 0) + { + throw new RuntimeException("No compute platforms found"); + } + + cl_platform_id[] platforms = new cl_platform_id[platformCount[0]]; + clGetPlatformIDs(platforms.length, platforms, null); + + for (cl_platform_id platform : platforms) + { + log.debug("Found cl_platform_id {}", platform); + logPlatformInfo(platform, CL_PLATFORM_PROFILE); + logPlatformInfo(platform, CL_PLATFORM_VERSION); + logPlatformInfo(platform, CL_PLATFORM_NAME); + logPlatformInfo(platform, CL_PLATFORM_VENDOR); + String[] extensions = logPlatformInfo(platform, CL_PLATFORM_EXTENSIONS).split(" "); + if (Arrays.stream(extensions).noneMatch(s -> s.equals(GL_SHARING_PLATFORM_EXT))) + { + throw new RuntimeException("Platform does not support OpenGL buffer sharing"); + } + } + + platform = platforms[0]; + log.debug("Selected cl_platform_id {}", platform); + } + + private void initDevice() + { + int[] deviceCount = new int[1]; + clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 0, null, deviceCount); + if (deviceCount[0] == 0) + { + throw new RuntimeException("No compute devices found"); + } + + cl_device_id[] devices = new cl_device_id[(int) deviceCount[0]]; + clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, devices.length, devices, null); + + for (cl_device_id device : devices) + { + long[] size = new long[1]; + clGetDeviceInfo(device, CL_DEVICE_EXTENSIONS, 0, null, size); + + byte[] devInfoBuf = new byte[(int) size[0]]; + clGetDeviceInfo(device, CL_DEVICE_EXTENSIONS, devInfoBuf.length, Pointer.to(devInfoBuf), null); + + log.debug("Found cl_device_id: {}", device); + log.debug("Device extensions: {}", new String(devInfoBuf, Charsets.UTF_8)); + } + + device = devices[0]; + log.debug("Selected cl_device_id {}", device); + } + + private void initContext(GL4 gl) + { + // set computation platform + cl_context_properties contextProps = new cl_context_properties(); + contextProps.addProperty(CL_CONTEXT_PLATFORM, platform); + + // pull gl context + GLContext glContext = gl.getContext(); + log.debug("Got GLContext of type {}", glContext.getClass().getSimpleName()); + if (!glContext.isCurrent()) + { + throw new RuntimeException("Can't create OpenCL context from inactive GL Context"); + } + + // get correct props based on os + long glContextHandle = glContext.getHandle(); + GLContextImpl glContextImpl = (GLContextImpl) glContext; + GLDrawableImpl glDrawableImpl = glContextImpl.getDrawableImpl(); + NativeSurface nativeSurface = glDrawableImpl.getNativeSurface(); + + if (glContext instanceof X11GLXContext) + { + long displayHandle = nativeSurface.getDisplayHandle(); + contextProps.addProperty(CL_GL_CONTEXT_KHR, glContextHandle); + contextProps.addProperty(CL_GLX_DISPLAY_KHR, displayHandle); + } + else if (glContext instanceof WindowsWGLContext) + { + long surfaceHandle = nativeSurface.getSurfaceHandle(); + contextProps.addProperty(CL_GL_CONTEXT_KHR, glContextHandle); + contextProps.addProperty(CL_WGL_HDC_KHR, surfaceHandle); + } + else if (glContext instanceof EGLContext) + { + long displayHandle = nativeSurface.getDisplayHandle(); + contextProps.addProperty(CL_GL_CONTEXT_KHR, glContextHandle); + contextProps.addProperty(CL_EGL_DISPLAY_KHR, displayHandle); + } + + log.debug("Creating context with props: {}", contextProps); + context = clCreateContext(contextProps, 1, new cl_device_id[]{device}, null, null, null); + log.debug("Created compute context {}", context); + } + + private void initMacOS(GL4 gl) + { + // get sharegroup from gl context + GLContext glContext = gl.getContext(); + if (!glContext.isCurrent()) + { + throw new RuntimeException("Can't create context from inactive GL"); + } + long cglContext = CGL.CGLGetCurrentContext(); + long cglShareGroup = CGL.CGLGetShareGroup(cglContext); + + // build context props + cl_context_properties contextProps = new cl_context_properties(); + contextProps.addProperty(CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE, cglShareGroup); + + // ask macos to make the context for us + log.debug("Creating context with props: {}", contextProps); + context = clCreateContext(contextProps, 0, null, null, null, null); + + // pull the compute device out of the provided context + device = new cl_device_id(); + clGetGLContextInfoAPPLE(context, cglContext, CL_CGL_DEVICE_FOR_CURRENT_VIRTUAL_SCREEN_APPLE, Sizeof.cl_device_id, Pointer.to(device), null); + + log.debug("Got macOS CLGL compute device {}", device); + } + + private void ensureMinWorkGroupSize() + { + long[] maxWorkGroupSize = new long[1]; + clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, Sizeof.size_t, Pointer.to(maxWorkGroupSize), null); + log.debug("Device CL_DEVICE_MAX_WORK_GROUP_SIZE: {}", maxWorkGroupSize[0]); + + if (maxWorkGroupSize[0] < MIN_WORK_GROUP_SIZE) + { + throw new RuntimeException("Compute device does not support min work group size " + MIN_WORK_GROUP_SIZE); + } + + // Largest power of 2 less than or equal to maxWorkGroupSize + int groupSize = 0x80000000 >>> Integer.numberOfLeadingZeros((int) maxWorkGroupSize[0]); + largeFaceCount = LARGE_SIZE / (Math.min(groupSize, LARGE_SIZE)); + smallFaceCount = SMALL_SIZE / (Math.min(groupSize, SMALL_SIZE)); + + log.debug("Face counts: small: {}, large: {}", smallFaceCount, largeFaceCount); + } + + private void initQueue() + { + long[] l = new long[1]; + clGetDeviceInfo(device, CL_DEVICE_QUEUE_PROPERTIES, Sizeof.cl_long, Pointer.to(l), null); + + commandQueue = clCreateCommandQueue(context, device, l[0] & CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE, null); + log.debug("Created command_queue {}, properties {}", commandQueue, l[0] & CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE); + } + + private cl_program compileProgram(String programSource) + { + log.trace("Compiling program:\n {}", programSource); + cl_program program = clCreateProgramWithSource(context, 1, new String[]{programSource}, null, null); + + try + { + clBuildProgram(program, 0, null, null, null, null); + } + catch (CLException e) + { + logBuildInfo(program, CL_PROGRAM_BUILD_LOG); + throw e; + } + + logBuildInfo(program, CL_PROGRAM_BUILD_STATUS); + logBuildInfo(program, CL_PROGRAM_BINARY_TYPE); + logBuildInfo(program, CL_PROGRAM_BUILD_OPTIONS); + logBuildInfo(program, CL_PROGRAM_BUILD_LOG); + return program; + } + + private cl_kernel getKernel(cl_program program, String kernelName) + { + cl_kernel kernel = clCreateKernel(program, kernelName, null); + log.debug("Loaded kernel {} for program {}", kernelName, program); + return kernel; + } + + private void compilePrograms() + { + Template templateSmall = new Template() + .addInclude(OpenCLManager.class) + .add(key -> key.equals("FACE_COUNT") ? ("#define FACE_COUNT " + smallFaceCount) : null); + Template templateLarge = new Template() + .addInclude(OpenCLManager.class) + .add(key -> key.equals("FACE_COUNT") ? ("#define FACE_COUNT " + largeFaceCount) : null); + + String unordered = new Template() + .addInclude(OpenCLManager.class) + .load("comp_unordered.cl"); + String small = templateSmall.load("comp.cl"); + String large = templateLarge.load("comp.cl"); + + programUnordered = compileProgram(unordered); + programSmall = compileProgram(small); + programLarge = compileProgram(large); + + kernelUnordered = getKernel(programUnordered, KERNEL_NAME_UNORDERED); + kernelSmall = getKernel(programSmall, KERNEL_NAME_LARGE); + kernelLarge = getKernel(programLarge, KERNEL_NAME_LARGE); + } + + void compute(int unorderedModels, int smallModels, int largeModels, + GLBuffer sceneVertexBuffer, + GLBuffer sceneUvBuffer, + GLBuffer vertexBuffer, + GLBuffer uvBuffer, + GLBuffer unorderedBuffer, + GLBuffer smallBuffer, + GLBuffer largeBuffer, + GLBuffer outVertexBuffer, + GLBuffer outUvBuffer, + GLBuffer uniformBuffer + ) + { + cl_mem[] glBuffersAll = { + sceneVertexBuffer.cl_mem, + sceneUvBuffer.cl_mem, + unorderedBuffer.cl_mem, + smallBuffer.cl_mem, + largeBuffer.cl_mem, + vertexBuffer.cl_mem, + uvBuffer.cl_mem, + outVertexBuffer.cl_mem, + outUvBuffer.cl_mem, + uniformBuffer.cl_mem, + }; + cl_mem[] glBuffers = Arrays.stream(glBuffersAll) + .filter(Objects::nonNull) + .toArray(cl_mem[]::new); + + cl_event acquireGLBuffers = new cl_event(); + clEnqueueAcquireGLObjects(commandQueue, glBuffers.length, glBuffers, 0, null, acquireGLBuffers); + + cl_event[] computeEvents = { + new cl_event(), + new cl_event(), + new cl_event() + }; + int numComputeEvents = 0; + + if (unorderedModels > 0) + { + clSetKernelArg(kernelUnordered, 0, Sizeof.cl_mem, unorderedBuffer.ptr()); + clSetKernelArg(kernelUnordered, 1, Sizeof.cl_mem, sceneVertexBuffer.ptr()); + clSetKernelArg(kernelUnordered, 2, Sizeof.cl_mem, vertexBuffer.ptr()); + clSetKernelArg(kernelUnordered, 3, Sizeof.cl_mem, sceneUvBuffer.ptr()); + clSetKernelArg(kernelUnordered, 4, Sizeof.cl_mem, uvBuffer.ptr()); + clSetKernelArg(kernelUnordered, 5, Sizeof.cl_mem, outVertexBuffer.ptr()); + clSetKernelArg(kernelUnordered, 6, Sizeof.cl_mem, outUvBuffer.ptr()); + + // queue compute call after acquireGLBuffers + clEnqueueNDRangeKernel(commandQueue, kernelUnordered, 1, null, + new long[]{unorderedModels * 6L}, new long[]{6}, 1, new cl_event[]{acquireGLBuffers}, computeEvents[numComputeEvents++]); + } + + if (smallModels > 0) + { + clSetKernelArg(kernelSmall, 0, (SHARED_SIZE + SMALL_SIZE) * Integer.BYTES, null); + clSetKernelArg(kernelSmall, 1, Sizeof.cl_mem, smallBuffer.ptr()); + clSetKernelArg(kernelSmall, 2, Sizeof.cl_mem, sceneVertexBuffer.ptr()); + clSetKernelArg(kernelSmall, 3, Sizeof.cl_mem, vertexBuffer.ptr()); + clSetKernelArg(kernelSmall, 4, Sizeof.cl_mem, sceneUvBuffer.ptr()); + clSetKernelArg(kernelSmall, 5, Sizeof.cl_mem, uvBuffer.ptr()); + clSetKernelArg(kernelSmall, 6, Sizeof.cl_mem, outVertexBuffer.ptr()); + clSetKernelArg(kernelSmall, 7, Sizeof.cl_mem, outUvBuffer.ptr()); + clSetKernelArg(kernelSmall, 8, Sizeof.cl_mem, uniformBuffer.ptr()); + + clEnqueueNDRangeKernel(commandQueue, kernelSmall, 1, null, + new long[]{smallModels * (SMALL_SIZE / smallFaceCount)}, new long[]{SMALL_SIZE / smallFaceCount}, 1, new cl_event[]{acquireGLBuffers}, computeEvents[numComputeEvents++]); + } + + if (largeModels > 0) + { + clSetKernelArg(kernelLarge, 0, (SHARED_SIZE + LARGE_SIZE) * Integer.BYTES, null); + clSetKernelArg(kernelLarge, 1, Sizeof.cl_mem, largeBuffer.ptr()); + clSetKernelArg(kernelLarge, 2, Sizeof.cl_mem, sceneVertexBuffer.ptr()); + clSetKernelArg(kernelLarge, 3, Sizeof.cl_mem, vertexBuffer.ptr()); + clSetKernelArg(kernelLarge, 4, Sizeof.cl_mem, sceneUvBuffer.ptr()); + clSetKernelArg(kernelLarge, 5, Sizeof.cl_mem, uvBuffer.ptr()); + clSetKernelArg(kernelLarge, 6, Sizeof.cl_mem, outVertexBuffer.ptr()); + clSetKernelArg(kernelLarge, 7, Sizeof.cl_mem, outUvBuffer.ptr()); + clSetKernelArg(kernelLarge, 8, Sizeof.cl_mem, uniformBuffer.ptr()); + + clEnqueueNDRangeKernel(commandQueue, kernelLarge, 1, null, + new long[]{(long) largeModels * (LARGE_SIZE / largeFaceCount)}, new long[]{LARGE_SIZE / largeFaceCount}, 1, new cl_event[]{acquireGLBuffers}, computeEvents[numComputeEvents++]); + } + + clEnqueueReleaseGLObjects(commandQueue, glBuffers.length, glBuffers, numComputeEvents, computeEvents, null); + } + + void finish() + { + clFinish(commandQueue); + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePlugin.java index d28f4b0323..f3d9b513b3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePlugin.java @@ -128,7 +128,6 @@ public class GrandExchangePlugin extends Plugin private static final String BUY_LIMIT_GE_TEXT = "
Buy limit: "; private static final String BUY_LIMIT_KEY = "buylimit"; - private static final Gson GSON = new Gson(); private static final Duration BUY_LIMIT_RESET = Duration.ofHours(4); static final String SEARCH_GRAND_EXCHANGE = "Search Grand Exchange"; @@ -183,6 +182,9 @@ public class GrandExchangePlugin extends Plugin @Inject private ConfigManager configManager; + @Inject + private Gson gson; + private Widget grandExchangeText; private Widget grandExchangeItem; private String grandExchangeExamine; @@ -253,12 +255,12 @@ public class GrandExchangePlugin extends Plugin { return null; } - return GSON.fromJson(offer, SavedOffer.class); + return gson.fromJson(offer, SavedOffer.class); } private void setOffer(int slot, SavedOffer offer) { - configManager.setRSProfileConfiguration("geoffer", Integer.toString(slot), GSON.toJson(offer)); + configManager.setRSProfileConfiguration("geoffer", Integer.toString(slot), gson.toJson(offer)); } private void deleteOffer(int slot) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsConfig.java index 6540aa6e80..96f454cd1c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsConfig.java @@ -156,7 +156,7 @@ public interface GroundItemsConfig extends Config @ConfigItem( keyName = "notifyTier", - name = "Notify >= Tier", + name = "Notify tier", description = "Configures which price tiers will trigger a notification on drop", position = 8 ) @@ -211,7 +211,7 @@ public interface GroundItemsConfig extends Config @ConfigItem( keyName = "hideUnderValue", - name = "Hide < Value", + name = "Hide under value", description = "Configures hidden ground items under both GE and HA value", position = 13 ) @@ -223,7 +223,7 @@ public interface GroundItemsConfig extends Config @Alpha @ConfigItem( keyName = "defaultColor", - name = "Default items color", + name = "Default items", description = "Configures the color for default, non-highlighted items", position = 14 ) @@ -235,7 +235,7 @@ public interface GroundItemsConfig extends Config @Alpha @ConfigItem( keyName = "highlightedColor", - name = "Highlighted items color", + name = "Highlighted items", description = "Configures the color for highlighted items", position = 15 ) @@ -247,7 +247,7 @@ public interface GroundItemsConfig extends Config @Alpha @ConfigItem( keyName = "hiddenColor", - name = "Hidden items color", + name = "Hidden items", description = "Configures the color for hidden items in right-click menu and when holding ALT", position = 16 ) @@ -259,7 +259,7 @@ public interface GroundItemsConfig extends Config @Alpha @ConfigItem( keyName = "lowValueColor", - name = "Low value items color", + name = "Low value items", description = "Configures the color for low value items", position = 17 ) @@ -282,7 +282,7 @@ public interface GroundItemsConfig extends Config @Alpha @ConfigItem( keyName = "mediumValueColor", - name = "Medium value items color", + name = "Medium value items", description = "Configures the color for medium value items", position = 19 ) @@ -305,7 +305,7 @@ public interface GroundItemsConfig extends Config @Alpha @ConfigItem( keyName = "highValueColor", - name = "High value items color", + name = "High value items", description = "Configures the color for high value items", position = 21 ) @@ -328,7 +328,7 @@ public interface GroundItemsConfig extends Config @Alpha @ConfigItem( keyName = "insaneValueColor", - name = "Insane value items color", + name = "Insane value items", description = "Configures the color for insane value items", position = 23 ) @@ -361,8 +361,8 @@ public interface GroundItemsConfig extends Config @ConfigItem( keyName = "doubleTapDelay", - name = "Delay for double-tap ALT to hide", - description = "Decrease this number if you accidentally hide ground items often. (0 = Disabled)", + name = "Double-tap delay", + description = "Delay for the double-tap ALT to hide ground items. 0 to disable.", position = 26 ) @Units(Units.MILLISECONDS) @@ -373,7 +373,7 @@ public interface GroundItemsConfig extends Config @ConfigItem( keyName = "collapseEntries", - name = "Collapse ground item menu entries", + name = "Collapse ground item menu", description = "Collapses ground item menu entries together and appends count", position = 27 ) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsOverlay.java index dbd1db7ddd..f565652b11 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsOverlay.java @@ -58,7 +58,6 @@ import net.runelite.client.ui.overlay.components.BackgroundComponent; import net.runelite.client.ui.overlay.components.ProgressPieComponent; import net.runelite.client.ui.overlay.components.TextComponent; import net.runelite.client.util.QuantityFormatter; -import org.apache.commons.lang3.ArrayUtils; public class GroundItemsOverlay extends Overlay { @@ -76,8 +75,14 @@ public class GroundItemsOverlay extends Overlay private static final Duration DESPAWN_TIME_INSTANCE = Duration.ofMinutes(30); private static final Duration DESPAWN_TIME_LOOT = Duration.ofMinutes(2); private static final Duration DESPAWN_TIME_DROP = Duration.ofMinutes(3); + private static final Duration DESPAWN_TIME_TABLE = Duration.ofMinutes(10); private static final int KRAKEN_REGION = 9116; private static final int KBD_NMZ_REGION = 9033; + private static final int ZILYANA_REGION = 11602; + private static final int GRAARDOR_REGION = 11347; + private static final int KRIL_TSUTSAROTH_REGION = 11603; + private static final int KREEARRA_REGION = 11346; + private static final int NIGHTMARE_REGION = 15515; private final Client client; private final GroundItemsPlugin plugin; @@ -394,8 +399,11 @@ public class GroundItemsOverlay extends Overlay private Instant calculateDespawnTime(GroundItem groundItem) { - // We can only accurately guess despawn times for our own pvm loot and dropped items - if (groundItem.getLootType() != LootType.PVM && groundItem.getLootType() != LootType.DROPPED) + // We can only accurately guess despawn times for our own pvm loot, dropped items, + // and items we placed on tables + if (groundItem.getLootType() != LootType.PVM + && groundItem.getLootType() != LootType.DROPPED + && groundItem.getLootType() != LootType.TABLE) { return null; } @@ -410,35 +418,31 @@ public class GroundItemsOverlay extends Overlay return null; } - Instant despawnTime; + final Instant despawnTime; Instant now = Instant.now(); if (client.isInInstancedRegion()) { - // Items in the Kraken instance appear to never despawn? - if (isInKraken()) + final int playerRegionID = WorldPoint.fromLocalInstance(client, client.getLocalPlayer().getLocalLocation()).getRegionID(); + if (playerRegionID == KRAKEN_REGION) { + // Items in the Kraken instance never despawn return null; } - else if (isInKBDorNMZ()) + else if (playerRegionID == KBD_NMZ_REGION) { // NMZ and the KBD lair uses the same region ID but NMZ uses planes 1-3 and KBD uses plane 0 if (client.getLocalPlayer().getWorldLocation().getPlane() == 0) { // Items in the KBD instance use the standard despawn timer - if (groundItem.getLootType() == LootType.DROPPED) - { - despawnTime = spawnTime.plus(DESPAWN_TIME_DROP); - } - else - { - despawnTime = spawnTime.plus(DESPAWN_TIME_LOOT); - } + despawnTime = spawnTime.plus(groundItem.getLootType() == LootType.DROPPED + ? DESPAWN_TIME_DROP + : DESPAWN_TIME_LOOT); } else { - // Dropped items in the NMZ instance appear to never despawn? if (groundItem.getLootType() == LootType.DROPPED) { + // Dropped items in the NMZ instance never despawn return null; } else @@ -447,6 +451,14 @@ public class GroundItemsOverlay extends Overlay } } } + else if (playerRegionID == ZILYANA_REGION || playerRegionID == GRAARDOR_REGION || + playerRegionID == KRIL_TSUTSAROTH_REGION || playerRegionID == KREEARRA_REGION || playerRegionID == NIGHTMARE_REGION) + { + // GWD and Nightmare instances use the normal despawn timers + despawnTime = spawnTime.plus(groundItem.getLootType() == LootType.DROPPED + ? DESPAWN_TIME_DROP + : DESPAWN_TIME_LOOT); + } else { despawnTime = spawnTime.plus(DESPAWN_TIME_INSTANCE); @@ -454,13 +466,17 @@ public class GroundItemsOverlay extends Overlay } else { - if (groundItem.getLootType() == LootType.DROPPED) + switch (groundItem.getLootType()) { - despawnTime = spawnTime.plus(DESPAWN_TIME_DROP); - } - else - { - despawnTime = spawnTime.plus(DESPAWN_TIME_LOOT); + case DROPPED: + despawnTime = spawnTime.plus(DESPAWN_TIME_DROP); + break; + case TABLE: + despawnTime = spawnTime.plus(DESPAWN_TIME_TABLE); + break; + default: + despawnTime = spawnTime.plus(DESPAWN_TIME_LOOT); + break; } } @@ -475,8 +491,11 @@ public class GroundItemsOverlay extends Overlay private Color getItemTimerColor(GroundItem groundItem) { - // We can only accurately guess despawn times for our own pvm loot and dropped items - if (groundItem.getLootType() != LootType.PVM && groundItem.getLootType() != LootType.DROPPED) + // We can only accurately guess despawn times for our own pvm loot, dropped items, + // and items we placed on tables + if (groundItem.getLootType() != LootType.PVM + && groundItem.getLootType() != LootType.DROPPED + && groundItem.getLootType() != LootType.TABLE) { return null; } @@ -561,14 +580,4 @@ public class GroundItemsOverlay extends Overlay } } - - private boolean isInKraken() - { - return ArrayUtils.contains(client.getMapRegions(), KRAKEN_REGION); - } - - private boolean isInKBDorNMZ() - { - return ArrayUtils.contains(client.getMapRegions(), KBD_NMZ_REGION); - } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsPlugin.java index 0c8db3a0e1..b7a8fc6500 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsPlugin.java @@ -52,11 +52,13 @@ import lombok.Setter; import lombok.Value; import net.runelite.api.Client; import net.runelite.api.GameState; +import net.runelite.api.InventoryID; +import net.runelite.api.Item; import net.runelite.api.ItemComposition; +import net.runelite.api.ItemContainer; import net.runelite.api.ItemID; import net.runelite.api.MenuAction; import net.runelite.api.MenuEntry; -import net.runelite.api.Player; import net.runelite.api.Tile; import net.runelite.api.TileItem; import net.runelite.api.coords.WorldPoint; @@ -180,6 +182,7 @@ public class GroundItemsPlugin extends Plugin private LoadingCache highlightedItems; private LoadingCache hiddenItems; private final Queue droppedItemQueue = EvictingQueue.create(16); // recently dropped items + private int lastUsedItem; @Provides GroundItemsConfig provideConfig(ConfigManager configManager) @@ -194,6 +197,7 @@ public class GroundItemsPlugin extends Plugin mouseManager.registerMouseListener(inputListener); keyManager.registerKeyListener(inputListener); executor.execute(this::reset); + lastUsedItem = -1; } @Override @@ -384,6 +388,7 @@ public class GroundItemsPlugin extends Plugin final int realItemId = itemComposition.getNote() != -1 ? itemComposition.getLinkedNoteId() : itemId; final int alchPrice = itemComposition.getHaPrice(); final boolean dropped = tile.getWorldLocation().equals(client.getLocalPlayer().getWorldLocation()) && droppedItemQueue.remove(itemId); + final boolean table = itemId == lastUsedItem && tile.getItemLayer().getHeight() > 0; final GroundItem groundItem = GroundItem.builder() .id(itemId) @@ -394,12 +399,11 @@ public class GroundItemsPlugin extends Plugin .haPrice(alchPrice) .height(tile.getItemLayer().getHeight()) .tradeable(itemComposition.isTradeable()) - .lootType(dropped ? LootType.DROPPED : LootType.UNKNOWN) + .lootType(dropped ? LootType.DROPPED : (table ? LootType.TABLE : LootType.UNKNOWN)) .spawnTime(Instant.now()) .stackable(itemComposition.isStackable()) .build(); - // Update item price in case it is coins if (realItemId == COINS) { @@ -638,11 +642,8 @@ public class GroundItemsPlugin extends Plugin return; } - final Player local = client.getLocalPlayer(); final StringBuilder notificationStringBuilder = new StringBuilder() - .append('[') - .append(local.getName()) - .append("] received a ") + .append("You received a ") .append(dropType) .append(" drop: ") .append(item.getName()); @@ -687,5 +688,21 @@ public class GroundItemsPlugin extends Plugin // item spawns that are drops droppedItemQueue.add(itemId); } + else if (menuOptionClicked.getMenuAction() == MenuAction.ITEM_USE_ON_GAME_OBJECT) + { + final ItemContainer inventory = client.getItemContainer(InventoryID.INVENTORY); + if (inventory == null) + { + return; + } + + final Item clickedItem = inventory.getItem(menuOptionClicked.getSelectedItemIndex()); + if (clickedItem == null) + { + return; + } + + lastUsedItem = clickedItem.getId(); + } } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/LootType.java b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/LootType.java index b434298faf..604815732f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/LootType.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/LootType.java @@ -27,6 +27,7 @@ package net.runelite.client.plugins.grounditems; enum LootType { UNKNOWN, + TABLE, DROPPED, PVP, PVM; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPlugin.java index 73e93f86ad..81ac210bfc 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPlugin.java @@ -34,6 +34,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; import javax.inject.Inject; import lombok.AccessLevel; @@ -51,6 +52,7 @@ import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.MenuEntryAdded; import net.runelite.api.events.MenuOptionClicked; import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.game.chatbox.ChatboxPanelManager; import net.runelite.client.plugins.Plugin; @@ -72,8 +74,6 @@ public class GroundMarkerPlugin extends Plugin private static final String WALK_HERE = "Walk here"; private static final String REGION_PREFIX = "region_"; - private static final Gson GSON = new Gson(); - @Getter(AccessLevel.PACKAGE) private final List points = new ArrayList<>(); @@ -98,7 +98,16 @@ public class GroundMarkerPlugin extends Plugin @Inject private ChatboxPanelManager chatboxPanelManager; - private void savePoints(int regionId, Collection points) + @Inject + private EventBus eventBus; + + @Inject + private GroundMarkerSharingManager sharingManager; + + @Inject + private Gson gson; + + void savePoints(int regionId, Collection points) { if (points == null || points.isEmpty()) { @@ -106,11 +115,11 @@ public class GroundMarkerPlugin extends Plugin return; } - String json = GSON.toJson(points); + String json = gson.toJson(points); configManager.setConfiguration(CONFIG_GROUP, REGION_PREFIX + regionId, json); } - private Collection getPoints(int regionId) + Collection getPoints(int regionId) { String json = configManager.getConfiguration(CONFIG_GROUP, REGION_PREFIX + regionId); if (Strings.isNullOrEmpty(json)) @@ -119,7 +128,7 @@ public class GroundMarkerPlugin extends Plugin } // CHECKSTYLE:OFF - return GSON.fromJson(json, new TypeToken>(){}.getType()); + return gson.fromJson(json, new TypeToken>(){}.getType()); // CHECKSTYLE:ON } @@ -129,7 +138,7 @@ public class GroundMarkerPlugin extends Plugin return configManager.getConfig(GroundMarkerConfig.class); } - private void loadPoints() + void loadPoints() { points.clear(); @@ -181,14 +190,18 @@ public class GroundMarkerPlugin extends Plugin { overlayManager.add(overlay); overlayManager.add(minimapOverlay); + sharingManager.addMenuOptions(); loadPoints(); + eventBus.register(sharingManager); } @Override public void shutDown() { + eventBus.unregister(sharingManager); overlayManager.remove(overlay); overlayManager.remove(minimapOverlay); + sharingManager.removeMenuOptions(); points.clear(); } @@ -301,21 +314,22 @@ public class GroundMarkerPlugin extends Plugin WorldPoint worldPoint = WorldPoint.fromLocalInstance(client, localPoint); final int regionId = worldPoint.getRegionID(); + GroundMarkerPoint searchPoint = new GroundMarkerPoint(regionId, worldPoint.getRegionX(), worldPoint.getRegionY(), client.getPlane(), null, null); + Collection points = getPoints(regionId); + GroundMarkerPoint existing = points.stream() + .filter(p -> p.equals(searchPoint)) + .findFirst().orElse(null); + if (existing == null) + { + return; + } + chatboxPanelManager.openTextInput("Tile label") + .value(Optional.ofNullable(existing.getLabel()).orElse("")) .onDone((input) -> { input = Strings.emptyToNull(input); - GroundMarkerPoint searchPoint = new GroundMarkerPoint(regionId, worldPoint.getRegionX(), worldPoint.getRegionY(), client.getPlane(), null, null); - Collection points = getPoints(regionId); - GroundMarkerPoint existing = points.stream() - .filter(p -> p.equals(searchPoint)) - .findFirst().orElse(null); - if (existing == null) - { - return; - } - GroundMarkerPoint newPoint = new GroundMarkerPoint(regionId, worldPoint.getRegionX(), worldPoint.getRegionY(), client.getPlane(), existing.getColor(), input); points.remove(searchPoint); points.add(newPoint); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerSharingManager.java b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerSharingManager.java new file mode 100644 index 0000000000..91c0e800ac --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerSharingManager.java @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2021, Adam + * 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.groundmarkers; + +import com.google.common.base.Strings; +import com.google.common.util.concurrent.Runnables; +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; +import com.google.gson.reflect.TypeToken; +import java.awt.Toolkit; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; +import javax.inject.Inject; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.ChatMessageType; +import net.runelite.api.Client; +import net.runelite.api.events.WidgetMenuOptionClicked; +import static net.runelite.api.widgets.WidgetInfo.WORLD_MAP_OPTION; +import net.runelite.client.chat.ChatMessageManager; +import net.runelite.client.chat.QueuedMessage; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.game.chatbox.ChatboxPanelManager; +import net.runelite.client.menus.MenuManager; +import net.runelite.client.menus.WidgetMenuOption; + +@Slf4j +class GroundMarkerSharingManager +{ + private static final WidgetMenuOption EXPORT_MARKERS_OPTION = new WidgetMenuOption("Export", "Ground Markers", WORLD_MAP_OPTION); + private static final WidgetMenuOption IMPORT_MARKERS_OPTION = new WidgetMenuOption("Import", "Ground Markers", WORLD_MAP_OPTION); + + private final GroundMarkerPlugin plugin; + private final Client client; + private final MenuManager menuManager; + private final ChatMessageManager chatMessageManager; + private final ChatboxPanelManager chatboxPanelManager; + private final Gson gson; + + @Inject + private GroundMarkerSharingManager(GroundMarkerPlugin plugin, Client client, MenuManager menuManager, + ChatMessageManager chatMessageManager, ChatboxPanelManager chatboxPanelManager, Gson gson) + { + this.plugin = plugin; + this.client = client; + this.menuManager = menuManager; + this.chatMessageManager = chatMessageManager; + this.chatboxPanelManager = chatboxPanelManager; + this.gson = gson; + } + + void addMenuOptions() + { + menuManager.addManagedCustomMenu(EXPORT_MARKERS_OPTION); + menuManager.addManagedCustomMenu(IMPORT_MARKERS_OPTION); + } + + void removeMenuOptions() + { + menuManager.removeManagedCustomMenu(EXPORT_MARKERS_OPTION); + menuManager.removeManagedCustomMenu(IMPORT_MARKERS_OPTION); + } + + private boolean widgetMenuClickedEquals(final WidgetMenuOptionClicked event, final WidgetMenuOption target) + { + return event.getMenuTarget().equals(target.getMenuTarget()) && + event.getMenuOption().equals(target.getMenuOption()); + } + + @Subscribe + public void onWidgetMenuOptionClicked(WidgetMenuOptionClicked event) + { + // ensure that the option clicked is the export markers option + if (event.getWidget() != WORLD_MAP_OPTION) + { + return; + } + + if (widgetMenuClickedEquals(event, EXPORT_MARKERS_OPTION)) + { + exportGroundMarkers(); + } + else if (widgetMenuClickedEquals(event, IMPORT_MARKERS_OPTION)) + { + promptForImport(); + } + } + + private void exportGroundMarkers() + { + int[] regions = client.getMapRegions(); + if (regions == null) + { + return; + } + + List activePoints = Arrays.stream(regions) + .mapToObj(regionId -> plugin.getPoints(regionId).stream()) + .flatMap(Function.identity()) + .collect(Collectors.toList()); + + if (activePoints.isEmpty()) + { + sendChatMessage("You have no ground markers to export."); + return; + } + + final String exportDump = gson.toJson(activePoints); + + log.debug("Exported ground markers: {}", exportDump); + + Toolkit.getDefaultToolkit() + .getSystemClipboard() + .setContents(new StringSelection(exportDump), null); + sendChatMessage(activePoints.size() + " ground markers were copied to your clipboard."); + } + + private void promptForImport() + { + final String clipboardText; + try + { + clipboardText = Toolkit.getDefaultToolkit() + .getSystemClipboard() + .getData(DataFlavor.stringFlavor) + .toString(); + } + catch (IOException | UnsupportedFlavorException ex) + { + sendChatMessage("Unable to read system clipboard."); + log.warn("error reading clipboard", ex); + return; + } + + log.debug("Clipboard contents: {}", clipboardText); + if (Strings.isNullOrEmpty(clipboardText)) + { + sendChatMessage("You do not have any ground markers copied in your clipboard."); + return; + } + + List importPoints; + try + { + // CHECKSTYLE:OFF + importPoints = gson.fromJson(clipboardText, new TypeToken>(){}.getType()); + // CHECKSTYLE:ON + } + catch (JsonSyntaxException e) + { + log.debug("Malformed JSON for clipboard import", e); + sendChatMessage("You do not have any ground markers copied in your clipboard."); + return; + } + + if (importPoints.isEmpty()) + { + sendChatMessage("You do not have any ground markers copied in your clipboard."); + return; + } + + chatboxPanelManager.openTextMenuInput("Are you sure you want to import " + importPoints.size() + " ground markers?") + .option("Yes", () -> importGroundMarkers(importPoints)) + .option("No", Runnables::doNothing) + .build(); + } + + private void importGroundMarkers(Collection importPoints) + { + // regions being imported may not be loaded on client, + // so need to import each bunch directly into the config + // first, collate the list of unique region ids in the import + Map> regionGroupedPoints = importPoints.stream() + .collect(Collectors.groupingBy(GroundMarkerPoint::getRegionId)); + + // now import each region into the config + regionGroupedPoints.forEach((regionId, groupedPoints) -> + { + // combine imported points with existing region points + log.debug("Importing {} points to region {}", groupedPoints.size(), regionId); + Collection regionPoints = plugin.getPoints(regionId); + + List mergedList = new ArrayList<>(regionPoints.size() + groupedPoints.size()); + // add existing points + mergedList.addAll(regionPoints); + + // add new points + for (GroundMarkerPoint point : groupedPoints) + { + // filter out duplicates + if (!mergedList.contains(point)) + { + mergedList.add(point); + } + } + + plugin.savePoints(regionId, mergedList); + }); + + // reload points from config + log.debug("Reloading points after import"); + plugin.loadPoints(); + sendChatMessage(importPoints.size() + " ground markers were imported from the clipboard."); + } + + private void sendChatMessage(final String message) + { + chatMessageManager.queue(QueuedMessage.builder() + .type(ChatMessageType.CONSOLE) + .runeLiteFormattedMessage(message) + .build()); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/HiscorePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/HiscorePlugin.java index edb450d61b..caf3020149 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/HiscorePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/HiscorePlugin.java @@ -38,9 +38,10 @@ import net.runelite.api.ChatMessageType; import net.runelite.api.Client; import net.runelite.api.MenuAction; import net.runelite.api.MenuEntry; +import net.runelite.api.Player; import net.runelite.api.events.ChatMessage; import net.runelite.api.events.MenuEntryAdded; -import net.runelite.api.events.PlayerMenuOptionClicked; +import net.runelite.api.events.MenuOptionClicked; import net.runelite.api.widgets.WidgetInfo; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; @@ -174,11 +175,30 @@ public class HiscorePlugin extends Plugin } @Subscribe - public void onPlayerMenuOptionClicked(PlayerMenuOptionClicked event) + public void onMenuOptionClicked(MenuOptionClicked event) { - if (event.getMenuOption().equals(LOOKUP)) + if ((event.getMenuAction() == MenuAction.RUNELITE || event.getMenuAction() == MenuAction.RUNELITE_PLAYER) + && event.getMenuOption().equals(LOOKUP)) { - lookupPlayer(Text.removeTags(event.getMenuTarget())); + final String target; + if (event.getMenuAction() == MenuAction.RUNELITE_PLAYER) + { + // The player id is included in the event, so we can use that to get the player name, + // which avoids having to parse out the combat level and any icons preceding the name. + Player player = client.getCachedPlayers()[event.getId()]; + if (player == null) + { + return; + } + + target = player.getName(); + } + else + { + target = Text.removeTags(event.getMenuTarget()); + } + + lookupPlayer(target); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierConfig.java index 564cbb609b..99f0a5b55f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierConfig.java @@ -27,6 +27,7 @@ package net.runelite.client.plugins.idlenotifier; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.Range; import net.runelite.client.config.Units; @ConfigGroup("idlenotifier") @@ -90,7 +91,7 @@ public interface IdleNotifierConfig extends Config @ConfigItem( keyName = "hitpoints", - name = "Hitpoints Notification Threshold", + name = "Hitpoints Threshold", description = "The amount of hitpoints to send a notification at. A value of 0 will disable notification.", position = 6 ) @@ -101,7 +102,7 @@ public interface IdleNotifierConfig extends Config @ConfigItem( keyName = "prayer", - name = "Prayer Notification Threshold", + name = "Prayer Threshold", description = "The amount of prayer points to send a notification at. A value of 0 will disable notification.", position = 7 ) @@ -110,10 +111,36 @@ public interface IdleNotifierConfig extends Config return 0; } + @ConfigItem( + keyName = "lowEnergy", + name = "Low Energy Threshold", + description = "The amount of energy points remaining to send a notification at. A value of 100 will disable notification.", + position = 8 + ) + @Units(Units.PERCENT) + @Range(max = 100) + default int getLowEnergyThreshold() + { + return 100; + } + + @ConfigItem( + keyName = "highEnergy", + name = "High Energy Threshold", + description = "The amount of energy points reached to send a notification. A value of 0 will disable notification.", + position = 9 + ) + @Units(Units.PERCENT) + @Range(max = 100) + default int getHighEnergyThreshold() + { + return 0; + } + @ConfigItem( keyName = "oxygen", - name = "Oxygen Notification Threshold", - position = 8, + name = "Oxygen Threshold", + position = 10, description = "The amount of remaining oxygen to send a notification at. A value of 0 will disable notification." ) @Units(Units.PERCENT) @@ -124,9 +151,9 @@ public interface IdleNotifierConfig extends Config @ConfigItem( keyName = "spec", - name = "Special Attack Energy Notification Threshold", - position = 9, - description = "The amount of spec energy reached to send a notification at. A value of 0 will disable notification." + name = "Spec Threshold", + position = 11, + description = "The amount of special attack energy reached to send a notification at. A value of 0 will disable notification." ) @Units(Units.PERCENT) default int getSpecEnergyThreshold() diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java index 93566d4c22..6d7dcec442 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java @@ -93,6 +93,8 @@ public class IdleNotifierPlugin extends Plugin private boolean notifyPosition = false; private boolean notifyHitpoints = true; private boolean notifyPrayer = true; + private boolean shouldNotifyLowEnergy = false; + private boolean shouldNotifyHighEnergy = false; private boolean notifyOxygen = true; private boolean notifyIdleLogout = true; private boolean notify6HourLogout = true; @@ -136,6 +138,7 @@ public class IdleNotifierPlugin extends Plugin case WOODCUTTING_RUNE: case WOODCUTTING_GILDED: case WOODCUTTING_DRAGON: + case WOODCUTTING_DRAGON_OR: case WOODCUTTING_INFERNAL: case WOODCUTTING_3A_AXE: case WOODCUTTING_CRYSTAL: @@ -144,7 +147,7 @@ public class IdleNotifierPlugin extends Plugin case COOKING_FIRE: case COOKING_RANGE: case COOKING_WINE: - /* Crafting(Gem Cutting, Glassblowing, Spinning, Battlestaves, Pottery) */ + /* Crafting(Gem Cutting, Glassblowing, Spinning, Weaving, Battlestaves, Pottery) */ case GEM_CUTTING_OPAL: case GEM_CUTTING_JADE: case GEM_CUTTING_REDTOPAZ: @@ -155,6 +158,7 @@ public class IdleNotifierPlugin extends Plugin case GEM_CUTTING_AMETHYST: case CRAFTING_GLASSBLOWING: case CRAFTING_SPINNING: + case CRAFTING_LOOM: case CRAFTING_BATTLESTAVES: case CRAFTING_LEATHER: case CRAFTING_POTTERS_WHEEL: @@ -197,10 +201,10 @@ public class IdleNotifierPlugin extends Plugin case FISHING_HARPOON: case FISHING_BARBTAIL_HARPOON: case FISHING_DRAGON_HARPOON: + case FISHING_DRAGON_HARPOON_OR: case FISHING_INFERNAL_HARPOON: case FISHING_CRYSTAL_HARPOON: case FISHING_TRAILBLAZER_HARPOON: - case FISHING_TRAILBLAZER_HARPOON_2: case FISHING_OILY_ROD: case FISHING_KARAMBWAN: case FISHING_BAREHAND: @@ -223,6 +227,7 @@ public class IdleNotifierPlugin extends Plugin case MINING_DRAGON_PICKAXE: case MINING_DRAGON_PICKAXE_UPGRADED: case MINING_DRAGON_PICKAXE_OR: + case MINING_DRAGON_PICKAXE_OR_TRAILBLAZER: case MINING_INFERNAL_PICKAXE: case MINING_3A_PICKAXE: case MINING_CRYSTAL_PICKAXE: @@ -243,6 +248,7 @@ public class IdleNotifierPlugin extends Plugin case MINING_MOTHERLODE_DRAGON: case MINING_MOTHERLODE_DRAGON_UPGRADED: case MINING_MOTHERLODE_DRAGON_OR: + case MINING_MOTHERLODE_DRAGON_OR_TRAILBLAZER: case MINING_MOTHERLODE_INFERNAL: case MINING_MOTHERLODE_3A: case MINING_MOTHERLODE_CRYSTAL: @@ -263,6 +269,10 @@ public class IdleNotifierPlugin extends Plugin case MAGIC_ENCHANTING_BOLTS: /* Prayer */ case USING_GILDED_ALTAR: + case ECTOFUNTUS_FILL_SLIME_BUCKET: + case ECTOFUNTUS_INSERT_BONES: + case ECTOFUNTUS_GRIND_BONES: + case ECTOFUNTUS_EMPTY_BIN: /* Farming */ case FARMING_MIX_ULTRACOMPOST: case FARMING_HARVEST_BUSH: @@ -428,54 +438,64 @@ public class IdleNotifierPlugin extends Plugin if (config.logoutIdle() && checkIdleLogout()) { - notifier.notify("[" + local.getName() + "] is about to log out from idling too long!"); + notifier.notify("You are about to log out from idling too long!"); } if (check6hrLogout()) { - notifier.notify("[" + local.getName() + "] is about to log out from being online for 6 hours!"); + notifier.notify("You are about to log out from being online for 6 hours!"); } if (config.animationIdle() && checkAnimationIdle(waitDuration, local)) { - notifier.notify("[" + local.getName() + "] is now idle!"); + notifier.notify("You are now idle!"); } if (config.movementIdle() && checkMovementIdle(waitDuration, local)) { - notifier.notify("[" + local.getName() + "] has stopped moving!"); + notifier.notify("You have stopped moving!"); } if (config.interactionIdle() && checkInteractionIdle(waitDuration, local)) { if (lastInteractWasCombat) { - notifier.notify("[" + local.getName() + "] is now out of combat!"); + notifier.notify("You are now out of combat!"); } else { - notifier.notify("[" + local.getName() + "] is now idle!"); + notifier.notify("You are now idle!"); } } if (checkLowHitpoints()) { - notifier.notify("[" + local.getName() + "] has low hitpoints!"); + notifier.notify("You have low hitpoints!"); } if (checkLowPrayer()) { - notifier.notify("[" + local.getName() + "] has low prayer!"); + notifier.notify("You have low prayer!"); + } + + if (checkLowEnergy()) + { + notifier.notify("You have low run energy!"); + } + + if (checkHighEnergy()) + { + notifier.notify("You have restored run energy!"); } if (checkLowOxygen()) { - notifier.notify("[" + local.getName() + "] has low oxygen!"); + notifier.notify("You have low oxygen!"); } if (checkFullSpecEnergy()) { - notifier.notify("[" + local.getName() + "] has restored spec energy!"); + notifier.notify("You have restored spec energy!"); } } @@ -569,6 +589,52 @@ public class IdleNotifierPlugin extends Plugin return false; } + private boolean checkLowEnergy() + { + if (config.getLowEnergyThreshold() >= 100) + { + return false; + } + + if (client.getEnergy() <= config.getLowEnergyThreshold()) + { + if (shouldNotifyLowEnergy) + { + shouldNotifyLowEnergy = false; + return true; + } + } + else + { + shouldNotifyLowEnergy = true; + } + + return false; + } + + private boolean checkHighEnergy() + { + if (config.getHighEnergyThreshold() == 0) + { + return false; + } + + if (client.getEnergy() >= config.getHighEnergyThreshold()) + { + if (shouldNotifyHighEnergy) + { + shouldNotifyHighEnergy = false; + return true; + } + } + else + { + shouldNotifyHighEnergy = true; + } + + return false; + } + private boolean checkInteractionIdle(Duration waitDuration, Player local) { if (lastInteract == null) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/implings/ImplingsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/implings/ImplingsConfig.java index 9fe7e56fb9..a11ef6f7df 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/implings/ImplingsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/implings/ImplingsConfig.java @@ -55,7 +55,7 @@ public interface ImplingsConfig extends Config @ConfigItem( position = 1, keyName = "showbaby", - name = "Show Baby implings", + name = "Baby implings", description = "Configures whether or not Baby impling tags are displayed", section = implingSection ) @@ -80,7 +80,7 @@ public interface ImplingsConfig extends Config @ConfigItem( position = 3, keyName = "showyoung", - name = "Show Young implings", + name = "Young implings", description = "Configures whether or not Young impling tags are displayed", section = implingSection ) @@ -105,7 +105,7 @@ public interface ImplingsConfig extends Config @ConfigItem( position = 5, keyName = "showgourmet", - name = "Show Gourmet implings", + name = "Gourmet implings", description = "Configures whether or not Gourmet impling tags are displayed", section = implingSection ) @@ -130,7 +130,7 @@ public interface ImplingsConfig extends Config @ConfigItem( position = 7, keyName = "showearth", - name = "Show Earth implings", + name = "Earth implings", description = "Configures whether or not Earth impling tags are displayed", section = implingSection ) @@ -155,7 +155,7 @@ public interface ImplingsConfig extends Config @ConfigItem( position = 9, keyName = "showessence", - name = "Show Essence implings", + name = "Essence implings", description = "Configures whether or not Essence impling tags are displayed", section = implingSection ) @@ -180,7 +180,7 @@ public interface ImplingsConfig extends Config @ConfigItem( position = 11, keyName = "showeclectic", - name = "Show Eclectic implings", + name = "Eclectic implings", description = "Configures whether or not Eclectic impling tags are displayed", section = implingSection ) @@ -205,7 +205,7 @@ public interface ImplingsConfig extends Config @ConfigItem( position = 13, keyName = "shownature", - name = "Show Nature implings", + name = "Nature implings", description = "Configures whether or not Nature impling tags are displayed", section = implingSection ) @@ -230,7 +230,7 @@ public interface ImplingsConfig extends Config @ConfigItem( position = 15, keyName = "showmagpie", - name = "Show Magpie implings", + name = "Magpie implings", description = "Configures whether or not Magpie impling tags are displayed", section = implingSection ) @@ -255,7 +255,7 @@ public interface ImplingsConfig extends Config @ConfigItem( position = 17, keyName = "showninja", - name = "Show Ninja implings", + name = "Ninja implings", description = "Configures whether or not Ninja impling tags are displayed", section = implingSection ) @@ -280,7 +280,7 @@ public interface ImplingsConfig extends Config @ConfigItem( position = 19, keyName = "showCrystal", - name = "Show Crystal implings", + name = "Crystal implings", description = "Configures whether or not Crystal implings are displayed", section = implingSection ) @@ -305,7 +305,7 @@ public interface ImplingsConfig extends Config @ConfigItem( position = 21, keyName = "showdragon", - name = "Show Dragon implings", + name = "Dragon implings", description = "Configures whether or not Dragon impling tags are displayed", section = implingSection ) @@ -330,7 +330,7 @@ public interface ImplingsConfig extends Config @ConfigItem( position = 23, keyName = "showlucky", - name = "Show Lucky implings", + name = "Lucky implings", description = "Configures whether or not Lucky impling tags are displayed", section = implingSection ) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPanel.java index c59fa78798..2386bb8c45 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPanel.java @@ -27,6 +27,7 @@ package net.runelite.client.plugins.info; import com.google.common.base.MoreObjects; import com.google.inject.Inject; +import com.openosrs.client.OpenOSRS; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Cursor; @@ -135,8 +136,11 @@ public class InfoPanel extends PluginPanel final Font smallFont = FontManager.getRunescapeSmallFont(); - JLabel version = new JLabel(htmlLabel("RuneLite version: ", runeliteVersion)); - version.setFont(smallFont); + JLabel rlVersion = new JLabel(htmlLabel("RuneLite version: ", runeliteVersion)); + rlVersion.setFont(smallFont); + + JLabel oprsVersion = new JLabel(htmlLabel("OpenOSRS version: ", OpenOSRS.SYSTEM_VERSION)); + oprsVersion.setFont(smallFont); JLabel revision = new JLabel(); revision.setFont(smallFont); @@ -147,7 +151,7 @@ public class InfoPanel extends PluginPanel engineVer = String.format("Rev %d", client.getRevision()); } - revision.setText(htmlLabel("Oldschool revision: ", engineVer)); + revision.setText(htmlLabel("OldSchool revision: ", engineVer)); JLabel launcher = new JLabel(htmlLabel("Launcher version: ", MoreObjects .firstNonNull(RuneLiteProperties.getLauncherVersion(), "Unknown"))); @@ -170,7 +174,8 @@ public class InfoPanel extends PluginPanel } }); - versionPanel.add(version); + versionPanel.add(rlVersion); + versionPanel.add(oprsVersion); versionPanel.add(revision); versionPanel.add(launcher); versionPanel.add(Box.createGlue()); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorytags/InventoryTagsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorytags/InventoryTagsConfig.java index 745d64594b..b9981d49f9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/inventorytags/InventoryTagsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/inventorytags/InventoryTagsConfig.java @@ -28,20 +28,74 @@ import java.awt.Color; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.ConfigSection; +import net.runelite.client.config.Range; -@ConfigGroup("inventorytags") +@ConfigGroup(InventoryTagsConfig.GROUP) public interface InventoryTagsConfig extends Config { - enum DisplayMode - { - OUTLINE, - UNDERLINE - } - String GROUP = "inventorytags"; + @ConfigSection( + name = "Tag display mode", + description = "How tags are displayed in the inventory", + position = 0 + ) + String tagStyleSection = "tagStyleSection"; + @ConfigItem( position = 0, + keyName = "showTagOutline", + name = "Outline", + description = "Configures whether or not item tags show be outlined", + section = tagStyleSection + ) + default boolean showTagOutline() + { + return true; + } + + @ConfigItem( + position = 1, + keyName = "tagUnderline", + name = "Underline", + description = "Configures whether or not item tags should be underlined", + section = tagStyleSection + ) + default boolean showTagUnderline() + { + return false; + } + + @ConfigItem( + position = 2, + keyName = "tagFill", + name = "Fill", + description = "Configures whether or not item tags should be filled", + section = tagStyleSection + ) + default boolean showTagFill() + { + return false; + } + + @Range( + max = 255 + ) + @ConfigItem( + position = 3, + keyName = "fillOpacity", + name = "Fill opacity", + description = "Configures the opacity of the tag \"Fill\"", + section = tagStyleSection + ) + default int fillOpacity() + { + return 50; + } + + @ConfigItem( + position = 1, keyName = "groupColor1", name = "Group 1 Color", description = "Color of the Tag" @@ -52,7 +106,7 @@ public interface InventoryTagsConfig extends Config } @ConfigItem( - position = 1, + position = 2, keyName = "groupColor2", name = "Group 2 Color", description = "Color of the Tag" @@ -63,7 +117,7 @@ public interface InventoryTagsConfig extends Config } @ConfigItem( - position = 2, + position = 3, keyName = "groupColor3", name = "Group 3 Color", description = "Color of the Tag" @@ -74,7 +128,7 @@ public interface InventoryTagsConfig extends Config } @ConfigItem( - position = 3, + position = 4, keyName = "groupColor4", name = "Group 4 Color", description = "Color of the Tag" @@ -85,7 +139,7 @@ public interface InventoryTagsConfig extends Config } @ConfigItem( - position = 4, + position = 5, keyName = "groupColor5", name = "Group 5 Color", description = "Color of the Tag" @@ -96,7 +150,7 @@ public interface InventoryTagsConfig extends Config } @ConfigItem( - position = 5, + position = 6, keyName = "groupColor6", name = "Group 6 Color", description = "Color of the Tag" @@ -105,15 +159,4 @@ public interface InventoryTagsConfig extends Config { return new Color(0, 255, 255); } - - @ConfigItem( - position = 6, - keyName = "displayMode", - name = "Display mode", - description = "How tags are displayed in the inventory" - ) - default DisplayMode getDisplayMode() - { - return DisplayMode.OUTLINE; - } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorytags/InventoryTagsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorytags/InventoryTagsOverlay.java index 03857e185c..4b9e471fab 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/inventorytags/InventoryTagsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/inventorytags/InventoryTagsOverlay.java @@ -24,21 +24,26 @@ */ package net.runelite.client.plugins.inventorytags; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; import java.awt.Color; import java.awt.Graphics2D; +import java.awt.Image; import java.awt.Rectangle; import java.awt.image.BufferedImage; import javax.inject.Inject; import net.runelite.api.widgets.WidgetItem; import net.runelite.client.game.ItemManager; -import net.runelite.client.plugins.inventorytags.InventoryTagsConfig.DisplayMode; import net.runelite.client.ui.overlay.WidgetItemOverlay; +import net.runelite.client.util.ColorUtil; +import net.runelite.client.util.ImageUtil; public class InventoryTagsOverlay extends WidgetItemOverlay { private final ItemManager itemManager; private final InventoryTagsPlugin plugin; private final InventoryTagsConfig config; + private final Cache fillCache; @Inject private InventoryTagsOverlay(ItemManager itemManager, InventoryTagsPlugin plugin, InventoryTagsConfig config) @@ -48,6 +53,10 @@ public class InventoryTagsOverlay extends WidgetItemOverlay this.config = config; showOnEquipment(); showOnInventory(); + fillCache = CacheBuilder.newBuilder() + .concurrencyLevel(1) + .maximumSize(32) + .build(); } @Override @@ -57,16 +66,22 @@ public class InventoryTagsOverlay extends WidgetItemOverlay if (group != null) { final Color color = plugin.getGroupNameColor(group); - final DisplayMode displayMode = config.getDisplayMode(); if (color != null) { Rectangle bounds = widgetItem.getCanvasBounds(); - if (displayMode == DisplayMode.OUTLINE) + if (config.showTagOutline()) { final BufferedImage outline = itemManager.getItemOutline(itemId, widgetItem.getQuantity(), color); graphics.drawImage(outline, (int) bounds.getX(), (int) bounds.getY(), null); } - else + + if (config.showTagFill()) + { + final Image image = getFillImage(color, widgetItem.getId(), widgetItem.getQuantity()); + graphics.drawImage(image, (int) bounds.getX(), (int) bounds.getY(), null); + } + + if (config.showTagUnderline()) { int heightOffSet = (int) bounds.getY() + (int) bounds.getHeight() + 2; graphics.setColor(color); @@ -75,4 +90,22 @@ public class InventoryTagsOverlay extends WidgetItemOverlay } } } + + private Image getFillImage(Color color, int itemId, int qty) + { + long key = (((long) itemId) << 32) | qty; + Image image = fillCache.getIfPresent(key); + if (image == null) + { + final Color fillColor = ColorUtil.colorWithAlpha(color, config.fillOpacity()); + image = ImageUtil.fillImage(itemManager.getImage(itemId, qty, false), fillColor); + fillCache.put(key, image); + } + return image; + } + + void invalidateCache() + { + fillCache.invalidateAll(); + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorytags/InventoryTagsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorytags/InventoryTagsPlugin.java index 77a0548287..cdbf26a845 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/inventorytags/InventoryTagsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/inventorytags/InventoryTagsPlugin.java @@ -39,6 +39,7 @@ import net.runelite.api.events.WidgetMenuOptionClicked; import net.runelite.api.widgets.WidgetInfo; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.events.ConfigChanged; import net.runelite.client.menus.MenuManager; import net.runelite.client.menus.WidgetMenuOption; import net.runelite.client.plugins.Plugin; @@ -147,6 +148,15 @@ public class InventoryTagsPlugin extends Plugin editorMode = false; } + @Subscribe + public void onConfigChanged(ConfigChanged configChanged) + { + if (configChanged.getGroup().equals(InventoryTagsConfig.GROUP)) + { + overlay.invalidateCache(); + } + } + @Subscribe public void onWidgetMenuOptionClicked(final WidgetMenuOptionClicked event) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeConfig.java index 0e8a4569fe..b998251ccb 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeConfig.java @@ -51,7 +51,7 @@ public interface ItemChargeConfig extends Config @ConfigItem( keyName = "veryLowWarningColor", - name = "Very Low Warning Color", + name = "Very Low Warning", description = "The color of the overlay when charges are very low", position = 1 ) @@ -62,7 +62,7 @@ public interface ItemChargeConfig extends Config @ConfigItem( keyName = "lowWarningColor", - name = "Low Warning Color", + name = "Low Warning", description = "The color of the overlay when charges are low", position = 2 ) @@ -95,7 +95,7 @@ public interface ItemChargeConfig extends Config @ConfigItem( keyName = "showTeleportCharges", - name = "Show Teleport Charges", + name = "Teleport Charges", description = "Show teleport item charge counts", position = 5, section = chargesSection @@ -149,7 +149,7 @@ public interface ItemChargeConfig extends Config @ConfigItem( keyName = "showImpCharges", - name = "Show Imp-in-a-box charges", + name = "Imp-in-a-box charges", description = "Show Imp-in-a-box item charges", position = 8, section = chargesSection @@ -161,7 +161,7 @@ public interface ItemChargeConfig extends Config @ConfigItem( keyName = "showFungicideCharges", - name = "Show Fungicide Charges", + name = "Fungicide Charges", description = "Show Fungicide item charges", position = 9, section = chargesSection @@ -173,7 +173,7 @@ public interface ItemChargeConfig extends Config @ConfigItem( keyName = "showWateringCanCharges", - name = "Show Watering Can Charges", + name = "Watering Can Charges", description = "Show Watering can item charges", position = 10, section = chargesSection @@ -185,7 +185,7 @@ public interface ItemChargeConfig extends Config @ConfigItem( keyName = "showWaterskinCharges", - name = "Show Waterskin Charges", + name = "Waterskin Charges", description = "Show Waterskin dose counts", position = 11, section = chargesSection @@ -197,7 +197,7 @@ public interface ItemChargeConfig extends Config @ConfigItem( keyName = "showBellowCharges", - name = "Show Bellows Charges", + name = "Bellows Charges", description = "Show Ogre bellows item charges", position = 12, section = chargesSection @@ -209,7 +209,7 @@ public interface ItemChargeConfig extends Config @ConfigItem( keyName = "showBasketCharges", - name = "Show Basket Charges", + name = "Basket Charges", description = "Show Fruit basket item counts", position = 13, section = chargesSection @@ -221,7 +221,7 @@ public interface ItemChargeConfig extends Config @ConfigItem( keyName = "showSackCharges", - name = "Show Sack Charges", + name = "Sack Charges", description = "Show Sack item counts", position = 14, section = chargesSection @@ -233,7 +233,7 @@ public interface ItemChargeConfig extends Config @ConfigItem( keyName = "showAbyssalBraceletCharges", - name = "Show Abyssal Bracelet Charges", + name = "Abyssal Bracelet Charges", description = "Show Abyssal bracelet item charges", position = 15, section = chargesSection @@ -245,7 +245,7 @@ public interface ItemChargeConfig extends Config @ConfigItem( keyName = "showAmuletOfChemistryCharges", - name = "Show Amulet of Chemistry Charges", + name = "Amulet of Chemistry Charges", description = "Show Amulet of chemistry item charges", position = 16, section = chargesSection @@ -275,7 +275,7 @@ public interface ItemChargeConfig extends Config @ConfigItem( keyName = "showAmuletOfBountyCharges", - name = "Show Amulet of Bounty Charges", + name = "Amulet of Bounty Charges", description = "Show Amulet of bounty item charges", position = 17, section = chargesSection @@ -317,7 +317,7 @@ public interface ItemChargeConfig extends Config @ConfigItem( keyName = "showBindingNecklaceCharges", - name = "Show Binding Necklace Charges", + name = "Binding Necklace Charges", description = "Show Binding necklace item charges", position = 19, section = chargesSection @@ -359,7 +359,7 @@ public interface ItemChargeConfig extends Config @ConfigItem( keyName = "showExplorerRingCharges", - name = "Show Explorer's Ring Alch Charges", + name = "Explorer's Ring Alch Charges", description = "Show Explorer's ring alchemy charges", position = 21, section = chargesSection @@ -389,7 +389,7 @@ public interface ItemChargeConfig extends Config @ConfigItem( keyName = "showRingOfForgingCount", - name = "Show Ring of Forging Charges", + name = "Ring of Forging Charges", description = "Show Ring of forging item charges", position = 22, section = chargesSection @@ -431,7 +431,7 @@ public interface ItemChargeConfig extends Config @ConfigItem( keyName = "showInfoboxes", - name = "Show Infoboxes", + name = "Infoboxes", description = "Show an infobox with remaining charges for equipped items", position = 24 ) @@ -442,7 +442,7 @@ public interface ItemChargeConfig extends Config @ConfigItem( keyName = "showPotionDoseCount", - name = "Show Potion Doses", + name = "Potion Doses", description = "Show remaining potion doses", position = 25, section = chargesSection diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatChanges.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatChanges.java index a5dc493f5b..ac7be8d848 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatChanges.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatChanges.java @@ -131,7 +131,7 @@ public class ItemStatChanges add(boost(DEFENCE, perc(.15, 5)), SUPER_DEFENCE1, SUPER_DEFENCE2, SUPER_DEFENCE3, SUPER_DEFENCE4); add(boost(MAGIC, 3), MAGIC_ESSENCE1, MAGIC_ESSENCE2, MAGIC_ESSENCE3, MAGIC_ESSENCE4); add(combo(3, boost(ATTACK, perc(.15, 5)), boost(STRENGTH, perc(.15, 5)), boost(DEFENCE, perc(.15, 5))), SUPER_COMBAT_POTION1, SUPER_COMBAT_POTION2, SUPER_COMBAT_POTION3, SUPER_COMBAT_POTION4); - add(combo(3, boost(ATTACK, perc(.20, 2)), boost(STRENGTH, perc(.12, 2)), heal(PRAYER, perc(.10, 0)), heal(DEFENCE, perc(.10, -2)), new BoostedStatBoost(HITPOINTS, false, perc(-.12, 0))), ZAMORAK_BREW1, ZAMORAK_BREW2, ZAMORAK_BREW3, ZAMORAK_BREW4); + add(combo(3, boost(ATTACK, perc(.20, 2)), boost(STRENGTH, perc(.12, 2)), heal(PRAYER, perc(.10, 0)), new BoostedStatBoost(DEFENCE, false, perc(.10, -2)), new BoostedStatBoost(HITPOINTS, false, perc(-.12, 0))), ZAMORAK_BREW1, ZAMORAK_BREW2, ZAMORAK_BREW3, ZAMORAK_BREW4); add(new SaradominBrew(0.15, 0.2, 0.1, 2, 2), SARADOMIN_BREW1, SARADOMIN_BREW2, SARADOMIN_BREW3, SARADOMIN_BREW4); add(boost(RANGED, perc(.15, 5)), SUPER_RANGING_1, SUPER_RANGING_2, SUPER_RANGING_3, SUPER_RANGING_4); add(boost(MAGIC, perc(.15, 5)), SUPER_MAGIC_POTION_1, SUPER_MAGIC_POTION_2, SUPER_MAGIC_POTION_3, SUPER_MAGIC_POTION_4); @@ -214,6 +214,10 @@ public class ItemStatChanges add(heal(HITPOINTS, 20), PADDLEFISH); add(new GauntletPotion(), EGNIOL_POTION_1, EGNIOL_POTION_2, EGNIOL_POTION_3, EGNIOL_POTION_4); + // Soul Wars + add(combo(2, heal(HITPOINTS, perc(.15, 1)), heal(RUN_ENERGY, 100)), BANDAGES_25202); + add(combo(6, boost(ATTACK, perc(.15, 5)), boost(STRENGTH, perc(.15, 5)), boost(DEFENCE, perc(.15, 5)), boost(RANGED, perc(.15, 5)), boost(MAGIC, perc(.15, 5)), heal(PRAYER, perc(.25, 8))), POTION_OF_POWER1, POTION_OF_POWER2, POTION_OF_POWER3, POTION_OF_POWER4); + log.debug("{} items; {} behaviours loaded", effects.size(), new HashSet<>(effects.values()).size()); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/stats/Stat.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/stats/Stat.java index be7b2ff4d8..2d65a7993c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/stats/Stat.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/stats/Stat.java @@ -52,7 +52,7 @@ public abstract class Stat public abstract int getValue(Client client); /** - * Get the base stat maximum, ie. the bottom half of the stat fraction. + * Get the base stat maximum. (ie. the bottom half of the stat fraction) */ public abstract int getMaximum(Client client); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java index 6f8c1d966d..f3802e230a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java @@ -145,7 +145,8 @@ public class LootTrackerPlugin extends Plugin // Chest loot handling private static final String CHEST_LOOTED_MESSAGE = "You find some treasure in the chest!"; private static final Pattern LARRAN_LOOTED_PATTERN = Pattern.compile("You have opened Larran's (big|small) chest .*"); - private static final String STONE_CHEST_LOOTED_MESSAGE = "You steal some loot from the chest."; + // Used by Stone Chest, Isle of Souls chest, Dark Chest + private static final String OTHER_CHEST_LOOTED_MESSAGE = "You steal some loot from the chest."; private static final String DORGESH_KAAN_CHEST_LOOTED_MESSAGE = "You find treasure inside!"; private static final String GRUBBY_CHEST_LOOTED_MESSAGE = "You have opened the Grubby Chest"; private static final Pattern HAM_CHEST_LOOTED_PATTERN = Pattern.compile("Your (?[a-z]+) key breaks in the lock.*"); @@ -161,6 +162,8 @@ public class LootTrackerPlugin extends Plugin put(10835, "Dorgesh-Kaan Chest"). put(10834, "Dorgesh-Kaan Chest"). put(7323, "Grubby Chest"). + put(8593, "Isle of Souls Chest"). + put(7827, "Dark Chest"). build(); // Shade chest loot handling @@ -186,6 +189,11 @@ public class LootTrackerPlugin extends Plugin put(ObjectID.SILVER_CHEST_4128, "Silver key crimson"). put(ObjectID.SILVER_CHEST_4129, "Silver key black"). put(ObjectID.SILVER_CHEST_4130, "Silver key purple"). + put(ObjectID.GOLD_CHEST, "Gold key red"). + put(ObjectID.GOLD_CHEST_41213, "Gold key brown"). + put(ObjectID.GOLD_CHEST_41214, "Gold key crimson"). + put(ObjectID.GOLD_CHEST_41215, "Gold key black"). + put(ObjectID.GOLD_CHEST_41216, "Gold key purple"). build(); // Hallow Sepulchre Coffin handling @@ -227,6 +235,10 @@ public class LootTrackerPlugin extends Plugin private static final String CASKET_EVENT = "Casket"; + // Soul Wars + private static final String SPOILS_OF_WAR_EVENT = "Spoils of war"; + private static final Set SOUL_WARS_REGIONS = ImmutableSet.of(8493, 8749, 9005); + private static final Set VOWELS = ImmutableSet.of('a', 'e', 'i', 'o', 'u'); @Inject @@ -487,8 +499,8 @@ public class LootTrackerPlugin extends Plugin @Subscribe public void onPlayerLootReceived(final PlayerLootReceived playerLootReceived) { - // Ignore Last Man Standing player loots - if (isPlayerWithinMapRegion(LAST_MAN_STANDING_REGIONS)) + // Ignore Last Man Standing and Soul Wars player loots + if (isPlayerWithinMapRegion(LAST_MAN_STANDING_REGIONS) || isPlayerWithinMapRegion(SOUL_WARS_REGIONS)) { return; } @@ -621,7 +633,7 @@ public class LootTrackerPlugin extends Plugin final String message = event.getMessage(); - if (message.equals(CHEST_LOOTED_MESSAGE) || message.equals(STONE_CHEST_LOOTED_MESSAGE) + if (message.equals(CHEST_LOOTED_MESSAGE) || message.equals(OTHER_CHEST_LOOTED_MESSAGE) || message.equals(DORGESH_KAAN_CHEST_LOOTED_MESSAGE) || message.startsWith(GRUBBY_CHEST_LOOTED_MESSAGE) || LARRAN_LOOTED_PATTERN.matcher(message).matches()) { @@ -741,7 +753,7 @@ public class LootTrackerPlugin extends Plugin return; } - setEvent(LootRecordType.EVENT, type, client.getRealSkillLevel(Skill.HUNTER)); + setEvent(LootRecordType.EVENT, type, client.getBoostedSkillLevel(Skill.HUNTER)); takeInventorySnapshot(); } } @@ -763,6 +775,7 @@ public class LootTrackerPlugin extends Plugin || SEEDPACK_EVENT.equals(eventType) || CASKET_EVENT.equals(eventType) || BIRDNEST_EVENT.equals(eventType) + || SPOILS_OF_WAR_EVENT.equals(eventType) || eventType.endsWith("Bird House") || eventType.startsWith("H.A.M. chest") || lootRecordType == LootRecordType.PICKPOCKET) @@ -799,7 +812,7 @@ public class LootTrackerPlugin extends Plugin if (event.getMenuOption().equals("Search") && BIRDNEST_IDS.contains(event.getId())) { - setEvent(LootRecordType.EVENT, BIRDNEST_EVENT); + setEvent(LootRecordType.EVENT, BIRDNEST_EVENT, event.getId()); takeInventorySnapshot(); } @@ -808,6 +821,12 @@ public class LootTrackerPlugin extends Plugin setEvent(LootRecordType.EVENT, CASKET_EVENT); takeInventorySnapshot(); } + + if (event.getMenuOption().equals("Open") && event.getId() == ItemID.SPOILS_OF_WAR) + { + setEvent(LootRecordType.EVENT, SPOILS_OF_WAR_EVENT); + takeInventorySnapshot(); + } } @Schedule( diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperConfig.java index 33ac662638..785c812d85 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperConfig.java @@ -144,6 +144,17 @@ public interface MenuEntrySwapperConfig extends Config return false; } + @ConfigItem( + keyName = "swapBattlestaves", + name = "Battlestaff", + description = "Swap Wield with Use on Battlestaves without orbs", + section = itemSection + ) + default boolean swapBattlestaves() + { + return false; + } + @ConfigItem( keyName = "swapPrayerBook", name = "Recite-Prayer", @@ -606,4 +617,15 @@ public interface MenuEntrySwapperConfig extends Config { return false; } + + @ConfigItem( + keyName = "swapRockCake", + name = "Dwarven rock cake", + description = "Swap Eat with Guzzle on the Dwarven rock cake", + section = itemSection + ) + default boolean swapRockCake() + { + return false; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java index 3ac2489645..4ef686a34c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java @@ -311,9 +311,10 @@ public class MenuEntrySwapperPlugin extends Plugin swap("view offer", "abort offer", () -> shiftModifier() && config.swapGEAbort()); Arrays.asList( - "honest jimmy", "bert the sandman", "advisor ghrim", "dark mage", "lanthus", "turael", "mazchna", "vannaka", - "chaeldar", "nieve", "steve", "duradel", "krystilia", "konar", "murphy", "cyrisus", "smoggy", "ginea", "watson", - "barbarian guard", "amy", "random" + "honest jimmy", "bert the sandman", "advisor ghrim", "dark mage", "lanthus", "spria", "turael", + "mazchna", "vannaka", "chaeldar", "nieve", "steve", "duradel", "krystilia", "konar", + "murphy", "cyrisus", "smoggy", "ginea", "watson", "barbarian guard", "amy", + "random" ).forEach(npc -> swap("cast", "npc contact", npc, () -> shiftModifier() && config.swapNpcContact())); swap("value", "buy 1", () -> shiftModifier() && config.shopBuy() == BuyMode.BUY_1); @@ -329,9 +330,12 @@ public class MenuEntrySwapperPlugin extends Plugin swap("wear", "rub", config::swapTeleportItem); swap("wear", "teleport", config::swapTeleportItem); swap("wield", "teleport", config::swapTeleportItem); + swap("wield", "invoke", config::swapTeleportItem); swap("bury", "use", config::swapBones); + swap("wield", "battlestaff", "use", config::swapBattlestaves); + swap("clean", "use", config::swapHerbs); swap("read", "recite-prayer", config::swapPrayerBook); @@ -355,24 +359,26 @@ public class MenuEntrySwapperPlugin extends Plugin swapTeleport("camelot teleport", "seers'"); swapTeleport("watchtower teleport", "yanille"); swapTeleport("teleport to house", "outside"); + + swap("eat", "guzzle", config::swapRockCake); } - private void swap(String option, String swappedOption, Supplier enabled) + public void swap(String option, String swappedOption, Supplier enabled) { swap(option, alwaysTrue(), swappedOption, enabled); } - private void swap(String option, String target, String swappedOption, Supplier enabled) + public void swap(String option, String target, String swappedOption, Supplier enabled) { swap(option, equalTo(target), swappedOption, enabled); } - private void swap(String option, Predicate targetPredicate, String swappedOption, Supplier enabled) + public void swap(String option, Predicate targetPredicate, String swappedOption, Supplier enabled) { swaps.put(option, new Swap(alwaysTrue(), targetPredicate, swappedOption, enabled, true)); } - private void swapContains(String option, Predicate targetPredicate, String swappedOption, Supplier enabled) + public void swapContains(String option, Predicate targetPredicate, String swappedOption, Supplier enabled) { swaps.put(option, new Swap(alwaysTrue(), targetPredicate, swappedOption, enabled, false)); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/mining/Pickaxe.java b/runelite-client/src/main/java/net/runelite/client/plugins/mining/Pickaxe.java index c0531ac091..9ad4604607 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/mining/Pickaxe.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/mining/Pickaxe.java @@ -34,6 +34,7 @@ import static net.runelite.api.AnimationID.MINING_BRONZE_PICKAXE; import static net.runelite.api.AnimationID.MINING_CRYSTAL_PICKAXE; import static net.runelite.api.AnimationID.MINING_DRAGON_PICKAXE; import static net.runelite.api.AnimationID.MINING_DRAGON_PICKAXE_OR; +import static net.runelite.api.AnimationID.MINING_DRAGON_PICKAXE_OR_TRAILBLAZER; import static net.runelite.api.AnimationID.MINING_DRAGON_PICKAXE_UPGRADED; import static net.runelite.api.AnimationID.MINING_GILDED_PICKAXE; import static net.runelite.api.AnimationID.MINING_INFERNAL_PICKAXE; @@ -46,6 +47,7 @@ import static net.runelite.api.AnimationID.MINING_MOTHERLODE_BRONZE; import static net.runelite.api.AnimationID.MINING_MOTHERLODE_CRYSTAL; import static net.runelite.api.AnimationID.MINING_MOTHERLODE_DRAGON; import static net.runelite.api.AnimationID.MINING_MOTHERLODE_DRAGON_OR; +import static net.runelite.api.AnimationID.MINING_MOTHERLODE_DRAGON_OR_TRAILBLAZER; import static net.runelite.api.AnimationID.MINING_MOTHERLODE_DRAGON_UPGRADED; import static net.runelite.api.AnimationID.MINING_MOTHERLODE_GILDED; import static net.runelite.api.AnimationID.MINING_MOTHERLODE_INFERNAL; @@ -65,6 +67,7 @@ import static net.runelite.api.ItemID.BRONZE_PICKAXE; import static net.runelite.api.ItemID.CRYSTAL_PICKAXE; import static net.runelite.api.ItemID.DRAGON_PICKAXE; import static net.runelite.api.ItemID.DRAGON_PICKAXE_OR; +import static net.runelite.api.ItemID.DRAGON_PICKAXE_OR_25376; import static net.runelite.api.ItemID.DRAGON_PICKAXE_12797; import static net.runelite.api.ItemID.GILDED_PICKAXE; import static net.runelite.api.ItemID.INFERNAL_PICKAXE; @@ -89,6 +92,7 @@ enum Pickaxe GILDED(GILDED_PICKAXE, MINING_GILDED_PICKAXE, MINING_MOTHERLODE_GILDED), DRAGON(DRAGON_PICKAXE, MINING_DRAGON_PICKAXE, MINING_MOTHERLODE_DRAGON), DRAGON_OR(DRAGON_PICKAXE_OR, MINING_DRAGON_PICKAXE_OR, MINING_MOTHERLODE_DRAGON_OR), + DRAGON_OR_TRAILBLAZER(DRAGON_PICKAXE_OR_25376, MINING_DRAGON_PICKAXE_OR_TRAILBLAZER, MINING_MOTHERLODE_DRAGON_OR_TRAILBLAZER), DRAGON_UPGRADED(DRAGON_PICKAXE_12797, MINING_DRAGON_PICKAXE_UPGRADED, MINING_MOTHERLODE_DRAGON_UPGRADED), INFERNAL(INFERNAL_PICKAXE, MINING_INFERNAL_PICKAXE, MINING_MOTHERLODE_INFERNAL), THIRDAGE(_3RD_AGE_PICKAXE, MINING_3A_PICKAXE, MINING_MOTHERLODE_3A), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/motherlode/MotherlodeGemOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/motherlode/MotherlodeGemOverlay.java index 5d6c86a445..2efd088235 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/motherlode/MotherlodeGemOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/motherlode/MotherlodeGemOverlay.java @@ -71,9 +71,9 @@ public class MotherlodeGemOverlay extends OverlayPanel } Duration statTimeout = Duration.ofMinutes(config.statTimeout()); - Duration sinceCut = Duration.between(session.getLastGemFound(), Instant.now()); + Duration sinceLastGem = Duration.between(session.getLastGemFound(), Instant.now()); - if (sinceCut.compareTo(statTimeout) >= 0) + if (sinceLastGem.compareTo(statTimeout) >= 0) { return null; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/motherlode/MotherlodeOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/motherlode/MotherlodeOverlay.java index b3dba5c048..4a6e040f26 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/motherlode/MotherlodeOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/motherlode/MotherlodeOverlay.java @@ -47,8 +47,9 @@ class MotherlodeOverlay extends OverlayPanel MINING_MOTHERLODE_BRONZE, MINING_MOTHERLODE_IRON, MINING_MOTHERLODE_STEEL, MINING_MOTHERLODE_BLACK, MINING_MOTHERLODE_MITHRIL, MINING_MOTHERLODE_ADAMANT, MINING_MOTHERLODE_RUNE, MINING_MOTHERLODE_GILDED, MINING_MOTHERLODE_DRAGON, - MINING_MOTHERLODE_DRAGON_UPGRADED, MINING_MOTHERLODE_DRAGON_OR, MINING_MOTHERLODE_INFERNAL, - MINING_MOTHERLODE_3A, MINING_MOTHERLODE_CRYSTAL, MINING_MOTHERLODE_TRAILBLAZER + MINING_MOTHERLODE_DRAGON_UPGRADED, MINING_MOTHERLODE_DRAGON_OR, MINING_MOTHERLODE_DRAGON_OR_TRAILBLAZER, + MINING_MOTHERLODE_INFERNAL, MINING_MOTHERLODE_3A, MINING_MOTHERLODE_CRYSTAL, + MINING_MOTHERLODE_TRAILBLAZER ); static final String MINING_RESET = "Reset"; @@ -85,9 +86,9 @@ class MotherlodeOverlay extends OverlayPanel } Duration statTimeout = Duration.ofMinutes(config.statTimeout()); - Duration sinceCut = Duration.between(session.getLastPayDirtMined(), Instant.now()); + Duration sinceLastPayDirt = Duration.between(session.getLastPayDirtMined(), Instant.now()); - if (sinceCut.compareTo(statTimeout) >= 0) + if (sinceLastPayDirt.compareTo(statTimeout) >= 0) { return null; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicPlugin.java index 6f3421b08a..b557cc18b3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicPlugin.java @@ -466,6 +466,7 @@ public class MusicPlugin extends Plugin public void update() { + handle.setNoClickThrough(false); handle.setOnDragListener((JavaScriptCallback) this::drag); handle.setOnDragCompleteListener((JavaScriptCallback) this::drag); handle.setHasListener(true); @@ -511,6 +512,9 @@ public class MusicPlugin extends Plugin int level = (x * channel.max) / getWidth(); level = Ints.constrainToRange(level, 0, channel.max); channel.setLevel(level); + + int percent = (int) Math.round((level * 100.0 / channel.getMax())); + sliderTooltip = new Tooltip(channel.getName() + ": " + percent + "%"); } protected int getWidth() diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcMinimapOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcMinimapOverlay.java index 9582288ea1..e1fd961216 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcMinimapOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcMinimapOverlay.java @@ -36,6 +36,7 @@ import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.OverlayLayer; import net.runelite.client.ui.overlay.OverlayPosition; import net.runelite.client.ui.overlay.OverlayUtil; +import net.runelite.client.util.Text; public class NpcMinimapOverlay extends Overlay { @@ -56,7 +57,7 @@ public class NpcMinimapOverlay extends Overlay { for (NPC npc : plugin.getHighlightedNpcs()) { - renderNpcOverlay(graphics, npc, npc.getName(), config.getHighlightColor()); + renderNpcOverlay(graphics, npc, Text.removeTags(npc.getName()), config.getHighlightColor()); } return null; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/objectindicators/ObjectIndicatorsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/objectindicators/ObjectIndicatorsPlugin.java index 46a4a0924d..cfa99092a8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/objectindicators/ObjectIndicatorsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/objectindicators/ObjectIndicatorsPlugin.java @@ -88,7 +88,6 @@ public class ObjectIndicatorsPlugin extends Plugin private static final String MARK = "Mark object"; private static final String UNMARK = "Unmark object"; - private final Gson GSON = new Gson(); @Getter(AccessLevel.PACKAGE) private final List objects = new ArrayList<>(); private final Map> points = new HashMap<>(); @@ -108,6 +107,9 @@ public class ObjectIndicatorsPlugin extends Plugin @Inject private ObjectIndicatorsConfig config; + @Inject + private Gson gson; + @Provides ObjectIndicatorsConfig provideConfig(ConfigManager configManager) { @@ -428,7 +430,7 @@ public class ObjectIndicatorsPlugin extends Plugin } else { - final String json = GSON.toJson(points); + final String json = gson.toJson(points); configManager.setConfiguration(CONFIG_GROUP, "region_" + id, json); } } @@ -442,7 +444,7 @@ public class ObjectIndicatorsPlugin extends Plugin return null; } - Set points = GSON.fromJson(json, new TypeToken>() + Set points = gson.fromJson(json, new TypeToken>() { }.getType()); // Prior to multiloc support the plugin would mark objects named "null", which breaks diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/openosrs/OpenOSRSPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/openosrs/OpenOSRSPlugin.java new file mode 100644 index 0000000000..c991795cce --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/openosrs/OpenOSRSPlugin.java @@ -0,0 +1,131 @@ +/* + * + * Copyright (c) 2019, Zeruth + * 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.openosrs; + +import ch.qos.logback.classic.Logger; +import com.openosrs.client.config.OpenOSRSConfig; +import net.runelite.client.plugins.openosrs.externals.ExternalPluginManagerPanel; +import java.awt.image.BufferedImage; +import javax.inject.Inject; +import javax.inject.Singleton; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.client.config.Keybind; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.events.ConfigChanged; +import net.runelite.client.input.KeyManager; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.ui.ClientToolbar; +import net.runelite.client.ui.NavigationButton; +import net.runelite.client.util.HotkeyListener; +import net.runelite.client.util.ImageUtil; +import org.slf4j.LoggerFactory; + +@PluginDescriptor( + loadWhenOutdated = true, // prevent users from disabling + hidden = true, // prevent users from disabling + name = "OpenOSRS" +) +@Singleton +@Slf4j +public class OpenOSRSPlugin extends Plugin +{ + @Inject + private OpenOSRSConfig config; + + @Inject + private KeyManager keyManager; + + @Inject + private Client client; + + @Inject + private ClientToolbar clientToolbar; + + private NavigationButton navButton; + + private final HotkeyListener hotkeyListener = new HotkeyListener(() -> this.keybind) + { + @Override + public void hotkeyPressed() + { + if (client == null) + { + return; + } + detach = !detach; + client.setOculusOrbState(detach ? 1 : 0); + client.setOculusOrbNormalSpeed(detach ? 36 : 12); + } + }; + private boolean detach; + private Keybind keybind; + + @Override + protected void startUp() + { + ExternalPluginManagerPanel panel = injector.getInstance(ExternalPluginManagerPanel.class); + + final BufferedImage icon = ImageUtil.getResourceStreamFromClass(getClass(), "externalmanager_icon.png"); + + navButton = NavigationButton.builder() + .tooltip("External Plugin Manager") + .icon(icon) + .priority(1) + .panel(panel) + .build(); + clientToolbar.addNavigation(navButton); + + this.keybind = config.detachHotkey(); + keyManager.registerKeyListener(hotkeyListener); + } + + @Override + protected void shutDown() + { + clientToolbar.removeNavigation(navButton); + } + + @Subscribe + private void onConfigChanged(ConfigChanged event) + { + if (!event.getGroup().equals("openosrs")) + { + return; + } + + this.keybind = config.detachHotkey(); + + if (event.getKey().equals("shareLogs") && !config.shareLogs()) + { + final Logger logger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME); + logger.detachAppender("Sentry"); + } + } + +} \ No newline at end of file diff --git a/runelite-client/src/main/java/com/openosrs/client/plugins/openosrs/externals/ExternalBox.java b/runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/ExternalBox.java similarity index 98% rename from runelite-client/src/main/java/com/openosrs/client/plugins/openosrs/externals/ExternalBox.java rename to runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/ExternalBox.java index cdaef1c8cd..51c9e94b90 100644 --- a/runelite-client/src/main/java/com/openosrs/client/plugins/openosrs/externals/ExternalBox.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/ExternalBox.java @@ -1,4 +1,4 @@ -package com.openosrs.client.plugins.openosrs.externals; +package net.runelite.client.plugins.openosrs.externals; import java.awt.BorderLayout; import java.awt.Color; diff --git a/runelite-client/src/main/java/com/openosrs/client/plugins/openosrs/externals/ExternalPluginManagerPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/ExternalPluginManagerPanel.java similarity index 94% rename from runelite-client/src/main/java/com/openosrs/client/plugins/openosrs/externals/ExternalPluginManagerPanel.java rename to runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/ExternalPluginManagerPanel.java index 43211002e5..c4c4ee8390 100644 --- a/runelite-client/src/main/java/com/openosrs/client/plugins/openosrs/externals/ExternalPluginManagerPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/ExternalPluginManagerPanel.java @@ -1,6 +1,6 @@ -package com.openosrs.client.plugins.openosrs.externals; +package net.runelite.client.plugins.openosrs.externals; -import com.openosrs.client.plugins.ExternalPluginManager; +import net.runelite.client.plugins.OPRSExternalPluginManager; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; @@ -46,12 +46,12 @@ public class ExternalPluginManagerPanel extends PluginPanel ADD_HOVER_ICON_GH = new ImageIcon(ImageUtil.alphaOffset(addIconGh, 0.53f)); } - private final ExternalPluginManager externalPluginManager; + private final OPRSExternalPluginManager externalPluginManager; private final ScheduledExecutorService executor; private final EventBus eventBus; @Inject - private ExternalPluginManagerPanel(ExternalPluginManager externalPluginManager, ScheduledExecutorService executor, EventBus eventBus) + private ExternalPluginManagerPanel(OPRSExternalPluginManager externalPluginManager, ScheduledExecutorService executor, EventBus eventBus) { super(false); @@ -134,7 +134,7 @@ public class ExternalPluginManagerPanel extends PluginPanel return; } - if (ExternalPluginManager.testGHRepository(owner.getText(), name.getText())) + if (OPRSExternalPluginManager.testGHRepository(owner.getText(), name.getText())) { JOptionPane.showMessageDialog(ClientUI.getFrame(), "This doesn't appear to be a valid repository.", "Error!", JOptionPane.ERROR_MESSAGE); @@ -222,7 +222,7 @@ public class ExternalPluginManagerPanel extends PluginPanel return; } - if (ExternalPluginManager.testRepository(urlActual)) + if (OPRSExternalPluginManager.testRepository(urlActual)) { JOptionPane.showMessageDialog(ClientUI.getFrame(), "This doesn't appear to be a valid repository.", "Error!", JOptionPane.ERROR_MESSAGE); diff --git a/runelite-client/src/main/java/com/openosrs/client/plugins/openosrs/externals/PluginsPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/PluginsPanel.java similarity index 95% rename from runelite-client/src/main/java/com/openosrs/client/plugins/openosrs/externals/PluginsPanel.java rename to runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/PluginsPanel.java index fa3af31ca2..6989e2ae19 100644 --- a/runelite-client/src/main/java/com/openosrs/client/plugins/openosrs/externals/PluginsPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/PluginsPanel.java @@ -1,12 +1,10 @@ -package com.openosrs.client.plugins.openosrs.externals; +package net.runelite.client.plugins.openosrs.externals; -import com.openosrs.client.plugins.ExternalPluginManager; +import net.runelite.client.plugins.OPRSExternalPluginManager; import com.google.gson.JsonSyntaxException; -import com.openosrs.client.events.ExternalPluginChanged; -import com.openosrs.client.events.ExternalRepositoryChanged; -import com.openosrs.client.util.DeferredDocumentChangedListener; -import com.openosrs.client.util.ImageUtil; -import com.openosrs.client.util.SwingUtil; +import com.openosrs.client.events.OPRSPluginChanged; +import com.openosrs.client.events.OPRSRepositoryChanged; +import net.runelite.client.util.DeferredDocumentChangedListener; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; @@ -45,6 +43,8 @@ import net.runelite.client.ui.FontManager; import net.runelite.client.ui.PluginPanel; import net.runelite.client.ui.components.IconTextField; import net.runelite.client.ui.components.shadowlabel.JShadowedLabel; +import net.runelite.client.util.ImageUtil; +import net.runelite.client.util.SwingUtil; import org.pf4j.update.PluginInfo; import org.pf4j.update.UpdateManager; import org.pf4j.update.UpdateRepository; @@ -82,7 +82,7 @@ public class PluginsPanel extends JPanel DELETE_HOVER_ICON_GRAY = new ImageIcon(ImageUtil.alphaOffset(ImageUtil.grayscaleImage(deleteImg), 0.53f)); } - private final ExternalPluginManager externalPluginManager; + private final OPRSExternalPluginManager externalPluginManager; private final UpdateManager updateManager; private final ScheduledExecutorService executor; private final EventBus eventBus; @@ -97,7 +97,7 @@ public class PluginsPanel extends JPanel private JComboBox filterComboBox; private Set deps; - PluginsPanel(ExternalPluginManager externalPluginManager, ScheduledExecutorService executor, EventBus eventBus) + PluginsPanel(OPRSExternalPluginManager externalPluginManager, ScheduledExecutorService executor, EventBus eventBus) { this.externalPluginManager = externalPluginManager; this.updateManager = externalPluginManager.getUpdateManager(); @@ -123,7 +123,7 @@ public class PluginsPanel extends JPanel } @Subscribe - public void onExternalRepositoryChanged(ExternalRepositoryChanged event) + public void onExternalRepositoryChanged(OPRSRepositoryChanged event) { buildFilter(); reloadPlugins(); @@ -283,7 +283,7 @@ public class PluginsPanel extends JPanel } @Subscribe - private void onExternalPluginChanged(ExternalPluginChanged externalPluginChanged) + private void onExternalPluginChanged(OPRSPluginChanged externalPluginChanged) { String pluginId = externalPluginChanged.getPluginId(); Optional externalBox; diff --git a/runelite-client/src/main/java/com/openosrs/client/plugins/openosrs/externals/RepositoryBox.java b/runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/RepositoryBox.java similarity index 95% rename from runelite-client/src/main/java/com/openosrs/client/plugins/openosrs/externals/RepositoryBox.java rename to runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/RepositoryBox.java index 9a1171d726..8a1aec5eaf 100644 --- a/runelite-client/src/main/java/com/openosrs/client/plugins/openosrs/externals/RepositoryBox.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/RepositoryBox.java @@ -1,8 +1,7 @@ -package com.openosrs.client.plugins.openosrs.externals; +package net.runelite.client.plugins.openosrs.externals; -import com.openosrs.client.plugins.ExternalPluginManager; +import net.runelite.client.plugins.OPRSExternalPluginManager; import com.openosrs.client.ui.JMultilineLabel; -import com.openosrs.client.util.ImageUtil; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; @@ -19,6 +18,7 @@ import javax.swing.border.CompoundBorder; import javax.swing.border.EmptyBorder; import net.runelite.client.ui.ColorScheme; import net.runelite.client.ui.FontManager; +import net.runelite.client.util.ImageUtil; import net.runelite.client.util.LinkBrowser; import org.pf4j.update.PluginInfo; import org.pf4j.update.UpdateRepository; @@ -53,7 +53,7 @@ public class RepositoryBox extends JPanel DISCORD_HOVER_ICON = new ImageIcon(ImageUtil.alphaOffset(discordImg, 0.53f)); } - RepositoryBox(ExternalPluginManager externalPluginManager, UpdateRepository updateRepository) + RepositoryBox(OPRSExternalPluginManager externalPluginManager, UpdateRepository updateRepository) { setLayout(new BorderLayout()); setBackground(ColorScheme.DARKER_GRAY_COLOR); diff --git a/runelite-client/src/main/java/com/openosrs/client/plugins/openosrs/externals/RepositoryPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/RepositoryPanel.java similarity index 73% rename from runelite-client/src/main/java/com/openosrs/client/plugins/openosrs/externals/RepositoryPanel.java rename to runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/RepositoryPanel.java index 1f8973aa88..03a46a751a 100644 --- a/runelite-client/src/main/java/com/openosrs/client/plugins/openosrs/externals/RepositoryPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/RepositoryPanel.java @@ -1,7 +1,7 @@ -package com.openosrs.client.plugins.openosrs.externals; +package net.runelite.client.plugins.openosrs.externals; -import com.openosrs.client.plugins.ExternalPluginManager; -import com.openosrs.client.events.ExternalRepositoryChanged; +import net.runelite.client.plugins.OPRSExternalPluginManager; +import com.openosrs.client.events.OPRSRepositoryChanged; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; @@ -18,11 +18,11 @@ public class RepositoryPanel extends JPanel @Inject public EventBus eventBus; - private final ExternalPluginManager externalPluginManager; + private final OPRSExternalPluginManager externalPluginManager; private final GridBagConstraints c = new GridBagConstraints(); - RepositoryPanel(ExternalPluginManager externalPluginManager, EventBus eventBus) + RepositoryPanel(OPRSExternalPluginManager externalPluginManager, EventBus eventBus) { this.externalPluginManager = externalPluginManager; @@ -36,7 +36,7 @@ public class RepositoryPanel extends JPanel } @Subscribe - private void onExternalRepositoryChanged(ExternalRepositoryChanged event) + private void onExternalRepositoryChanged(OPRSRepositoryChanged event) { removeAll(); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoConfig.java index 6adb3af1f2..ce0c565c03 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoConfig.java @@ -44,7 +44,7 @@ public interface OpponentInfoConfig extends Config @ConfigItem( keyName = "hitpointsDisplayStyle", - name = "Hitpoints display style", + name = "Display style", description = "Show opponent's hitpoints as a value (if known), percentage, or both", position = 1 ) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsConfig.java index cb55db7b1e..5daffe8ef0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsConfig.java @@ -55,7 +55,7 @@ public interface PlayerIndicatorsConfig extends Config @ConfigItem( position = 1, keyName = "ownNameColor", - name = "Own player color", + name = "Own player", description = "Color of your own player", section = highlightSection ) @@ -79,7 +79,7 @@ public interface PlayerIndicatorsConfig extends Config @ConfigItem( position = 3, keyName = "friendNameColor", - name = "Friend color", + name = "Friend", description = "Color of friend names", section = highlightSection ) @@ -103,7 +103,7 @@ public interface PlayerIndicatorsConfig extends Config @ConfigItem( position = 5, keyName = "clanMemberColor", - name = "Friends chat member color", + name = "Friends chat", description = "Color of friends chat members", section = highlightSection ) @@ -127,7 +127,7 @@ public interface PlayerIndicatorsConfig extends Config @ConfigItem( position = 7, keyName = "teamMemberColor", - name = "Team member color", + name = "Team member", description = "Color of team members", section = highlightSection ) @@ -151,7 +151,7 @@ public interface PlayerIndicatorsConfig extends Config @ConfigItem( position = 9, keyName = "nonClanMemberColor", - name = "Others color", + name = "Others", description = "Color of other players names", section = highlightSection ) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerConfig.java index d2cad67fe5..c9fc7fcd2b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerConfig.java @@ -133,7 +133,7 @@ public interface PrayerConfig extends Config @ConfigItem( position = 9, keyName = "replaceOrbText", - name = "Replace orb text with prayer time left", + name = "Show time left", description = "Show time remaining of current prayers in the prayer orb." ) default boolean replaceOrbText() diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/pyramidplunder/PyramidPlunderConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/pyramidplunder/PyramidPlunderConfig.java index aa145fad74..ffde9e56d4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/pyramidplunder/PyramidPlunderConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/pyramidplunder/PyramidPlunderConfig.java @@ -69,7 +69,7 @@ public interface PyramidPlunderConfig extends Config @ConfigItem( position = 3, keyName = "highlightDoorsColor", - name = "Highlight doors color", + name = "Highlight doors", description = "Selects the color for highlighting tomb doors" ) default Color highlightDoorsColor() @@ -92,7 +92,7 @@ public interface PyramidPlunderConfig extends Config @ConfigItem( position = 5, keyName = "highlightSpeartrapColor", - name = "Highlight speartrap color", + name = "Highlight speartrap", description = "Selects the color for highlighting speartraps" ) default Color highlightSpeartrapsColor() @@ -115,7 +115,7 @@ public interface PyramidPlunderConfig extends Config @ConfigItem( position = 7, keyName = "highlightContainersColor", - name = "Highlight containers color", + name = "Highlight containers", description = "Selects the color for highlighting urns, chests and sarcophagus" ) default Color highlightContainersColor() diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsConfig.java index 5a1a81bf7e..3abb6eb4f5 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsConfig.java @@ -47,7 +47,7 @@ public interface RaidsConfig extends Config @ConfigItem( position = 1, keyName = "pointsMessage", - name = "Display points in chatbox after raid", + name = "Display points in chatbox", description = "Display a message with total points, individual points and percentage at the end of a raid" ) default boolean pointsMessage() @@ -69,8 +69,8 @@ public interface RaidsConfig extends Config @ConfigItem( position = 3, keyName = "scoutOverlayAtBank", - name = "Show scout overlay outside lobby", - description = "Keep the overlay active while at the raids area" + name = "Show scout overlay outside", + description = "Keep the overlay active outside of the raid starting room" ) default boolean scoutOverlayAtBank() { @@ -168,8 +168,8 @@ public interface RaidsConfig extends Config @ConfigItem( position = 12, keyName = "layoutMessage", - name = "Send raid layout message when entering raid", - description = "Sends game message with raid layout on entering new raid" + name = "Raid layout message", + description = "Sends a game message with the raid layout on entering a raid" ) default boolean layoutMessage() { @@ -179,7 +179,7 @@ public interface RaidsConfig extends Config @ConfigItem( position = 13, keyName = "screenshotHotkey", - name = "Scouter screenshot hotkey", + name = "Screenshot hotkey", description = "Hotkey used to screenshot the scouting overlay" ) default Keybind screenshotHotkey() @@ -190,7 +190,7 @@ public interface RaidsConfig extends Config @ConfigItem( position = 14, keyName = "uploadScreenshot", - name = "Upload scouting screenshot", + name = "Upload screenshot", description = "Uploads the scouting screenshot to Imgur or the clipboard" ) default ImageUploadStyle uploadScreenshot() diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterConfig.java index a206557fcb..a1a528ae58 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterConfig.java @@ -52,7 +52,7 @@ public interface RegenMeterConfig extends Config @ConfigItem( keyName = "showWhenNoChange", - name = "Show hitpoints regen at full hitpoints", + name = "Show at full hitpoints", description = "Always show the hitpoints regen orb, even if there will be no stat change") default boolean showWhenNoChange() { @@ -61,7 +61,7 @@ public interface RegenMeterConfig extends Config @ConfigItem( keyName = "notifyBeforeHpRegenDuration", - name = "Hitpoint Regen Notification", + name = "Hitpoint Notification", description = "Notify approximately when your next hitpoint is about to regen. A value of 0 will disable notification." ) @Units(Units.SECONDS) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterPlugin.java index 6339ce5486..2160148401 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterPlugin.java @@ -166,7 +166,7 @@ public class RegenMeterPlugin extends Plugin if (config.getNotifyBeforeHpRegenSeconds() > 0 && currentHP < maxHP && shouldNotifyHpRegenThisTick(ticksPerHPRegen)) { - notifier.notify("[" + client.getLocalPlayer().getName() + "] regenerates their next hitpoint soon!"); + notifier.notify("Your next hitpoint will regenerate soon!"); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runenergy/RunEnergyPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/runenergy/RunEnergyPlugin.java index 867134f8fd..004396a75e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runenergy/RunEnergyPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runenergy/RunEnergyPlugin.java @@ -63,35 +63,35 @@ public class RunEnergyPlugin extends Plugin GRACEFUL_HOOD_11851, GRACEFUL_HOOD_13579, GRACEFUL_HOOD_13580, GRACEFUL_HOOD_13591, GRACEFUL_HOOD_13592, GRACEFUL_HOOD_13603, GRACEFUL_HOOD_13604, GRACEFUL_HOOD_13615, GRACEFUL_HOOD_13616, GRACEFUL_HOOD_13627, GRACEFUL_HOOD_13628, GRACEFUL_HOOD_13667, GRACEFUL_HOOD_13668, GRACEFUL_HOOD_21061, GRACEFUL_HOOD_21063, - GRACEFUL_HOOD_24743, GRACEFUL_HOOD_24745 + GRACEFUL_HOOD_24743, GRACEFUL_HOOD_24745, GRACEFUL_HOOD_25069, GRACEFUL_HOOD_25071 ); private static final ImmutableSet ALL_GRACEFUL_TOPS = ImmutableSet.of( GRACEFUL_TOP_11855, GRACEFUL_TOP_13583, GRACEFUL_TOP_13584, GRACEFUL_TOP_13595, GRACEFUL_TOP_13596, GRACEFUL_TOP_13607, GRACEFUL_TOP_13608, GRACEFUL_TOP_13619, GRACEFUL_TOP_13620, GRACEFUL_TOP_13631, GRACEFUL_TOP_13632, GRACEFUL_TOP_13671, GRACEFUL_TOP_13672, GRACEFUL_TOP_21067, GRACEFUL_TOP_21069, - GRACEFUL_TOP_24749, GRACEFUL_TOP_24751 + GRACEFUL_TOP_24749, GRACEFUL_TOP_24751, GRACEFUL_TOP_25075, GRACEFUL_TOP_25077 ); private static final ImmutableSet ALL_GRACEFUL_LEGS = ImmutableSet.of( GRACEFUL_LEGS_11857, GRACEFUL_LEGS_13585, GRACEFUL_LEGS_13586, GRACEFUL_LEGS_13597, GRACEFUL_LEGS_13598, GRACEFUL_LEGS_13609, GRACEFUL_LEGS_13610, GRACEFUL_LEGS_13621, GRACEFUL_LEGS_13622, GRACEFUL_LEGS_13633, GRACEFUL_LEGS_13634, GRACEFUL_LEGS_13673, GRACEFUL_LEGS_13674, GRACEFUL_LEGS_21070, GRACEFUL_LEGS_21072, - GRACEFUL_LEGS_24752, GRACEFUL_LEGS_24754 + GRACEFUL_LEGS_24752, GRACEFUL_LEGS_24754, GRACEFUL_LEGS_25078, GRACEFUL_LEGS_25080 ); private static final ImmutableSet ALL_GRACEFUL_GLOVES = ImmutableSet.of( GRACEFUL_GLOVES_11859, GRACEFUL_GLOVES_13587, GRACEFUL_GLOVES_13588, GRACEFUL_GLOVES_13599, GRACEFUL_GLOVES_13600, GRACEFUL_GLOVES_13611, GRACEFUL_GLOVES_13612, GRACEFUL_GLOVES_13623, GRACEFUL_GLOVES_13624, GRACEFUL_GLOVES_13635, GRACEFUL_GLOVES_13636, GRACEFUL_GLOVES_13675, GRACEFUL_GLOVES_13676, GRACEFUL_GLOVES_21073, GRACEFUL_GLOVES_21075, - GRACEFUL_GLOVES_24755, GRACEFUL_GLOVES_24757 + GRACEFUL_GLOVES_24755, GRACEFUL_GLOVES_24757, GRACEFUL_GLOVES_25081, GRACEFUL_GLOVES_25083 ); private static final ImmutableSet ALL_GRACEFUL_BOOTS = ImmutableSet.of( GRACEFUL_BOOTS_11861, GRACEFUL_BOOTS_13589, GRACEFUL_BOOTS_13590, GRACEFUL_BOOTS_13601, GRACEFUL_BOOTS_13602, GRACEFUL_BOOTS_13613, GRACEFUL_BOOTS_13614, GRACEFUL_BOOTS_13625, GRACEFUL_BOOTS_13626, GRACEFUL_BOOTS_13637, GRACEFUL_BOOTS_13638, GRACEFUL_BOOTS_13677, GRACEFUL_BOOTS_13678, GRACEFUL_BOOTS_21076, GRACEFUL_BOOTS_21078, - GRACEFUL_BOOTS_24758, GRACEFUL_BOOTS_24760 + GRACEFUL_BOOTS_24758, GRACEFUL_BOOTS_24760, GRACEFUL_BOOTS_25084, GRACEFUL_BOOTS_25086 ); // Agility skill capes and the non-cosmetic Max capes also count for the Graceful set effect @@ -99,7 +99,8 @@ public class RunEnergyPlugin extends Plugin GRACEFUL_CAPE_11853, GRACEFUL_CAPE_13581, GRACEFUL_CAPE_13582, GRACEFUL_CAPE_13593, GRACEFUL_CAPE_13594, GRACEFUL_CAPE_13605, GRACEFUL_CAPE_13606, GRACEFUL_CAPE_13617, GRACEFUL_CAPE_13618, GRACEFUL_CAPE_13629, GRACEFUL_CAPE_13630, GRACEFUL_CAPE_13669, GRACEFUL_CAPE_13670, GRACEFUL_CAPE_21064, GRACEFUL_CAPE_21066, - GRACEFUL_CAPE_24746, GRACEFUL_CAPE_24748, AGILITY_CAPE, AGILITY_CAPET, MAX_CAPE + GRACEFUL_CAPE_24746, GRACEFUL_CAPE_24748, GRACEFUL_CAPE_25072, GRACEFUL_CAPE_25074, + AGILITY_CAPE, AGILITY_CAPET, MAX_CAPE ); @RequiredArgsConstructor diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerPlugin.java index 88dca9d214..5ec747e3f5 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerPlugin.java @@ -88,6 +88,9 @@ public class ScreenMarkerPlugin extends Plugin @Inject private ScreenMarkerCreationOverlay overlay; + @Inject + private Gson gson; + @Getter @Inject private ColorPickerManager colorPickerManager; @@ -266,7 +269,6 @@ public class ScreenMarkerPlugin extends Plugin return; } - final Gson gson = new Gson(); final String json = gson .toJson(screenMarkers.stream().map(ScreenMarkerOverlay::getMarker).collect(Collectors.toList())); configManager.setConfiguration(CONFIG_GROUP, CONFIG_KEY, json); @@ -279,7 +281,6 @@ public class ScreenMarkerPlugin extends Plugin return Stream.empty(); } - final Gson gson = new Gson(); final List screenMarkerData = gson.fromJson(json, new TypeToken>() { }.getType()); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotConfig.java index 269eb8554a..44d9d58b51 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotConfig.java @@ -205,11 +205,23 @@ public interface ScreenshotConfig extends Config return false; } + @ConfigItem( + keyName = "valuableDropThreshold", + name = "Valuable Threshold", + description = "The minimum value to save screenshots of valuable drops.", + position = 14, + section = whatSection + ) + default int valuableDropThreshold() + { + return 0; + } + @ConfigItem( keyName = "untradeableDrop", name = "Screenshot Untradeable drops", description = "Configures whether or not screenshots are automatically taken when you receive an untradeable drop.", - position = 14, + position = 15, section = whatSection ) default boolean screenshotUntradeableDrop() @@ -221,7 +233,7 @@ public interface ScreenshotConfig extends Config keyName = "ccKick", name = "Screenshot Kicks from FC", description = "Take a screenshot when you kick a user from a friends chat.", - position = 15, + position = 16, section = whatSection ) default boolean screenshotKick() @@ -233,7 +245,7 @@ public interface ScreenshotConfig extends Config keyName = "baHighGamble", name = "Screenshot BA high gambles", description = "Take a screenshot of your reward from a high gamble at Barbarian Assault.", - position = 16, + position = 17, section = whatSection ) default boolean screenshotHighGamble() @@ -245,7 +257,7 @@ public interface ScreenshotConfig extends Config keyName = "hotkey", name = "Screenshot hotkey", description = "When you press this key a screenshot will be taken", - position = 17 + position = 18 ) default Keybind hotkey() { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotPlugin.java index b199248c39..0dada91ae6 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotPlugin.java @@ -99,7 +99,7 @@ public class ScreenshotPlugin extends Plugin private static final Pattern NUMBER_PATTERN = Pattern.compile("([0-9]+)"); private static final Pattern LEVEL_UP_PATTERN = Pattern.compile(".*Your ([a-zA-Z]+) (?:level is|are)? now (\\d+)\\."); private static final Pattern BOSSKILL_MESSAGE_PATTERN = Pattern.compile("Your (.+) kill count is: (\\d+)."); - private static final Pattern VALUABLE_DROP_PATTERN = Pattern.compile(".*Valuable drop: ([^<>]+)(?:)?"); + private static final Pattern VALUABLE_DROP_PATTERN = Pattern.compile(".*Valuable drop: ([^<>]+?\\(((?:\\d+,?)+) coins\\))(?:)?"); private static final Pattern UNTRADEABLE_DROP_PATTERN = Pattern.compile(".*Untradeable drop: ([^<>]+)(?:)?"); private static final Pattern DUEL_END_PATTERN = Pattern.compile("You have now (won|lost) ([0-9]+) duels?\\."); private static final Pattern QUEST_PATTERN_1 = Pattern.compile(".+?ve\\.*? (?been|rebuilt|.+?ed)? ?(?:the )?'?(?.+?)'?(?: [Qq]uest)?[!.]?$"); @@ -417,9 +417,13 @@ public class ScreenshotPlugin extends Plugin Matcher m = VALUABLE_DROP_PATTERN.matcher(chatMessage); if (m.matches()) { - String valuableDropName = m.group(1); - String fileName = "Valuable drop " + valuableDropName; - takeScreenshot(fileName, "Valuable Drops"); + int valuableDropValue = Integer.parseInt(m.group(2).replaceAll(",", "")); + if (valuableDropValue >= config.valuableDropThreshold()) + { + String valuableDropName = m.group(1); + String fileName = "Valuable drop " + valuableDropName; + takeScreenshot(fileName, "Valuable Drops"); + } } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/SkillCalculator.java b/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/SkillCalculator.java index 64422ee34c..bd688d3788 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/SkillCalculator.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/SkillCalculator.java @@ -30,6 +30,8 @@ import java.awt.Color; import java.awt.Dimension; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.text.DecimalFormat; @@ -95,7 +97,14 @@ class SkillCalculator extends JPanel searchBar.setBackground(ColorScheme.DARKER_GRAY_COLOR); searchBar.setHoverBackgroundColor(ColorScheme.DARK_GRAY_HOVER_COLOR); searchBar.addClearListener(this::onSearch); - searchBar.addKeyListener(e -> onSearch()); + searchBar.addKeyListener(new KeyAdapter() + { + @Override + public void keyTyped(KeyEvent e) + { + onSearch(); + } + }); setLayout(new DynamicGridLayout(0, 1, 0, 5)); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerPlugin.java index 72ad3524ee..db9b247fe3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerPlugin.java @@ -99,7 +99,7 @@ public class SlayerPlugin extends Plugin //Chat messages private static final Pattern CHAT_GEM_PROGRESS_MESSAGE = Pattern.compile("^(?:You're assigned to kill|You have received a new Slayer assignment from .*:) (?:[Tt]he )?(?.+?)(?: (?:in|on|south of) (?:the )?(?[^;]+))?(?:; only | \\()(?\\d+)(?: more to go\\.|\\))$"); private static final String CHAT_GEM_COMPLETE_MESSAGE = "You need something new to hunt."; - private static final Pattern CHAT_COMPLETE_MESSAGE = Pattern.compile("(?:\\d+,)*\\d+"); + private static final Pattern CHAT_COMPLETE_MESSAGE = Pattern.compile("You've completed (?:at least )?(?[\\d,]+) (?:Wilderness )?tasks?(?: and received \\d+ points, giving you a total of (?[\\d,]+)| and reached the maximum amount of Slayer points \\((?[\\d,]+)\\))?"); private static final String CHAT_CANCEL_MESSAGE = "Your task has been cancelled."; private static final String CHAT_CANCEL_MESSAGE_JAD = "You no longer have a slayer task as you left the fight cave."; private static final String CHAT_CANCEL_MESSAGE_ZUK = "You no longer have a slayer task as you left the Inferno."; @@ -450,6 +450,7 @@ public class SlayerPlugin extends Plugin expeditiousChargeCount = Integer.parseInt(mExpeditious.group(1)); config.expeditious(expeditiousChargeCount); } + if (chatMsg.startsWith(CHAT_BRACELET_SLAUGHTER_CHARGE)) { Matcher mSlaughter = CHAT_BRACELET_SLAUGHTER_CHARGE_REGEX.matcher(chatMsg); @@ -466,35 +467,25 @@ public class SlayerPlugin extends Plugin { Matcher mComplete = CHAT_COMPLETE_MESSAGE.matcher(chatMsg); - List matches = new ArrayList<>(); - while (mComplete.find()) + if (mComplete.find()) { - matches.add(mComplete.group(0).replaceAll(",", "")); - } + String mTasks = mComplete.group("tasks"); + String mPoints = mComplete.group("points"); + if (mPoints == null) + { + mPoints = mComplete.group("points2"); + } - int streak = -1, points = -1; - switch (matches.size()) - { - case 0: - streak = 1; - break; - case 1: - streak = Integer.parseInt(matches.get(0)); - break; - case 3: - streak = Integer.parseInt(matches.get(0)); - points = Integer.parseInt(matches.get(2)); - break; - default: - log.warn("Unreachable default case for message ending in '; return to Slayer master'"); - } - if (streak != -1) - { - config.streak(streak); - } - if (points != -1) - { - config.points(points); + if (mTasks != null) + { + int streak = Integer.parseInt(mTasks.replace(",", "")); + config.streak(streak); + } + if (mPoints != null) + { + int points = Integer.parseInt(mPoints.replace(",", "")); + config.points(points); + } } setTask("", 0, 0); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/Task.java b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/Task.java index 8e02556440..29867dc042 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/Task.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/Task.java @@ -202,6 +202,7 @@ enum Task "Fremennik Slayer Dungeon", "God Wars Dungeon", "Iorwerth Dungeon", + "Isle of Souls", "Jormungand's Prison", "Kalphite Lair", "Karuulm Slayer Dungeon", diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/specialcounter/SpecialCounterPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/specialcounter/SpecialCounterPlugin.java index 799dd098ef..65f41baf67 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/specialcounter/SpecialCounterPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/specialcounter/SpecialCounterPlugin.java @@ -60,7 +60,7 @@ import net.runelite.client.ws.WSClient; @PluginDescriptor( name = "Special Attack Counter", - description = "Track DWH, Arclight, Darklight, and BGS special attacks used on NPCs", + description = "Track special attacks used on NPCs", tags = {"combat", "npcs", "overlay"}, enabledByDefault = false ) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/specialcounter/SpecialWeapon.java b/runelite-client/src/main/java/net/runelite/client/plugins/specialcounter/SpecialWeapon.java index e3cd82cfc6..a566f7680b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/specialcounter/SpecialWeapon.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/specialcounter/SpecialWeapon.java @@ -37,7 +37,13 @@ enum SpecialWeapon ARCLIGHT("Arclight", ItemID.ARCLIGHT, false, SpecialCounterConfig::arclightThreshold), DARKLIGHT("Darklight", ItemID.DARKLIGHT, false, SpecialCounterConfig::darklightThreshold), BANDOS_GODSWORD("Bandos Godsword", ItemID.BANDOS_GODSWORD, true, SpecialCounterConfig::bandosGodswordThreshold), - BANDOS_GODSWORD_OR("Bandos Godsword", ItemID.BANDOS_GODSWORD_OR, true, SpecialCounterConfig::bandosGodswordThreshold); + BANDOS_GODSWORD_OR("Bandos Godsword", ItemID.BANDOS_GODSWORD_OR, true, SpecialCounterConfig::bandosGodswordThreshold), + BARRELCHEST_ANCHOR("Barrelchest Anchor", ItemID.BARRELCHEST_ANCHOR, true, (c) -> 0), + BONE_DAGGER("Bone Dagger", ItemID.BONE_DAGGER, true, (c) -> 0), + BONE_DAGGER_P("Bone Dagger (p)", ItemID.BONE_DAGGER_P, true, (c) -> 0), + BONE_DAGGER_P8876("Bone Dagger (p+)", ItemID.BONE_DAGGER_P_8876, true, (c) -> 0), + BONE_DAGGER_P8878("Bone Dagger (p++)", ItemID.BONE_DAGGER_P_8878, true, (c) -> 0), + DORGESHUUN_CROSSBOW("Dorgeshuun Crossbow", ItemID.DORGESHUUN_CROSSBOW, true, (c) -> 0); private final String name; private final int itemID; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/statusbars/StatusBarsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/statusbars/StatusBarsConfig.java index b6883037b7..0624edbdc6 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/statusbars/StatusBarsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/statusbars/StatusBarsConfig.java @@ -64,7 +64,7 @@ public interface StatusBarsConfig extends Config @ConfigItem( keyName = "leftBarMode", - name = "Left Status Bar", + name = "Left Bar", description = "Configures the left status bar" ) default BarMode leftBarMode() @@ -74,7 +74,7 @@ public interface StatusBarsConfig extends Config @ConfigItem( keyName = "rightBarMode", - name = "Right Status Bar", + name = "Right Bar", description = "Configures the right status bar" ) default BarMode rightBarMode() diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/teamcapes/TeamCapesOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/teamcapes/TeamCapesOverlay.java index 8ec93c1b18..1d54c85935 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/teamcapes/TeamCapesOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/teamcapes/TeamCapesOverlay.java @@ -39,7 +39,7 @@ import net.runelite.client.ui.overlay.OverlayPriority; import net.runelite.client.ui.overlay.components.ComponentOrientation; import net.runelite.client.ui.overlay.components.ImageComponent; -public class TeamCapesOverlay extends OverlayPanel +class TeamCapesOverlay extends OverlayPanel { private final TeamCapesPlugin plugin; private final TeamCapesConfig config; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/teamcapes/TeamCapesPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/teamcapes/TeamCapesPlugin.java index 103129d64f..c36b7ddd76 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/teamcapes/TeamCapesPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/teamcapes/TeamCapesPlugin.java @@ -25,21 +25,24 @@ package net.runelite.client.plugins.teamcapes; import com.google.inject.Provides; -import java.time.temporal.ChronoUnit; import java.util.Comparator; import java.util.HashMap; import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; import java.util.stream.Collectors; import javax.inject.Inject; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; -import net.runelite.api.GameState; import net.runelite.api.Player; +import net.runelite.api.events.PlayerChanged; +import net.runelite.api.events.PlayerDespawned; +import net.runelite.client.callback.ClientThread; import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.task.Schedule; import net.runelite.client.ui.overlay.OverlayManager; @PluginDescriptor( @@ -48,19 +51,26 @@ import net.runelite.client.ui.overlay.OverlayManager; tags = {"overlay", "players"}, enabledByDefault = false ) +@Slf4j public class TeamCapesPlugin extends Plugin { @Inject private Client client; + @Inject + private ClientThread clientThread; + @Inject private OverlayManager overlayManager; @Inject private TeamCapesOverlay overlay; - // Hashmap of team capes: Key is the teamCape #, Value is the count of teamcapes in the area. - private Map teams = new HashMap<>(); + // Team number -> Number of players + @Getter(AccessLevel.PACKAGE) + private Map teams = new LinkedHashMap<>(); + // Player -> Team number + private final Map playerTeam = new HashMap<>(); @Provides TeamCapesConfig provideConfig(ConfigManager configManager) @@ -72,6 +82,8 @@ public class TeamCapesPlugin extends Plugin protected void startUp() throws Exception { overlayManager.add(overlay); + + clientThread.invokeLater(() -> client.getPlayers().forEach(this::update)); } @Override @@ -79,48 +91,61 @@ public class TeamCapesPlugin extends Plugin { overlayManager.remove(overlay); teams.clear(); + playerTeam.clear(); } - @Schedule( - period = 1800, - unit = ChronoUnit.MILLIS - ) - public void update() + @Subscribe + public void onPlayerChanged(PlayerChanged playerChanged) { - if (client.getGameState() != GameState.LOGGED_IN) + Player player = playerChanged.getPlayer(); + update(player); + } + + private void update(Player player) + { + int oldTeam = playerTeam.getOrDefault(player, 0); + if (oldTeam == player.getTeam()) { return; } - List players = client.getPlayers(); - teams.clear(); - for (Player player : players) + + log.debug("{} has changed teams: {} -> {}", player.getName(), oldTeam, player.getTeam()); + + if (oldTeam > 0) { - int team = player.getTeam(); - if (team > 0) - { - if (teams.containsKey(team)) - { - teams.put(team, teams.get(team) + 1); - } - else - { - teams.put(team, 1); - } - } + teams.computeIfPresent(oldTeam, (key, value) -> value > 1 ? value - 1 : null); + playerTeam.remove(player); } + if (player.getTeam() > 0) + { + teams.merge(player.getTeam(), 1, Integer::sum); + playerTeam.put(player, player.getTeam()); + } + + sort(); + } + + @Subscribe + public void onPlayerDespawned(PlayerDespawned playerDespawned) + { + Player player = playerDespawned.getPlayer(); + Integer team = playerTeam.remove(player); + if (team != null) + { + teams.computeIfPresent(team, (key, value) -> value > 1 ? value - 1 : null); + sort(); + } + } + + private void sort() + { // Sort teams by value in descending order and then by key in ascending order, limited to 5 entries teams = teams.entrySet().stream() - .sorted( - Comparator.comparing(Map.Entry::getValue, Comparator.reverseOrder()) - .thenComparingInt(Map.Entry::getKey) - ) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)); + .sorted( + Comparator.comparing(Map.Entry::getValue, Comparator.reverseOrder()) + .thenComparingInt(Map.Entry::getKey) + ) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)); } - - public Map getTeams() - { - return teams; - } - } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/tearsofguthix/TearsOfGuthixConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/tearsofguthix/TearsOfGuthixConfig.java new file mode 100644 index 0000000000..936a14db20 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/tearsofguthix/TearsOfGuthixConfig.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2020, cgati + * 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.tearsofguthix; + +import java.awt.Color; +import net.runelite.client.config.Alpha; +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; +import net.runelite.client.util.ColorUtil; + +@ConfigGroup("tearsofguthix") +public interface TearsOfGuthixConfig extends Config +{ + @ConfigItem( + keyName = "showGreenTearsTimer", + name = "Enable Green Tears Timer", + description = "Configures whether to display a timer for green tears or not", + position = 1 + ) + default boolean showGreenTearsTimer() + { + return true; + } + + @Alpha + @ConfigItem( + keyName = "blueTearsColor", + name = "Blue Tears Color", + description = "Color of Blue Tears timer", + position = 2 + ) + default Color getBlueTearsColor() + { + return ColorUtil.colorWithAlpha(Color.CYAN, 100); + } + + @Alpha + @ConfigItem( + keyName = "greenTearsColor", + name = "Green Tears Color", + description = "Color of Green Tears timer", + position = 3 + ) + default Color getGreenTearsColor() + { + return ColorUtil.colorWithAlpha(Color.GREEN, 100); + } + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/tearsofguthix/TearsOfGuthixOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/tearsofguthix/TearsOfGuthixOverlay.java index 87148caef7..63964d5541 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/tearsofguthix/TearsOfGuthixOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/tearsofguthix/TearsOfGuthixOverlay.java @@ -36,17 +36,18 @@ import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.OverlayLayer; import net.runelite.client.ui.overlay.OverlayPosition; import net.runelite.client.ui.overlay.components.ProgressPieComponent; +import net.runelite.client.util.ColorUtil; class TearsOfGuthixOverlay extends Overlay { - private static final Color CYAN_ALPHA = new Color(Color.CYAN.getRed(), Color.CYAN.getGreen(), Color.CYAN.getBlue(), 100); - private static final Color GREEN_ALPHA = new Color(Color.GREEN.getRed(), Color.GREEN.getGreen(), Color.GREEN.getBlue(), 100); private static final Duration MAX_TIME = Duration.ofSeconds(9); + private final TearsOfGuthixConfig config; private final TearsOfGuthixPlugin plugin; @Inject - private TearsOfGuthixOverlay(TearsOfGuthixPlugin plugin) + private TearsOfGuthixOverlay(TearsOfGuthixConfig config, TearsOfGuthixPlugin plugin) { + this.config = config; this.plugin = plugin; setPosition(OverlayPosition.DYNAMIC); setLayer(OverlayLayer.ABOVE_SCENE); @@ -55,8 +56,24 @@ class TearsOfGuthixOverlay extends Overlay @Override public Dimension render(Graphics2D graphics) { + if (plugin.getStreams().isEmpty()) + { + return null; + } + + Color blueTearsFill = config.getBlueTearsColor(); + Color greenTearsFill = config.getGreenTearsColor(); + Color blueTearsBorder = ColorUtil.colorWithAlpha(blueTearsFill, 255); + Color greenTearsBorder = ColorUtil.colorWithAlpha(greenTearsFill, 255); + plugin.getStreams().forEach((object, timer) -> { + if ((object.getId() == ObjectID.GREEN_TEARS || object.getId() == ObjectID.GREEN_TEARS_6666) + && !config.showGreenTearsTimer()) + { + return; + } + final Point position = object.getCanvasLocation(100); if (position == null) @@ -70,14 +87,14 @@ class TearsOfGuthixOverlay extends Overlay if (object.getId() == ObjectID.BLUE_TEARS || object.getId() == ObjectID.BLUE_TEARS_6665) { - progressPie.setFill(CYAN_ALPHA); - progressPie.setBorderColor(Color.CYAN); + progressPie.setFill(blueTearsFill); + progressPie.setBorderColor(blueTearsBorder); } else if (object.getId() == ObjectID.GREEN_TEARS || object.getId() == ObjectID.GREEN_TEARS_6666) { - progressPie.setFill(GREEN_ALPHA); - progressPie.setBorderColor(Color.GREEN); + progressPie.setFill(greenTearsFill); + progressPie.setBorderColor(greenTearsBorder); } progressPie.setPosition(position); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/tearsofguthix/TearsOfGuthixPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/tearsofguthix/TearsOfGuthixPlugin.java index 899182b500..5b315bb142 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/tearsofguthix/TearsOfGuthixPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/tearsofguthix/TearsOfGuthixPlugin.java @@ -28,6 +28,7 @@ import java.time.Instant; import java.util.HashMap; import java.util.Map; import javax.inject.Inject; +import com.google.inject.Provides; import lombok.Getter; import net.runelite.api.Client; import net.runelite.api.DecorativeObject; @@ -35,6 +36,7 @@ import net.runelite.api.ObjectID; import net.runelite.api.events.DecorativeObjectDespawned; import net.runelite.api.events.DecorativeObjectSpawned; import net.runelite.api.events.GameStateChanged; +import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; @@ -61,6 +63,12 @@ public class TearsOfGuthixPlugin extends Plugin @Getter private final Map streams = new HashMap<>(); + @Provides + TearsOfGuthixConfig provideConfig(ConfigManager configManager) + { + return configManager.getConfig(TearsOfGuthixConfig.class); + } + @Override protected void startUp() { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/tileindicators/TileIndicatorsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/tileindicators/TileIndicatorsConfig.java index a03f07e5f7..c1ab681930 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/tileindicators/TileIndicatorsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/tileindicators/TileIndicatorsConfig.java @@ -36,8 +36,9 @@ public interface TileIndicatorsConfig extends Config @Alpha @ConfigItem( keyName = "highlightDestinationColor", - name = "Color of current destination highlighting", - description = "Configures the highlight color of current destination" + name = "Destination tile", + description = "Configures the highlight color of current destination", + position = 1 ) default Color highlightDestinationColor() { @@ -47,7 +48,8 @@ public interface TileIndicatorsConfig extends Config @ConfigItem( keyName = "highlightDestinationTile", name = "Highlight destination tile", - description = "Highlights tile player is walking to" + description = "Highlights tile player is walking to", + position = 2 ) default boolean highlightDestinationTile() { @@ -57,8 +59,9 @@ public interface TileIndicatorsConfig extends Config @Alpha @ConfigItem( keyName = "highlightHoveredColor", - name = "Color of current hovered highlighting", - description = "Configures the highlight color of hovered tile" + name = "Hovered tile", + description = "Configures the highlight color of hovered tile", + position = 3 ) default Color highlightHoveredColor() { @@ -68,7 +71,8 @@ public interface TileIndicatorsConfig extends Config @ConfigItem( keyName = "highlightHoveredTile", name = "Highlight hovered tile", - description = "Highlights tile player is hovering with mouse" + description = "Highlights tile player is hovering with mouse", + position = 4 ) default boolean highlightHoveredTile() { @@ -78,8 +82,9 @@ public interface TileIndicatorsConfig extends Config @Alpha @ConfigItem( keyName = "highlightCurrentColor", - name = "Color of current true tile highlighting", - description = "Configures the highlight color of current true tile" + name = "True tile", + description = "Configures the highlight color of current true tile", + position = 5 ) default Color highlightCurrentColor() { @@ -88,8 +93,9 @@ public interface TileIndicatorsConfig extends Config @ConfigItem( keyName = "highlightCurrentTile", - name = "Highlight current true tile", - description = "Highlights true tile player is on as seen by server" + name = "Highlight true tile", + description = "Highlights true tile player is on as seen by server", + position = 6 ) default boolean highlightCurrentTile() { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimersPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimersPlugin.java index fb8572a853..341c1c35a0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimersPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimersPlugin.java @@ -89,6 +89,7 @@ public class TimersPlugin extends Plugin private static final String CANNON_FURNACE_MESSAGE = "You add the furnace."; private static final String CANNON_PICKUP_MESSAGE = "You pick up the cannon. It's really heavy."; private static final String CANNON_REPAIR_MESSAGE = "You repair your cannon, restoring it to working order."; + private static final String CANNON_DESTROYED_MESSAGE = "Your cannon has been destroyed!"; private static final String CHARGE_EXPIRED_MESSAGE = "Your magical charge fades away."; private static final String CHARGE_MESSAGE = "You feel charged with magic power."; private static final String EXTENDED_ANTIFIRE_DRINK_MESSAGE = "You drink some of your extended antifire potion."; @@ -517,7 +518,7 @@ public class TimersPlugin extends Plugin cannonTimer.setTooltip(cannonTimer.getTooltip() + " - World " + client.getWorld()); } - if (config.showCannon() && message.equals(CANNON_PICKUP_MESSAGE)) + if (config.showCannon() && (message.equals(CANNON_PICKUP_MESSAGE) || message.equals(CANNON_DESTROYED_MESSAGE))) { removeGameTimer(CANNON); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TabContentPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TabContentPanel.java index dd3a2bba5b..88b6362e26 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TabContentPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TabContentPanel.java @@ -77,7 +77,7 @@ public abstract class TabContentPanel extends JPanel LocalDateTime currentTime = LocalDateTime.now(); if (endTime.getDayOfWeek() != currentTime.getDayOfWeek()) { - sb.append(endTime.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.getDefault())).append(" "); + sb.append(endTime.getDayOfWeek().getDisplayName(TextStyle.SHORT, Locale.getDefault())).append(" "); } sb.append("at "); sb.append(formatter.format(endTime)); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingConfig.java index 76ceb67bc6..aa284ee86c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingConfig.java @@ -40,6 +40,8 @@ public interface TimeTrackingConfig extends Config String BOTANIST = "botanist"; String TIMERS = "timers"; String STOPWATCHES = "stopwatches"; + String PREFER_SOONEST = "preferSoonest"; + String NOTIFY = "notify"; @ConfigItem( keyName = "timeFormatMode", @@ -110,7 +112,7 @@ public interface TimeTrackingConfig extends Config @ConfigItem( keyName = "timerWarningThreshold", - name = "Timer Warning Threshold", + name = "Warning Threshold", description = "The time at which to change the timer color to the warning color", position = 6 ) @@ -120,6 +122,17 @@ public interface TimeTrackingConfig extends Config return 10; } + @ConfigItem( + keyName = PREFER_SOONEST, + name = "Prefer soonest completion", + description = "When displaying completion times on the overview, prefer showing the soonest any patch will complete.", + position = 7 + ) + default boolean preferSoonest() + { + return false; + } + @ConfigItem( keyName = "activeTab", name = "Active Tab", diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingPlugin.java index 0f6f3c30f1..7eee98df8c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingPlugin.java @@ -29,7 +29,6 @@ import com.google.inject.Inject; import com.google.inject.Provides; import java.awt.image.BufferedImage; import java.time.Instant; -import java.time.temporal.ChronoUnit; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; @@ -51,13 +50,13 @@ import net.runelite.client.events.RuneScapeProfileChanged; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import static net.runelite.client.plugins.timetracking.TimeTrackingConfig.CONFIG_GROUP; +import static net.runelite.client.plugins.timetracking.TimeTrackingConfig.PREFER_SOONEST; import static net.runelite.client.plugins.timetracking.TimeTrackingConfig.STOPWATCHES; import static net.runelite.client.plugins.timetracking.TimeTrackingConfig.TIMERS; import net.runelite.client.plugins.timetracking.clocks.ClockManager; import net.runelite.client.plugins.timetracking.farming.FarmingContractManager; import net.runelite.client.plugins.timetracking.farming.FarmingTracker; import net.runelite.client.plugins.timetracking.hunter.BirdHouseTracker; -import net.runelite.client.task.Schedule; import net.runelite.client.ui.ClientToolbar; import net.runelite.client.ui.NavigationButton; import net.runelite.client.ui.overlay.infobox.InfoBoxManager; @@ -101,6 +100,8 @@ public class TimeTrackingPlugin extends Plugin private ScheduledFuture panelUpdateFuture; + private ScheduledFuture notifierFuture; + private TimeTrackingPanel panel; private NavigationButton navButton; @@ -138,6 +139,7 @@ public class TimeTrackingPlugin extends Plugin clientToolbar.addNavigation(navButton); panelUpdateFuture = executorService.scheduleAtFixedRate(this::updatePanel, 200, 200, TimeUnit.MILLISECONDS); + notifierFuture = executorService.scheduleAtFixedRate(this::checkCompletion, 10, 10, TimeUnit.SECONDS); } @Override @@ -152,6 +154,7 @@ public class TimeTrackingPlugin extends Plugin panelUpdateFuture = null; } + notifierFuture.cancel(true); clientToolbar.removeNavigation(navButton); infoBoxManager.removeInfoBox(farmingContractManager.getInfoBox()); farmingContractManager.setInfoBox(null); @@ -173,6 +176,10 @@ public class TimeTrackingPlugin extends Plugin { clockManager.loadStopwatches(); } + else if (e.getKey().equals(PREFER_SOONEST)) + { + farmingTracker.loadCompletionTimes(); + } } @Subscribe @@ -255,8 +262,7 @@ public class TimeTrackingPlugin extends Plugin } } - @Schedule(period = 10, unit = ChronoUnit.SECONDS) - public void checkCompletion() + private void checkCompletion() { boolean birdHouseDataChanged = birdHouseTracker.checkCompletion(); @@ -264,6 +270,8 @@ public class TimeTrackingPlugin extends Plugin { panel.update(); } + + farmingTracker.checkCompletion(); } private void updatePanel() diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeablePanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeablePanel.java index e7584a6e27..9796146500 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeablePanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeablePanel.java @@ -29,22 +29,29 @@ import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.GridLayout; +import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JPanel; +import javax.swing.JToggleButton; import javax.swing.border.EmptyBorder; import lombok.Getter; +import lombok.extern.slf4j.Slf4j; import net.runelite.api.Constants; import net.runelite.client.ui.ColorScheme; import net.runelite.client.ui.FontManager; import net.runelite.client.ui.components.ThinProgressBar; import net.runelite.client.ui.components.shadowlabel.JShadowedLabel; +import net.runelite.client.util.ImageUtil; +import net.runelite.client.util.SwingUtil; +@Slf4j @Getter public class TimeablePanel extends JPanel { private final T timeable; private final JLabel icon = new JLabel(); private final JLabel farmingContractIcon = new JLabel(); + private final JToggleButton notifyButton = new JToggleButton(); private final JLabel estimate = new JLabel(); private final ThinProgressBar progress = new ThinProgressBar(); private final JLabel text; @@ -79,8 +86,29 @@ public class TimeablePanel extends JPanel infoPanel.add(text); infoPanel.add(estimate); + ImageIcon notifyIcon = new ImageIcon(ImageUtil.loadImageResource(TimeTrackingPlugin.class, "notify_icon.png")); + ImageIcon notifySelectedIcon = new ImageIcon(ImageUtil.loadImageResource(TimeTrackingPlugin.class, "notify_selected_icon.png")); + + notifyButton.setPreferredSize(new Dimension(30, 16)); + notifyButton.setBorder(new EmptyBorder(0, 0, 0, 10)); + notifyButton.setIcon(notifyIcon); + notifyButton.setSelectedIcon(notifySelectedIcon); + SwingUtil.removeButtonDecorations(notifyButton); + SwingUtil.addModalTooltip(notifyButton, "Disable notifications", "Enable notifications"); + + JPanel notifyPanel = new JPanel(); + notifyPanel.setLayout(new BorderLayout()); + notifyPanel.setBackground(ColorScheme.DARKER_GRAY_COLOR); + notifyPanel.add(notifyButton, BorderLayout.CENTER); + + JPanel iconPanel = new JPanel(); + iconPanel.setLayout(new BorderLayout()); + iconPanel.setBackground(ColorScheme.DARKER_GRAY_COLOR); + iconPanel.add(notifyPanel, BorderLayout.EAST); + iconPanel.add(farmingContractIcon, BorderLayout.WEST); + + topContainer.add(iconPanel, BorderLayout.EAST); topContainer.add(icon, BorderLayout.WEST); - topContainer.add(farmingContractIcon, BorderLayout.EAST); topContainer.add(infoPanel, BorderLayout.CENTER); progress.setValue(0); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/clocks/ClockManager.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/clocks/ClockManager.java index 720c5633e9..30d16ff573 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/clocks/ClockManager.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/clocks/ClockManager.java @@ -53,6 +53,9 @@ public class ClockManager @Inject private Notifier notifier; + @Inject + private Gson gson; + @Getter private final List timers = new CopyOnWriteArrayList<>(); @@ -183,7 +186,6 @@ public class ClockManager if (!Strings.isNullOrEmpty(timersJson)) { - final Gson gson = new Gson(); final List timers = gson.fromJson(timersJson, new TypeToken>() { }.getType()); @@ -200,7 +202,6 @@ public class ClockManager if (!Strings.isNullOrEmpty(stopwatchesJson)) { - final Gson gson = new Gson(); final List stopwatches = gson.fromJson(stopwatchesJson, new TypeToken>() { }.getType()); @@ -227,14 +228,12 @@ public class ClockManager void saveTimers() { - final Gson gson = new Gson(); final String json = gson.toJson(timers); configManager.setConfiguration(TimeTrackingConfig.CONFIG_GROUP, TimeTrackingConfig.TIMERS, json); } void saveStopwatches() { - final Gson gson = new Gson(); final String json = gson.toJson(stopwatches); configManager.setConfiguration(TimeTrackingConfig.CONFIG_GROUP, TimeTrackingConfig.STOPWATCHES, json); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingPatch.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingPatch.java index 8c24588917..25b29ba01f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingPatch.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingPatch.java @@ -29,6 +29,7 @@ import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.Setter; import net.runelite.api.Varbits; +import net.runelite.client.plugins.timetracking.TimeTrackingConfig; @RequiredArgsConstructor( access = AccessLevel.PACKAGE @@ -41,4 +42,14 @@ class FarmingPatch private final String name; private final Varbits varbit; private final PatchImplementation implementation; -} + + String configKey() + { + return region.getRegionID() + "." + varbit.getId(); + } + + String notifyConfigKey() + { + return TimeTrackingConfig.NOTIFY + "." + region.getRegionID() + "." + varbit.getId(); + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingRegion.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingRegion.java index a759d2c31b..bb149af373 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingRegion.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingRegion.java @@ -33,13 +33,15 @@ public class FarmingRegion { private final String name; private final int regionID; + private final boolean definite; private final FarmingPatch[] patches; private final Varbits[] varbits; - FarmingRegion(String name, int regionID, FarmingPatch... patches) + FarmingRegion(String name, int regionID, boolean definite, FarmingPatch... patches) { this.name = name; this.regionID = regionID; + this.definite = definite; this.patches = patches; this.varbits = new Varbits[patches.length]; for (int i = 0; i < patches.length; i++) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingTabPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingTabPanel.java index 1c068790c8..18d525c1e0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingTabPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingTabPanel.java @@ -33,8 +33,11 @@ import java.util.ArrayList; import java.util.List; import java.util.Set; import javax.swing.JLabel; +import javax.swing.JToggleButton; import javax.swing.border.EmptyBorder; +import lombok.extern.slf4j.Slf4j; import net.runelite.api.ItemID; +import net.runelite.client.config.ConfigManager; import net.runelite.client.game.ItemManager; import net.runelite.client.plugins.timetracking.TabContentPanel; import net.runelite.client.plugins.timetracking.TimeTrackingConfig; @@ -42,10 +45,12 @@ import net.runelite.client.plugins.timetracking.TimeablePanel; import net.runelite.client.ui.ColorScheme; import net.runelite.client.ui.FontManager; +@Slf4j public class FarmingTabPanel extends TabContentPanel { private final FarmingTracker farmingTracker; private final ItemManager itemManager; + private final ConfigManager configManager; private final TimeTrackingConfig config; private final List> patchPanels; private final FarmingContractManager farmingContractManager; @@ -53,6 +58,7 @@ public class FarmingTabPanel extends TabContentPanel FarmingTabPanel( FarmingTracker farmingTracker, ItemManager itemManager, + ConfigManager configManager, TimeTrackingConfig config, Set patches, FarmingContractManager farmingContractManager @@ -60,6 +66,7 @@ public class FarmingTabPanel extends TabContentPanel { this.farmingTracker = farmingTracker; this.itemManager = itemManager; + this.configManager = configManager; this.config = config; this.patchPanels = new ArrayList<>(); this.farmingContractManager = farmingContractManager; @@ -103,6 +110,18 @@ public class FarmingTabPanel extends TabContentPanel lastImpl = patch.getImplementation(); } + // Set toggle state of notification menu on icon click; + JToggleButton toggleNotify = p.getNotifyButton(); + String configKey = patch.notifyConfigKey(); + + toggleNotify.addActionListener(e -> + { + if (configManager.getRSProfileKey() != null) + { + configManager.setRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, configKey, toggleNotify.isSelected()); + } + }); + patchPanels.add(p); add(p, c); c.gridy++; @@ -197,18 +216,26 @@ public class FarmingTabPanel extends TabContentPanel { panel.getProgress().setVisible(false); } - JLabel farmingContractIcon = panel.getFarmingContractIcon(); - if (farmingContractManager.shouldHighlightFarmingTabPanel(patch)) - { - itemManager.getImage(ItemID.SEED_PACK).addTo(farmingContractIcon); - farmingContractIcon.setToolTipText(farmingContractManager.getContract().getName()); - } - else - { - farmingContractIcon.setIcon(null); - farmingContractIcon.setToolTipText(""); - } } + + JLabel farmingContractIcon = panel.getFarmingContractIcon(); + if (farmingContractManager.shouldHighlightFarmingTabPanel(patch)) + { + itemManager.getImage(ItemID.SEED_PACK).addTo(farmingContractIcon); + farmingContractIcon.setToolTipText(farmingContractManager.getContract().getName()); + } + else + { + farmingContractIcon.setIcon(null); + farmingContractIcon.setToolTipText(""); + } + + String configKey = patch.notifyConfigKey(); + JToggleButton toggleNotify = panel.getNotifyButton(); + boolean notifyEnabled = Boolean.TRUE + .equals(configManager.getRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, configKey, Boolean.class)); + + toggleNotify.setSelected(notifyEnabled); } } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingTracker.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingTracker.java index 409ee85e1d..4a381220b2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingTracker.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingTracker.java @@ -24,25 +24,34 @@ */ package net.runelite.client.plugins.timetracking.farming; +import com.google.common.annotations.VisibleForTesting; import com.google.inject.Inject; import com.google.inject.Singleton; import java.time.Instant; import java.util.Collection; import java.util.EnumMap; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Set; import javax.annotation.Nullable; import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; +import net.runelite.api.GameState; import net.runelite.api.Varbits; import net.runelite.api.coords.WorldPoint; import net.runelite.api.vars.Autoweed; import net.runelite.api.widgets.WidgetModalMode; +import net.runelite.client.Notifier; import net.runelite.client.config.ConfigManager; +import net.runelite.client.config.RuneScapeProfile; +import net.runelite.client.config.RuneScapeProfileType; import net.runelite.client.game.ItemManager; import net.runelite.client.plugins.timetracking.SummaryState; import net.runelite.client.plugins.timetracking.Tab; import net.runelite.client.plugins.timetracking.TimeTrackingConfig; +import net.runelite.client.util.Text; @Slf4j @Singleton @@ -53,6 +62,7 @@ public class FarmingTracker private final ConfigManager configManager; private final TimeTrackingConfig config; private final FarmingWorld farmingWorld; + private final Notifier notifier; private final Map summaries = new EnumMap<>(Tab.class); @@ -61,23 +71,26 @@ public class FarmingTracker * or {@code -1} if we have no data about any patch of the given type. */ private final Map completionTimes = new EnumMap<>(Tab.class); + Map wasNotified = new HashMap<>(); private boolean newRegionLoaded; private Collection lastRegions; + private boolean firstNotifyCheck = true; @Inject - private FarmingTracker(Client client, ItemManager itemManager, ConfigManager configManager, TimeTrackingConfig config, FarmingWorld farmingWorld) + private FarmingTracker(Client client, ItemManager itemManager, ConfigManager configManager, TimeTrackingConfig config, FarmingWorld farmingWorld, Notifier notifier) { this.client = client; this.itemManager = itemManager; this.configManager = configManager; this.config = config; this.farmingWorld = farmingWorld; + this.notifier = notifier; } public FarmingTabPanel createTabPanel(Tab tab, FarmingContractManager farmingContractManager) { - return new FarmingTabPanel(this, itemManager, config, farmingWorld.getTabs().get(tab), farmingContractManager); + return new FarmingTabPanel(this, itemManager, configManager, config, farmingWorld.getTabs().get(tab), farmingContractManager); } /** @@ -130,7 +143,7 @@ public class FarmingTracker { // Write the config value if it doesn't match what is current, or it is more than 5 minutes old Varbits varbit = patch.getVarbit(); - String key = region.getRegionID() + "." + varbit.getId(); + String key = patch.configKey(); String strVarbit = Integer.toString(client.getVar(varbit)); String storedValue = configManager.getRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, key); @@ -189,6 +202,12 @@ public class FarmingTracker configManager.setRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, TimeTrackingConfig.FARM_TICK_OFFSET, offsetMins); } } + if (currentPatchState.getTickRate() != 0 + // Don't set wasNotified to false if witnessing a check-health action + && !(previousPatchState.getCropState() == CropState.GROWING && currentPatchState.getCropState() == CropState.HARVESTABLE && currentPatchState.getProduce().getPatchImplementation().isHealthCheckRequired())) + { + wasNotified.put(new ProfilePatch(patch, configManager.getRSProfileKey()), false); + } } else { @@ -258,17 +277,23 @@ public class FarmingTracker @Nullable public PatchPrediction predictPatch(FarmingPatch patch) + { + return predictPatch(patch, configManager.getRSProfileKey()); + } + + @Nullable + public PatchPrediction predictPatch(FarmingPatch patch, String profile) { long unixNow = Instant.now().getEpochSecond(); boolean autoweed = Integer.toString(Autoweed.ON.ordinal()) - .equals(configManager.getRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, TimeTrackingConfig.AUTOWEED)); + .equals(configManager.getConfiguration(TimeTrackingConfig.CONFIG_GROUP, profile, TimeTrackingConfig.AUTOWEED)); boolean botanist = Boolean.TRUE - .equals(configManager.getRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, TimeTrackingConfig.BOTANIST, Boolean.class)); + .equals(configManager.getConfiguration(TimeTrackingConfig.CONFIG_GROUP, profile, TimeTrackingConfig.BOTANIST, Boolean.class)); - String key = patch.getRegion().getRegionID() + "." + patch.getVarbit().getId(); - String storedValue = configManager.getRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, key); + String key = patch.configKey(); + String storedValue = configManager.getConfiguration(TimeTrackingConfig.CONFIG_GROUP, profile, key); if (storedValue == null) { @@ -323,11 +348,11 @@ public class FarmingTracker long doneEstimate = 0; if (tickrate > 0) { - long tickNow = getTickTime(tickrate, 0, unixNow); - long tickTime = getTickTime(tickrate, 0, unixTime); + long tickNow = getTickTime(tickrate, 0, unixNow, profile); + long tickTime = getTickTime(tickrate, 0, unixTime, profile); int delta = (int) (tickNow - tickTime) / (tickrate * 60); - doneEstimate = getTickTime(tickrate, stages - 1 - stage, tickTime); + doneEstimate = getTickTime(tickrate, stages - 1 - stage, tickTime, profile); stage += delta; if (stage >= stages) @@ -347,13 +372,13 @@ public class FarmingTracker public long getTickTime(int tickRate, int ticks) { - return getTickTime(tickRate, ticks, Instant.now().getEpochSecond()); + return getTickTime(tickRate, ticks, Instant.now().getEpochSecond(), configManager.getRSProfileKey()); } - public long getTickTime(int tickRate, int ticks, long requestedTime) + public long getTickTime(int tickRate, int ticks, long requestedTime, String profile) { - Integer offsetPrecisionMins = configManager.getRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, TimeTrackingConfig.FARM_TICK_OFFSET_PRECISION, int.class); - Integer offsetTimeMins = configManager.getRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, TimeTrackingConfig.FARM_TICK_OFFSET, int.class); + Integer offsetPrecisionMins = configManager.getConfiguration(TimeTrackingConfig.CONFIG_GROUP, profile, TimeTrackingConfig.FARM_TICK_OFFSET_PRECISION, int.class); + Integer offsetTimeMins = configManager.getConfiguration(TimeTrackingConfig.CONFIG_GROUP, profile, TimeTrackingConfig.FARM_TICK_OFFSET, int.class); //All offsets are negative but are stored as positive long calculatedOffsetTime = 0L; @@ -407,7 +432,7 @@ public class FarmingTracker { for (Map.Entry> tab : farmingWorld.getTabs().entrySet()) { - long maxCompletionTime = 0; + long extremumCompletionTime = config.preferSoonest() ? Long.MAX_VALUE : 0; boolean allUnknown = true; boolean allEmpty = true; @@ -426,7 +451,15 @@ public class FarmingTracker allEmpty = false; // update max duration if this patch takes longer to grow - maxCompletionTime = Math.max(maxCompletionTime, prediction.getDoneEstimate()); + if (config.preferSoonest()) + { + extremumCompletionTime = Math.min(extremumCompletionTime, prediction.getDoneEstimate()); + } + else + { + extremumCompletionTime = Math.max(extremumCompletionTime, prediction.getDoneEstimate()); + } + } } @@ -443,7 +476,7 @@ public class FarmingTracker state = SummaryState.EMPTY; completionTime = -1L; } - else if (maxCompletionTime <= Instant.now().getEpochSecond()) + else if (extremumCompletionTime <= Instant.now().getEpochSecond()) { state = SummaryState.COMPLETED; completionTime = 0; @@ -451,10 +484,139 @@ public class FarmingTracker else { state = SummaryState.IN_PROGRESS; - completionTime = maxCompletionTime; + completionTime = extremumCompletionTime; } summaries.put(tab.getKey(), state); completionTimes.put(tab.getKey(), completionTime); } } + + public void checkCompletion() + { + List rsProfiles = configManager.getRSProfiles(); + long unixNow = Instant.now().getEpochSecond(); + + for (RuneScapeProfile profile : rsProfiles) + { + Integer offsetPrecisionMins = configManager.getConfiguration(TimeTrackingConfig.CONFIG_GROUP, profile.getKey(), TimeTrackingConfig.FARM_TICK_OFFSET_PRECISION, int.class); + Integer offsetTimeMins = configManager.getConfiguration(TimeTrackingConfig.CONFIG_GROUP, profile.getKey(), TimeTrackingConfig.FARM_TICK_OFFSET, int.class); + + for (Map.Entry> tab : farmingWorld.getTabs().entrySet()) + { + for (FarmingPatch patch : tab.getValue()) + { + ProfilePatch profilePatch = new ProfilePatch(patch, profile.getKey()); + boolean patchNotified = wasNotified.getOrDefault(profilePatch, false); + String configKey = patch.notifyConfigKey(); + boolean shouldNotify = Boolean.TRUE + .equals(configManager.getConfiguration(TimeTrackingConfig.CONFIG_GROUP, profile.getKey(), configKey, Boolean.class)); + PatchPrediction prediction = predictPatch(patch, profile.getKey()); + + if (prediction == null) + { + continue; + } + + int tickRate = prediction.getProduce().getTickrate(); + + if (offsetPrecisionMins == null || offsetTimeMins == null || (offsetPrecisionMins < tickRate && offsetPrecisionMins < 40) || prediction.getProduce() == Produce.WEEDS + || unixNow <= prediction.getDoneEstimate() || patchNotified || prediction.getCropState() == CropState.FILLING || prediction.getCropState() == CropState.EMPTY) + { + continue; + } + + wasNotified.put(profilePatch, true); + + if (!firstNotifyCheck && shouldNotify) + { + sendNotification(profile, prediction, patch); + } + } + } + } + firstNotifyCheck = false; + } + + @VisibleForTesting + void sendNotification(RuneScapeProfile profile, PatchPrediction prediction, FarmingPatch patch) + { + final RuneScapeProfileType profileType = profile.getType(); + + final StringBuilder stringBuilder = new StringBuilder(); + // Same RS account + if (client.getGameState() == GameState.LOGGED_IN && profile.getDisplayName().equals(client.getLocalPlayer().getName())) + { + // Same RS account but different profile type + if (profileType != RuneScapeProfileType.getCurrent(client)) + { + stringBuilder.append("(") + .append(Text.titleCase(profile.getType())) + .append(") "); + } + // Same RS account AND profile falls through here so no bracketed prefix is added + } + else + { + // Different RS account AND profile type + if (profileType != RuneScapeProfileType.getCurrent(client) || client.getGameState() == GameState.LOGIN_SCREEN) + { + //Don't print profile type when logged out if is STANDARD + if (client.getGameState() == GameState.LOGIN_SCREEN && profileType == RuneScapeProfileType.STANDARD) + { + stringBuilder.append("(") + .append(profile.getDisplayName()) + .append(") "); + } + else + { + stringBuilder.append("(") + .append(profile.getDisplayName()) + .append(" - ") + .append(Text.titleCase(profile.getType())) + .append(") "); + } + } + // Different RS account but same profile type + else + { + stringBuilder.append("(") + .append(profile.getDisplayName()) + .append(") "); + } + } + + stringBuilder + .append("Your ") + .append(prediction.getProduce().getName()); + + switch (prediction.getCropState()) + { + case HARVESTABLE: + case GROWING: + if (prediction.getProduce().getName().toLowerCase(Locale.ENGLISH).contains("compost")) + { + stringBuilder.append(" is ready to collect in "); + } + else + { + stringBuilder.append(" is ready to harvest in "); + } + break; + case DISEASED: + stringBuilder.append(" has become diseased in "); + break; + case DEAD: + stringBuilder.append(" has died in "); + break; + default: + // EMPTY and FILLING are caught above + throw new IllegalStateException(); + } + + stringBuilder.append(patch.getRegion().isDefinite() ? "the " : "") + .append(patch.getRegion().getName()) + .append("."); + + notifier.notify(stringBuilder.toString()); + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingWorld.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingWorld.java index 7ca46e130c..5429240775 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingWorld.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingWorld.java @@ -64,14 +64,14 @@ class FarmingWorld { // Some of these patches get updated in multiple regions. // It may be worth it to add a specialization for these patches - add(new FarmingRegion("Al Kharid", 13106, + add(new FarmingRegion("Al Kharid", 13106, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.CACTUS) ), 13362, 13105); - add(new FarmingRegion("Ardougne", 10290, + add(new FarmingRegion("Ardougne", 10290, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.BUSH) ), 10546); - add(new FarmingRegion("Ardougne", 10548, + add(new FarmingRegion("Ardougne", 10548, false, new FarmingPatch("North", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT), new FarmingPatch("South", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT), new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER), @@ -79,12 +79,12 @@ class FarmingWorld new FarmingPatch("", Varbits.FARMING_4775, PatchImplementation.COMPOST) )); - add(new FarmingRegion("Brimhaven", 11058, + add(new FarmingRegion("Brimhaven", 11058, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.FRUIT_TREE), new FarmingPatch("", Varbits.FARMING_4772, PatchImplementation.SPIRIT_TREE) ), 11057); - add(new FarmingRegion("Catherby", 11062, + add(new FarmingRegion("Catherby", 11062, false, new FarmingPatch("North", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT), new FarmingPatch("South", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT), new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER), @@ -103,7 +103,7 @@ class FarmingWorld return true; } }, 11061, 11318, 11317); - add(new FarmingRegion("Catherby", 11317, + add(new FarmingRegion("Catherby", 11317, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.FRUIT_TREE) ) { @@ -115,27 +115,27 @@ class FarmingWorld } }); - add(new FarmingRegion("Champions' Guild", 12596, + add(new FarmingRegion("Champions' Guild", 12596, true, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.BUSH) )); - add(new FarmingRegion("Draynor Manor", 12340, + add(new FarmingRegion("Draynor Manor", 12340, false, new FarmingPatch("Belladonna", Varbits.FARMING_4771, PatchImplementation.BELLADONNA) )); - add(new FarmingRegion("Entrana", 11060, + add(new FarmingRegion("Entrana", 11060, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.HOPS) ), 11316); - add(new FarmingRegion("Etceteria", 10300, + add(new FarmingRegion("Etceteria", 10300, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.BUSH), new FarmingPatch("", Varbits.FARMING_4772, PatchImplementation.SPIRIT_TREE) )); - add(new FarmingRegion("Falador", 11828, + add(new FarmingRegion("Falador", 11828, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.TREE) ), 12084); - add(new FarmingRegion("Falador", 12083, + add(new FarmingRegion("Falador", 12083, false, new FarmingPatch("North West", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT), new FarmingPatch("South East", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT), new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER), @@ -151,7 +151,7 @@ class FarmingWorld } }); - add(new FarmingRegion("Fossil Island", 14651, + add(new FarmingRegion("Fossil Island", 14651, false, new FarmingPatch("East", Varbits.FARMING_4771, PatchImplementation.HARDWOOD_TREE), new FarmingPatch("Middle", Varbits.FARMING_4772, PatchImplementation.HARDWOOD_TREE), new FarmingPatch("West", Varbits.FARMING_4773, PatchImplementation.HARDWOOD_TREE) @@ -179,22 +179,22 @@ class FarmingWorld return loc.getPlane() == 0; } }, 14907, 14908, 15164, 14652, 14906, 14650, 15162, 15163); - add(new FarmingRegion("Seaweed", 15008, + add(new FarmingRegion("Seaweed", 15008, false, new FarmingPatch("North", Varbits.FARMING_4771, PatchImplementation.SEAWEED), new FarmingPatch("South", Varbits.FARMING_4772, PatchImplementation.SEAWEED) )); - add(new FarmingRegion("Gnome Stronghold", 9781, + add(new FarmingRegion("Gnome Stronghold", 9781, true, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.TREE), new FarmingPatch("", Varbits.FARMING_4772, PatchImplementation.FRUIT_TREE) ), 9782, 9526, 9525); - add(new FarmingRegion("Harmony", 15148, + add(new FarmingRegion("Harmony", 15148, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT), new FarmingPatch("", Varbits.FARMING_4772, PatchImplementation.HERB) )); - add(new FarmingRegion("Kourend", 6967, + add(new FarmingRegion("Kourend", 6967, false, new FarmingPatch("North East", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT), new FarmingPatch("South West", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT), new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER), @@ -202,7 +202,7 @@ class FarmingWorld new FarmingPatch("", Varbits.FARMING_4775, PatchImplementation.COMPOST), new FarmingPatch("", Varbits.FARMING_7904, PatchImplementation.SPIRIT_TREE) ), 6711); - add(new FarmingRegion("Kourend", 7223, + add(new FarmingRegion("Kourend", 7223, false, new FarmingPatch("East 1", Varbits.GRAPES_4953, PatchImplementation.GRAPES), new FarmingPatch("East 2", Varbits.GRAPES_4954, PatchImplementation.GRAPES), new FarmingPatch("East 3", Varbits.GRAPES_4955, PatchImplementation.GRAPES), @@ -217,21 +217,21 @@ class FarmingWorld new FarmingPatch("West 6", Varbits.GRAPES_4964, PatchImplementation.GRAPES) )); - add(new FarmingRegion("Lletya", 9265, + add(new FarmingRegion("Lletya", 9265, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.FRUIT_TREE) ), 11103); - add(new FarmingRegion("Lumbridge", 12851, + add(new FarmingRegion("Lumbridge", 12851, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.HOPS) )); - add(new FarmingRegion("Lumbridge", 12594, + add(new FarmingRegion("Lumbridge", 12594, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.TREE) ), 12850); - add(new FarmingRegion("Morytania", 13622, + add(new FarmingRegion("Morytania", 13622, false, new FarmingPatch("Mushroom", Varbits.FARMING_4771, PatchImplementation.MUSHROOM) ), 13878); - add(new FarmingRegion("Morytania", 14391, + add(new FarmingRegion("Morytania", 14391, false, new FarmingPatch("North West", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT), new FarmingPatch("South East", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT), new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER), @@ -239,7 +239,7 @@ class FarmingWorld new FarmingPatch("", Varbits.FARMING_4775, PatchImplementation.COMPOST) ), 14390); - add(new FarmingRegion("Port Sarim", 12082, + add(new FarmingRegion("Port Sarim", 12082, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.SPIRIT_TREE) ) { @@ -250,48 +250,48 @@ class FarmingWorld } }, 12083); - add(new FarmingRegion("Rimmington", 11570, + add(new FarmingRegion("Rimmington", 11570, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.BUSH) ), 11826); - add(new FarmingRegion("Seers' Village", 10551, + add(new FarmingRegion("Seers' Village", 10551, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.HOPS) ), 10550); - add(new FarmingRegion("Tai Bwo Wannai", 11056, + add(new FarmingRegion("Tai Bwo Wannai", 11056, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.CALQUAT) )); - add(new FarmingRegion("Taverley", 11573, + add(new FarmingRegion("Taverley", 11573, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.TREE) ), 11829); - add(new FarmingRegion("Tree Gnome Village", 9777, + add(new FarmingRegion("Tree Gnome Village", 9777, true, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.FRUIT_TREE) ), 10033); - add(new FarmingRegion("Troll Stronghold", 11321, + add(new FarmingRegion("Troll Stronghold", 11321, true, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.HERB) )); - add(new FarmingRegion("Varrock", 12854, + add(new FarmingRegion("Varrock", 12854, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.TREE) ), 12853); - add(new FarmingRegion("Yanille", 10288, + add(new FarmingRegion("Yanille", 10288, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.HOPS) )); - add(new FarmingRegion("Weiss", 11325, + add(new FarmingRegion("Weiss", 11325, false, new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.HERB) )); - add(new FarmingRegion("Farming Guild", 5021, + add(new FarmingRegion("Farming Guild", 5021, true, new FarmingPatch("Hespori", Varbits.FARMING_7908, PatchImplementation.HESPORI) )); //Full 3x3 region area centered on farming guild - add(farmingGuildRegion = new FarmingRegion("Farming Guild", 4922, + add(farmingGuildRegion = new FarmingRegion("Farming Guild", 4922, true, new FarmingPatch("", Varbits.FARMING_7905, PatchImplementation.TREE), new FarmingPatch("", Varbits.FARMING_4775, PatchImplementation.HERB), new FarmingPatch("", Varbits.FARMING_4772, PatchImplementation.BUSH), @@ -308,7 +308,7 @@ class FarmingWorld ), 5177, 5178, 5179, 4921, 4923, 4665, 4666, 4667); //All of Prifddinas, and all of Prifddinas Underground - add(new FarmingRegion("Prifddinas", 13151, + add(new FarmingRegion("Prifddinas", 13151, false, new FarmingPatch("North", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT), new FarmingPatch("South", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT), new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/Produce.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/Produce.java index 033b358ad6..bfb5a1abe3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/Produce.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/Produce.java @@ -43,9 +43,9 @@ public enum Produce ONION("Onion", "Onions", PatchImplementation.ALLOTMENT, ItemID.ONION, 10, 5, 0, 3), CABBAGE("Cabbage", "Cabbages", PatchImplementation.ALLOTMENT, ItemID.CABBAGE, 10, 5, 0, 3), TOMATO("Tomato", "Tomatoes", PatchImplementation.ALLOTMENT, ItemID.TOMATO, 10, 5, 0, 3), - SWEETCORN("Sweetcorn", PatchImplementation.ALLOTMENT, ItemID.SWEETCORN, 10, 6, 0, 3), + SWEETCORN("Sweetcorn", PatchImplementation.ALLOTMENT, ItemID.SWEETCORN, 10, 7, 0, 3), STRAWBERRY("Strawberry", "Strawberries", PatchImplementation.ALLOTMENT, ItemID.STRAWBERRY, 10, 7, 0, 3), - WATERMELON("Watermelon", "Watermelons", PatchImplementation.ALLOTMENT, ItemID.WATERMELON, 10, 8, 0, 3), + WATERMELON("Watermelon", "Watermelons", PatchImplementation.ALLOTMENT, ItemID.WATERMELON, 10, 9, 0, 3), SNAPE_GRASS("Snape grass", PatchImplementation.ALLOTMENT, ItemID.SNAPE_GRASS, 10, 8, 0, 3), // Flower crops diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/ProfilePatch.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/ProfilePatch.java new file mode 100644 index 0000000000..d928c1f8e0 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/ProfilePatch.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021 Hannah Ryan + * 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.timetracking.farming; + +import lombok.Value; + +@Value +class ProfilePatch +{ + FarmingPatch patch; + String rsProfileKey; +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiSearchChatboxTextInput.java b/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiSearchChatboxTextInput.java index 8552d90eef..622e4db98b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiSearchChatboxTextInput.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiSearchChatboxTextInput.java @@ -67,7 +67,6 @@ public class WikiSearchChatboxTextInput extends ChatboxTextInput private static final int PREDICTION_DEBOUNCE_DELAY_MS = 200; private final ChatboxPanelManager chatboxPanelManager; - private final Gson gson = new Gson(); private Future runningRequest = null; private List predictions = ImmutableList.of(); @@ -78,7 +77,7 @@ public class WikiSearchChatboxTextInput extends ChatboxTextInput @Inject public WikiSearchChatboxTextInput(ChatboxPanelManager chatboxPanelManager, ClientThread clientThread, ScheduledExecutorService scheduledExecutorService, @Named("developerMode") final boolean developerMode, - OkHttpClient okHttpClient) + OkHttpClient okHttpClient, Gson gson) { super(chatboxPanelManager, clientThread); this.chatboxPanelManager = chatboxPanelManager; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/wintertodt/WintertodtConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/wintertodt/WintertodtConfig.java index 407d9018aa..a466568b82 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/wintertodt/WintertodtConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/wintertodt/WintertodtConfig.java @@ -51,7 +51,7 @@ public interface WintertodtConfig extends Config @ConfigItem( position = 1, keyName = "damageNotificationColor", - name = "Damage Notification Color", + name = "Damage Notification", description = "Color of damage notification text in chat" ) default Color damageNotificationColor() @@ -62,7 +62,7 @@ public interface WintertodtConfig extends Config @ConfigItem( position = 2, keyName = "roundNotification", - name = "Wintertodt round notification", + name = "Round notification", description = "Notifies you before the round starts (in seconds)" ) @Range( diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/wintertodt/WintertodtPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/wintertodt/WintertodtPlugin.java index 611dbeba22..343b55f458 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/wintertodt/WintertodtPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/wintertodt/WintertodtPlugin.java @@ -44,6 +44,7 @@ import static net.runelite.api.AnimationID.WOODCUTTING_BLACK; import static net.runelite.api.AnimationID.WOODCUTTING_BRONZE; import static net.runelite.api.AnimationID.WOODCUTTING_CRYSTAL; import static net.runelite.api.AnimationID.WOODCUTTING_DRAGON; +import static net.runelite.api.AnimationID.WOODCUTTING_DRAGON_OR; import static net.runelite.api.AnimationID.WOODCUTTING_GILDED; import static net.runelite.api.AnimationID.WOODCUTTING_INFERNAL; import static net.runelite.api.AnimationID.WOODCUTTING_IRON; @@ -414,6 +415,7 @@ public class WintertodtPlugin extends Plugin case WOODCUTTING_RUNE: case WOODCUTTING_GILDED: case WOODCUTTING_DRAGON: + case WOODCUTTING_DRAGON_OR: case WOODCUTTING_INFERNAL: case WOODCUTTING_3A_AXE: case WOODCUTTING_CRYSTAL: diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/Axe.java b/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/Axe.java index 90797e265d..5f48169633 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/Axe.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/Axe.java @@ -34,6 +34,7 @@ import static net.runelite.api.AnimationID.WOODCUTTING_BLACK; import static net.runelite.api.AnimationID.WOODCUTTING_BRONZE; import static net.runelite.api.AnimationID.WOODCUTTING_CRYSTAL; import static net.runelite.api.AnimationID.WOODCUTTING_DRAGON; +import static net.runelite.api.AnimationID.WOODCUTTING_DRAGON_OR; import static net.runelite.api.AnimationID.WOODCUTTING_GILDED; import static net.runelite.api.AnimationID.WOODCUTTING_INFERNAL; import static net.runelite.api.AnimationID.WOODCUTTING_IRON; @@ -46,6 +47,7 @@ import static net.runelite.api.ItemID.BLACK_AXE; import static net.runelite.api.ItemID.BRONZE_AXE; import static net.runelite.api.ItemID.CRYSTAL_AXE; import static net.runelite.api.ItemID.DRAGON_AXE; +import static net.runelite.api.ItemID.DRAGON_AXE_OR; import static net.runelite.api.ItemID.GILDED_AXE; import static net.runelite.api.ItemID.INFERNAL_AXE; import static net.runelite.api.ItemID.IRON_AXE; @@ -69,6 +71,7 @@ enum Axe RUNE(WOODCUTTING_RUNE, RUNE_AXE), GILDED(WOODCUTTING_GILDED, GILDED_AXE), DRAGON(WOODCUTTING_DRAGON, DRAGON_AXE), + DRAGON_OR(WOODCUTTING_DRAGON_OR, DRAGON_AXE_OR), INFERNAL(WOODCUTTING_INFERNAL, INFERNAL_AXE), THIRDAGE(WOODCUTTING_3A_AXE, _3RD_AGE_AXE), CRYSTAL(WOODCUTTING_CRYSTAL, CRYSTAL_AXE), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java index b10e2a0667..f0d4f88185 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java @@ -47,10 +47,10 @@ import lombok.Getter; import lombok.extern.slf4j.Slf4j; import net.runelite.api.ChatMessageType; import net.runelite.api.ChatPlayer; -import net.runelite.api.FriendsChatMember; -import net.runelite.api.FriendsChatManager; import net.runelite.api.Client; import net.runelite.api.Friend; +import net.runelite.api.FriendsChatManager; +import net.runelite.api.FriendsChatMember; import net.runelite.api.GameState; import net.runelite.api.MenuAction; import net.runelite.api.MenuEntry; @@ -60,10 +60,11 @@ import net.runelite.api.events.ChatMessage; import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GameTick; import net.runelite.api.events.MenuEntryAdded; -import net.runelite.api.events.PlayerMenuOptionClicked; +import net.runelite.api.events.MenuOptionClicked; import net.runelite.api.events.VarbitChanged; import net.runelite.api.events.WorldListLoad; import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.callback.ClientThread; import net.runelite.client.chat.ChatColorType; import net.runelite.client.chat.ChatMessageBuilder; import net.runelite.client.chat.ChatMessageManager; @@ -111,6 +112,9 @@ public class WorldHopperPlugin extends Plugin @Inject private Client client; + @Inject + private ClientThread clientThread; + @Inject private ConfigManager configManager; @@ -162,7 +166,7 @@ public class WorldHopperPlugin extends Plugin @Override public void hotkeyPressed() { - hop(true); + clientThread.invoke(() -> hop(true)); } }; private final HotkeyListener nextKeyListener = new HotkeyListener(() -> config.nextKey()) @@ -170,7 +174,7 @@ public class WorldHopperPlugin extends Plugin @Override public void hotkeyPressed() { - hop(false); + clientThread.invoke(() -> hop(false)); } }; @@ -304,7 +308,7 @@ public class WorldHopperPlugin extends Plugin void hopTo(World world) { - hop(world.getId()); + clientThread.invoke(() -> hop(world.getId())); } void addToFavorites(World world) @@ -408,9 +412,9 @@ public class WorldHopperPlugin extends Plugin } @Subscribe - public void onPlayerMenuOptionClicked(PlayerMenuOptionClicked event) + public void onMenuOptionClicked(MenuOptionClicked event) { - if (!event.getMenuOption().equals(HOP_TO)) + if (event.getMenuAction() != MenuAction.RUNELITE || !event.getMenuOption().equals(HOP_TO)) { return; } @@ -613,6 +617,8 @@ public class WorldHopperPlugin extends Plugin private void hop(int worldId) { + assert client.isClientThread(); + WorldResult worldResult = worldService.getWorlds(); // Don't try to hop if the world doesn't exist World world = worldResult.findWorld(worldId); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldSwitcherPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldSwitcherPanel.java index 9948a856f5..12d0a724c3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldSwitcherPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldSwitcherPanel.java @@ -370,10 +370,7 @@ class WorldSwitcherPanel extends PluginPanel private WorldTableRow buildRow(World world, boolean stripe, boolean current, boolean favorite) { WorldTableRow row = new WorldTableRow(world, current, favorite, plugin.getStoredPing(world), - world1 -> - { - plugin.hopTo(world1); - }, + plugin::hopTo, (world12, add) -> { if (add) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/AgilityShortcutPoint.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/AgilityShortcutPoint.java deleted file mode 100644 index c99979f103..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/AgilityShortcutPoint.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2018, Morgan Lewis - * 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 HOLDER 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.worldmap; - -import java.awt.image.BufferedImage; -import net.runelite.client.ui.overlay.worldmap.WorldMapPoint; -import net.runelite.client.game.AgilityShortcut; - -class AgilityShortcutPoint extends WorldMapPoint -{ - AgilityShortcutPoint(AgilityShortcut data, BufferedImage icon, boolean showTooltip) - { - super(data.getWorldMapLocation(), icon); - - if (showTooltip) - { - setTooltip(data.getTooltip()); - } - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/DungeonLocation.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/DungeonLocation.java index 1f5ee3bb0e..544cefd6c8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/DungeonLocation.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/DungeonLocation.java @@ -55,9 +55,10 @@ enum DungeonLocation CORSAIR_COVE_E("Corsair Cove Dungeon", new WorldPoint(2522, 2861, 0)), CORSAIR_COVE_N("Corsair Cove Dungeon", new WorldPoint(2482, 2891, 0)), CRABCLAW_CAVES("Crabclaw Caves", new WorldPoint(1643, 3449, 0)), - CRABCLAW_CAVES_TUNNEL("Crabclaw Caves Tunnel (quest)", new WorldPoint(1643, 3449, 0)), + CRABCLAW_CAVES_TUNNEL("Crabclaw Caves Tunnel (quest)", new WorldPoint(1671, 9800, 0)), CRANDOR("Crandor Dungeon", new WorldPoint(2833, 3256, 0)), CRASH_ISLAND("Crash Island Dungeon", new WorldPoint(2920, 2721, 0)), + CRUMBLING_TOWER("Crumbling Tower basement", new WorldPoint(2130, 2994, 0)), DEEP_WILDERNESS("Deep Wilderness Dungeon", new WorldPoint(3044, 3924, 0)), DRAYNOR_MANOR_E("Draynor Manor basement", new WorldPoint(3114, 3357, 0)), DRAYNOR_MANOR_W("Draynor Manor basement", new WorldPoint(3091, 3362, 0)), @@ -89,6 +90,7 @@ enum DungeonLocation ICE_QUEEN_W("Ice Queen's Lair", new WorldPoint(2822, 3510, 0)), ICE_TROLL_E("Ice Troll Caves", new WorldPoint(2400, 3889, 0)), ICE_TROLL_W("Ice Troll Caves", new WorldPoint(2315, 3894, 0)), + ISLE_OF_SOULS_DUNGEON("Isle of Souls Dungeon", new WorldPoint(2308, 2919, 0)), IORWERTH("Iorwerth Dungeon", new WorldPoint(3224, 6044, 0)), IORWERTH_CAMP_CAVE("Iorwerth Camp cave", new WorldPoint(2200, 3262, 0)), IORWERTH_CAMP_CAVE_PRIF("Iorwerth Camp cave", new WorldPoint(3224, 6014, 0)), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/DungeonPoint.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/DungeonPoint.java deleted file mode 100644 index 9d50ec322f..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/DungeonPoint.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2020, Arman S - * 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 HOLDER 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.worldmap; - -import java.awt.image.BufferedImage; -import net.runelite.client.ui.overlay.worldmap.WorldMapPoint; - -class DungeonPoint extends WorldMapPoint -{ - DungeonPoint(DungeonLocation data, BufferedImage icon) - { - super(data.getLocation(), icon); - setTooltip(data.getTooltip()); - } -} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/FairyRingPoint.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/FairyRingPoint.java deleted file mode 100644 index ef4e55da92..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/FairyRingPoint.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2018, Morgan Lewis - * 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 HOLDER 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.worldmap; - -import java.awt.image.BufferedImage; -import net.runelite.client.ui.overlay.worldmap.WorldMapPoint; - -class FairyRingPoint extends WorldMapPoint -{ - FairyRingPoint(FairyRingLocation data, BufferedImage icon, boolean showTooltip) - { - super(data.getLocation(), icon); - - if (showTooltip) - { - setTooltip("Fairy Ring - " + data.getCode()); - } - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/FarmingPatchPoint.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/FarmingPatchPoint.java deleted file mode 100644 index 79b380c220..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/FarmingPatchPoint.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2018, Torkel Velure - * 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 HOLDER 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.worldmap; - -import java.awt.image.BufferedImage; -import net.runelite.api.coords.WorldPoint; -import net.runelite.client.ui.overlay.worldmap.WorldMapPoint; - -class FarmingPatchPoint extends WorldMapPoint -{ - FarmingPatchPoint(WorldPoint point, String tooltip, BufferedImage icon) - { - super(point, icon); - setTooltip(tooltip); - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/FishingSpotLocation.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/FishingSpotLocation.java index 3180ca0973..4b04a4beea 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/FishingSpotLocation.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/FishingSpotLocation.java @@ -95,6 +95,9 @@ enum FishingSpotLocation IORWERTH_CAMP_OUTSIDE(FishingSpot.SALMON, new WorldPoint(2215, 3245, 0)), ISAFDAR_NORTH_EAST_INSIDE(FishingSpot.SALMON, new WorldPoint(3293, 6005, 0)), ISAFDAR_NORTH_EAST_OUTSIDE(FishingSpot.SALMON, new WorldPoint(2269, 3253, 0)), + ISLE_OF_SOULS_EAST(FishingSpot.SHARK, new WorldPoint(2281, 2841, 0)), + ISLE_OF_SOULS_NORTH(FishingSpot.LOBSTER, new WorldPoint(2280, 2975, 0)), + ISLE_OF_SOULS_SOUTH_WEST(FishingSpot.SHRIMP, new WorldPoint(2162, 2782, 0)), JATISZO(new FishingSpot[]{FishingSpot.SHARK, FishingSpot.LOBSTER}, new WorldPoint(2400, 3780, 0), new WorldPoint(2412, 3780, 0), new WorldPoint(2419, 3789, 0)), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/FishingSpotPoint.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/FishingSpotPoint.java deleted file mode 100644 index fa32c86ffe..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/FishingSpotPoint.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2020, melky - * 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 HOLDER 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.worldmap; - -import java.awt.image.BufferedImage; -import net.runelite.api.coords.WorldPoint; -import net.runelite.client.ui.overlay.worldmap.WorldMapPoint; - -class FishingSpotPoint extends WorldMapPoint -{ - FishingSpotPoint(WorldPoint point, String tooltip, BufferedImage icon) - { - super(point, icon); - setTooltip(tooltip); - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/HunterAreaLocation.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/HunterAreaLocation.java index 3f9ee919b8..5607170461 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/HunterAreaLocation.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/HunterAreaLocation.java @@ -49,6 +49,9 @@ enum HunterAreaLocation FOSSIL_ISLAND_UNDERWATER(new WorldPoint(3743, 10295, 0), HunterCreature.FISH_SHOAL), GWENITH_HUNTER_AREA_OUTSIDE(new WorldPoint(2269, 3408, 0), HunterCreature.CARNIVOROUS_CHINCHOMPA), GWENITH_HUNTER_AREA_INSIDE(new WorldPoint(3293, 6160, 0), HunterCreature.CARNIVOROUS_CHINCHOMPA), + ISLE_OF_SOULS_NORTH(new WorldPoint(2207, 2964, 0), HunterCreature.COPPER_LONGTAIL), + ISLE_OF_SOULS_NORTH_WEST(new WorldPoint(2127, 2950, 0), HunterCreature.CHINCHOMPA), + ISLE_OF_SOULS_SOUTH_WEST(new WorldPoint(2158, 2822, 0), HunterCreature.CRIMSON_SWIFT), KARAMJA_HUNTER_AREA(new WorldPoint(2786, 3001, 0), HunterCreature.HORNED_GRAAHK), KEBOS_SWAMP(new WorldPoint(1184, 3595, 0), HunterCreature.CRIMSON_SWIFT), KOUREND_WOODLAND_CENTER(new WorldPoint(1512, 3478, 0), HunterCreature.RUBY_HARVEST), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/HunterAreaPoint.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/HunterAreaPoint.java deleted file mode 100644 index 2725f3de11..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/HunterAreaPoint.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2020, melky - * 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 HOLDER 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.worldmap; - -import java.awt.image.BufferedImage; -import net.runelite.client.ui.overlay.worldmap.WorldMapPoint; - -class HunterAreaPoint extends WorldMapPoint -{ - HunterAreaPoint(HunterAreaLocation data, BufferedImage icon) - { - super(data.getLocation(), icon); - setTooltip(data.getTooltip()); - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/KourendTaskPoint.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/KourendTaskPoint.java deleted file mode 100644 index 21170e0789..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/KourendTaskPoint.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2020, Brooklyn - * 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 HOLDER 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.worldmap; - -import net.runelite.client.ui.overlay.worldmap.WorldMapPoint; - -public class KourendTaskPoint extends WorldMapPoint -{ - KourendTaskPoint(KourendTaskLocation data) - { - super(data.getLocation(), WorldMapPlugin.BLANK_ICON); - setTooltip(data.getTooltip()); - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/AgilityCoursePoint.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/MapPoint.java similarity index 77% rename from runelite-client/src/main/java/net/runelite/client/plugins/worldmap/AgilityCoursePoint.java rename to runelite-client/src/main/java/net/runelite/client/plugins/worldmap/MapPoint.java index 982f8db975..161c669604 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/AgilityCoursePoint.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/MapPoint.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, melky + * Copyright (c) 2021, Adam * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,18 +25,32 @@ */ package net.runelite.client.plugins.worldmap; -import java.awt.image.BufferedImage; +import lombok.Getter; +import lombok.experimental.SuperBuilder; import net.runelite.client.ui.overlay.worldmap.WorldMapPoint; -class AgilityCoursePoint extends WorldMapPoint +@SuperBuilder +class MapPoint extends WorldMapPoint { - AgilityCoursePoint(AgilityCourseLocation data, BufferedImage icon, boolean showTooltip) + enum Type { - super(data.getLocation(), icon); - - if (showTooltip) - { - setTooltip(data.getTooltip()); - } + TELEPORT, + RUNECRAFT_ALTAR, + MINING_SITE, + DUNGEON, + HUNTER, + FISHING, + KOUREND_TASK, + FARMING_PATCH, + TRANSPORTATION, + MINIGAME, + FAIRY_RING, + AGILITY_COURSE, + AGILITY_SHORTCUT, + QUEST, + RARE_TREE } + + @Getter + private final Type type; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/MinigameLocation.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/MinigameLocation.java index a7145c8ee9..cc387c4872 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/MinigameLocation.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/MinigameLocation.java @@ -55,6 +55,7 @@ enum MinigameLocation PYRAMID_PLUNDER("Pyramid Plunder", new WorldPoint(3288, 2787, 0)), RANGING_GUILD("Ranging Guild", new WorldPoint(2671, 3419, 0)), ROGUES_DEN("Rogues' Den", new WorldPoint(2905, 3537, 0)), + SHADES_OF_MORTTON("Shades of Mort'ton", new WorldPoint(3505, 3315, 0)), SORCERESSS_GARDEN("Sorceress's Garden", new WorldPoint(3285, 3180, 0)), TROUBLE_BREWING("Trouble Brewing", new WorldPoint(3811, 3021, 0)), VOLCANIC_MINE("Volcanic Mine", new WorldPoint(3812, 3810, 0)), @@ -71,7 +72,13 @@ enum MinigameLocation CATAPULT_ROOM("Catapult Room", new WorldPoint(2842, 3545, 0)), SHOT_PUT_ROOM("Shot Put Room", new WorldPoint(2863, 3550, 0)), HALLOWED_SEPULCHRE("Hallowed Sepulchre", new WorldPoint(3653, 3386, 1)), - THE_GAUNTLET("The Gauntlet", new WorldPoint(3223, 12505, 1)); + THE_GAUNTLET("The Gauntlet", new WorldPoint(3223, 12505, 1)), + MAHOGANY_HOMES_ARDOUGNE("Mahogany Homes", new WorldPoint(2634, 3295, 0)), + MAHOGANY_HOMES_FALADOR("Mahogany Homes", new WorldPoint(2989, 3363, 0)), + MAHOGANY_HOMES_HOSIDIUS("Mahogany Homes", new WorldPoint(1780, 3623, 0)), + MAHOGANY_HOMES_VARROCK("Mahogany Homes", new WorldPoint(3240, 3471, 0)), + SOUL_WARS("Soul Wars", new WorldPoint(2209, 2855, 0)), + SOUL_WARS_EDGEVILLE_PORTAL("Soul Wars", new WorldPoint(3082, 3474, 0)); private final String tooltip; private final WorldPoint location; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/MiningSiteLocation.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/MiningSiteLocation.java index b01f709250..ef4db23372 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/MiningSiteLocation.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/MiningSiteLocation.java @@ -55,7 +55,7 @@ enum MiningSiteLocation BANDIT_CAMP_MINE(new WorldPoint(3086, 3763, 0), new Rock(16, Ore.IRON), new Rock(20, Ore.COAL), new Rock(22, Ore.MITHRIL), new Rock(8, Ore.ADAMANTITE)), BANDIT_CAMP_QUARRY(new WorldPoint(3171, 2912, 0), new Rock(4, Ore.CLAY), new Rock(2, Ore.COAL), new Rock(32, Ore.SANDSTONE), new Rock(28, Ore.GRANITE)), BARBARIAN_VILLAGE(new WorldPoint(3078, 3421, 0), new Rock(5, Ore.TIN), new Rock(4, Ore.COAL)), - BATTLEFIELD(new WorldPoint(2471, 3255, 0), new Rock(2, Ore.COPPER), new Rock(1, Ore.TIN)), + BATTLEFIELD(new WorldPoint(2471, 3255, 0), new Rock(3, Ore.COPPER), new Rock(1, Ore.TIN)), BLAST_MINE_EAST(new WorldPoint(1502, 3869, 0), new Rock(20, Ore.HARD_ROCK)), BLAST_MINE_NORTH(new WorldPoint(1485, 3882, 0), new Rock(17, Ore.HARD_ROCK)), BLAST_MINE_WEST(new WorldPoint(1471, 3865, 0), new Rock(22, Ore.HARD_ROCK)), @@ -117,6 +117,11 @@ enum MiningSiteLocation new Rock(10, Ore.CLAY), new Rock(11, Ore.COPPER), new Rock(4, Ore.TIN), new Rock(9, Ore.IRON), new Rock(2, Ore.SILVER)), ISAFDAR(new WorldPoint(2277, 3159, 0), new Rock(4, Ore.ADAMANTITE), new Rock(2, Ore.RUNITE)), + ISLE_OF_SOULS_DUNGEON_EAST(new WorldPoint(1831, 9109, 0), new Rock(1, Ore.RUNITE)), + ISLE_OF_SOULS_DUNGEON_WEST(new WorldPoint(1814, 9116, 0), new Rock(2, Ore.ADAMANTITE)), + ISLE_OF_SOULS_SOUTH(new WorldPoint(2195, 2793, 0), + new Rock(3, Ore.CLAY), new Rock(3, Ore.TIN), new Rock(3, Ore.COPPER), new Rock(10, Ore.IRON), + new Rock(3, Ore.SILVER), new Rock(6, Ore.COAL), new Rock(4, Ore.GOLD), new Rock(2, Ore.MITHRIL)), JATIZSO(new WorldPoint(2396, 3812, 0), new Rock(11, Ore.TIN), new Rock(7, Ore.IRON), new Rock(8, Ore.COAL), new Rock(15, Ore.MITHRIL), new Rock(11, Ore.ADAMANTITE)), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/MiningSitePoint.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/MiningSitePoint.java deleted file mode 100644 index 3a09a1b298..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/MiningSitePoint.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2020, dekvall - * 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 HOLDER 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.worldmap; - -import java.awt.image.BufferedImage; -import net.runelite.client.ui.overlay.worldmap.WorldMapPoint; - -class MiningSitePoint extends WorldMapPoint -{ - MiningSitePoint(MiningSiteLocation point, BufferedImage icon) - { - super(point.getLocation(), icon); - setTooltip(point.getTooltip()); - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/QuestStartLocation.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/QuestStartLocation.java index bf4c69b756..f731d20e9a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/QuestStartLocation.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/QuestStartLocation.java @@ -38,7 +38,7 @@ enum QuestStartLocation THE_CORSAIR_CURSE(Quest.THE_CORSAIR_CURSE, new WorldPoint(3029, 3273, 0)), DEMON_SLAYER(Quest.DEMON_SLAYER, new WorldPoint(3204, 3424, 0)), DORICS_QUEST(Quest.DORICS_QUEST, new WorldPoint(2952, 3450, 0)), - DRAGON_SLAYER(Quest.DRAGON_SLAYER, new WorldPoint(3190, 3362, 0)), + DRAGON_SLAYER_I(Quest.DRAGON_SLAYER_I, new WorldPoint(3190, 3362, 0)), ERNEST_THE_CHICKEN(Quest.ERNEST_THE_CHICKEN, new WorldPoint(3109, 3330, 0)), GOBLIN_DIPLOMACY(Quest.GOBLIN_DIPLOMACY, new WorldPoint(2957, 3509, 0)), IMP_CATCHER(Quest.IMP_CATCHER, new WorldPoint(3108, 3160, 0)), @@ -136,7 +136,7 @@ enum QuestStartLocation A_PORCINE_OF_INTEREST(Quest.A_PORCINE_OF_INTEREST, new WorldPoint(3085, 3251, 0)), PRIEST_IN_PERIL(Quest.PRIEST_IN_PERIL, new WorldPoint(3219, 3473, 0)), THE_QUEEN_OF_THIEVES(Quest.THE_QUEEN_OF_THIEVES, new WorldPoint(1795, 3782, 0)), - RAG_AND_BONE_MAN(new Quest[]{Quest.RAG_AND_BONE_MAN, Quest.RAG_AND_BONE_MAN_II}, new WorldPoint(3359, 3504, 0)), + RAG_AND_BONE_MAN_I(new Quest[]{Quest.RAG_AND_BONE_MAN_I, Quest.RAG_AND_BONE_MAN_II}, new WorldPoint(3359, 3504, 0)), RECRUITMENT_DRIVE_BLACK_KNIGHTS_FORTRESS(new Quest[]{Quest.BLACK_KNIGHTS_FORTRESS, Quest.RECRUITMENT_DRIVE}, new WorldPoint(2959, 3336, 0)), ROVING_ELVES(Quest.ROVING_ELVES, new WorldPoint(2288, 3146, 0)), RUM_DEAL(Quest.RUM_DEAL, new WorldPoint(3679, 3535, 0)), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/QuestStartPoint.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/QuestStartPoint.java deleted file mode 100644 index 681015b98e..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/QuestStartPoint.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2018, John James Hamilton - * 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 HOLDER 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.worldmap; - -import net.runelite.api.coords.WorldPoint; -import net.runelite.client.ui.overlay.worldmap.WorldMapPoint; -import java.awt.image.BufferedImage; - -class QuestStartPoint extends WorldMapPoint -{ - QuestStartPoint(WorldPoint location, BufferedImage icon, String tooltip) - { - super(location, icon); - setTooltip(tooltip); - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/RareTreeLocation.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/RareTreeLocation.java index addcda5af7..f7751bf5dd 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/RareTreeLocation.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/RareTreeLocation.java @@ -83,6 +83,9 @@ enum RareTreeLocation new WorldPoint(2748, 3466, 0), new WorldPoint(2710, 3570, 0), + // Isle of Souls + new WorldPoint(2254, 2808, 0), + // Prifddinas new WorldPoint(2209, 3427, 0), new WorldPoint(3233, 6179, 0)), @@ -111,6 +114,9 @@ enum RareTreeLocation // Mos Le'Harmless new WorldPoint(3810, 3058, 0), + // Isle of Souls + new WorldPoint(2194, 2991, 0), + // Karamja new WorldPoint(2821, 3084, 0)), @@ -180,6 +186,10 @@ enum RareTreeLocation new WorldPoint(3674, 3447, 0), new WorldPoint(3684, 3385, 0), + // Isle of Souls + new WorldPoint(2147, 2972, 0), + new WorldPoint(2165, 2863, 0), + // Zanaris new WorldPoint(2412, 4464, 0), new WorldPoint(2465, 4427, 0), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/RareTreePoint.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/RareTreePoint.java deleted file mode 100644 index 0dd42013bd..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/RareTreePoint.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2018, Spedwards - * 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 HOLDER 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.worldmap; - -import net.runelite.api.coords.WorldPoint; -import net.runelite.client.ui.overlay.worldmap.WorldMapPoint; - -import java.awt.image.BufferedImage; - -class RareTreePoint extends WorldMapPoint -{ - RareTreePoint(WorldPoint point, String tooltip, BufferedImage icon, boolean showTooltip) - { - super(point, icon); - - if (showTooltip) - { - setTooltip(tooltip); - } - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/RunecraftingAltarPoint.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/RunecraftingAltarPoint.java deleted file mode 100644 index d09ced3ce9..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/RunecraftingAltarPoint.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2019, Dava96 - * 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 HOLDER 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.worldmap; - -import net.runelite.client.ui.overlay.worldmap.WorldMapPoint; -import net.runelite.client.util.ImageUtil; - -class RunecraftingAltarPoint extends WorldMapPoint -{ - RunecraftingAltarPoint(RunecraftingAltarLocation point) - { - super(point.getLocation(), WorldMapPlugin.BLANK_ICON); - setImage(ImageUtil.loadImageResource(WorldMapPlugin.class, point.getIconPath())); - setTooltip(point.getTooltip()); - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TeleportLocationData.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TeleportLocationData.java index d2753e8010..44fb0b0dfb 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TeleportLocationData.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TeleportLocationData.java @@ -187,7 +187,8 @@ enum TeleportLocationData TAI_BWO_WANNAI_SCROLL(TeleportType.SCROLL, "Tai Bwo Wannai Teleport", new WorldPoint(2788, 3066, 0), "scroll_teleport_icon.png"), ZULANDRA_SCROLL(TeleportType.SCROLL, "Zul-Andra Teleport", new WorldPoint(2197, 3056, 0), "scroll_teleport_icon.png"), KEY_MASTER_SCROLL(TeleportType.SCROLL, "Key Master Teleport", new WorldPoint(2686, 9882, 0), "scroll_teleport_icon.png"), - REVENANT_CAVE_SCROLL(TeleportType.SCROLL, "Revenant Cave Teleport", new WorldPoint(3127, 3833, 0), "scroll_teleport_icon.png"); + REVENANT_CAVE_SCROLL(TeleportType.SCROLL, "Revenant Cave Teleport", new WorldPoint(3127, 3833, 0), "scroll_teleport_icon.png"), + WATSON_SCROLL(TeleportType.SCROLL, "Watson Teleport", new WorldPoint(1645, 3579, 0), "scroll_teleport_icon.png"); private final TeleportType type; private final String tooltip; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TeleportPoint.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TeleportPoint.java deleted file mode 100644 index a1171cfbc6..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TeleportPoint.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2018, Morgan Lewis - * 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 HOLDER 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.worldmap; - -import net.runelite.client.ui.overlay.worldmap.WorldMapPoint; -import net.runelite.client.util.ImageUtil; - -class TeleportPoint extends WorldMapPoint -{ - TeleportPoint(TeleportLocationData data) - { - super(data.getLocation(), WorldMapPlugin.BLANK_ICON); - setTooltip(data.getTooltip()); - setImage(ImageUtil.loadImageResource(WorldMapPlugin.class, data.getIconPath())); - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TransportationPoint.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TransportationPoint.java deleted file mode 100644 index 2996794212..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TransportationPoint.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2019, Kyle Sergio - * Copyright (c) 2019, Bryce Altomare - * Copyright (c) 2019, Kyle Stead - * 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 HOLDER 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.worldmap; - -import net.runelite.api.coords.WorldPoint; -import net.runelite.client.ui.overlay.worldmap.WorldMapPoint; -import java.awt.image.BufferedImage; - -class TransportationPoint extends WorldMapPoint -{ - TransportationPoint(TransportationPointLocation data, BufferedImage icon) - { - super(data.getLocation(), icon); - final WorldPoint target = data.getTarget(); - if (target != null) - { - setTarget(target); - setJumpOnClick(true); - } - setTooltip(data.getTooltip()); - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TransportationPointLocation.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TransportationPointLocation.java index d7a683076e..3d3913a304 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TransportationPointLocation.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TransportationPointLocation.java @@ -192,6 +192,7 @@ enum TransportationPointLocation MUSHTREE_TAR_SWAMP("Mushtree", new WorldPoint(3676, 3755, 0)), MUSHTREE_VERDANT_VALLEY("Mushtree", new WorldPoint(3757, 3756, 0)), MYTHS_GUILD_PORTAL("Portal to Guilds", new WorldPoint(2456, 2856, 0)), + SOUL_WARS_PORTAL("Portal to Edgeville/Ferox Enclave", new WorldPoint(2204, 2858, 0)), TRAIN_KELDAGRIM("Railway Station", new WorldPoint(2941, 10179, 0)), WILDERNESS_LEVER_ARDOUGNE("Wilderness Lever to Deserted Keep", new WorldPoint(2559, 3309, 0), new WorldPoint(3154, 3924, 0)), WILDERNESS_LEVER_EDGEVILLE("Wilderness Lever to Deserted Keep", new WorldPoint(3088, 3474, 0), new WorldPoint(3154, 3924, 0)), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/WorldMapConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/WorldMapConfig.java index 8dddb1ad60..3fbca342b6 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/WorldMapConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/WorldMapConfig.java @@ -34,7 +34,7 @@ public interface WorldMapConfig extends Config { @ConfigItem( keyName = WorldMapPlugin.CONFIG_KEY_FAIRY_RING_TOOLTIPS, - name = "Show fairy ring codes in tooltip", + name = "Fairy ring code tooltip", description = "Display the code for fairy rings in the icon tooltip", position = 1 ) @@ -45,7 +45,7 @@ public interface WorldMapConfig extends Config @ConfigItem( keyName = WorldMapPlugin.CONFIG_KEY_FAIRY_RING_ICON, - name = "Show fairy ring travel icon", + name = "Fairy ring travel icon", description = "Override the travel icon for fairy rings", position = 2 ) @@ -56,7 +56,7 @@ public interface WorldMapConfig extends Config @ConfigItem( keyName = WorldMapPlugin.CONFIG_KEY_AGILITY_SHORTCUT_TOOLTIPS, - name = "Show agility level requirement", + name = "Agility level requirement", description = "Display the required Agility level in the icon tooltip", position = 3 ) @@ -78,7 +78,7 @@ public interface WorldMapConfig extends Config @ConfigItem( keyName = WorldMapPlugin.CONFIG_KEY_AGILITY_COURSE_TOOLTIPS, - name = "Show agility course in tooltip", + name = "Agility course tooltip", description = "Displays the name of the agility course in the tooltip", position = 5 ) @@ -100,7 +100,7 @@ public interface WorldMapConfig extends Config @ConfigItem( keyName = WorldMapPlugin.CONFIG_KEY_NORMAL_TELEPORT_ICON, - name = "Show Standard Spellbook destinations", + name = "Standard Spellbook destinations", description = "Show icons at the destinations for teleports in the Standard Spellbook", position = 7 ) @@ -111,7 +111,7 @@ public interface WorldMapConfig extends Config @ConfigItem( keyName = WorldMapPlugin.CONFIG_KEY_MINIGAME_TOOLTIP, - name = "Show minigame name in tooltip", + name = "Minigame names", description = "Display the name of the minigame in the icon tooltip", position = 8 ) @@ -122,7 +122,7 @@ public interface WorldMapConfig extends Config @ConfigItem( keyName = WorldMapPlugin.CONFIG_KEY_ANCIENT_TELEPORT_ICON, - name = "Show Ancient Magicks destinations", + name = "Ancient Magicks destinations", description = "Show icons at the destinations for teleports in the Ancient Spellbook", position = 9 ) @@ -133,7 +133,7 @@ public interface WorldMapConfig extends Config @ConfigItem( keyName = WorldMapPlugin.CONFIG_KEY_LUNAR_TELEPORT_ICON, - name = "Show Lunar Spellbook destinations", + name = "Lunar Spellbook destinations", description = "Show icons at the destinations for teleports in the Lunar Spellbook", position = 10 ) @@ -144,7 +144,7 @@ public interface WorldMapConfig extends Config @ConfigItem( keyName = WorldMapPlugin.CONFIG_KEY_ARCEUUS_TELEPORT_ICON, - name = "Show Arceuus Spellbook destinations", + name = "Arceuus Spellbook destinations", description = "Show icons at the destinations for teleports in the Arceuus Spellbook", position = 11 ) @@ -155,7 +155,7 @@ public interface WorldMapConfig extends Config @ConfigItem( keyName = WorldMapPlugin.CONFIG_KEY_JEWELLERY_TELEPORT_ICON, - name = "Show jewellery teleport locations", + name = "Jewellery teleport destinations", description = "Show icons at the destinations for teleports from jewellery", position = 12 ) @@ -166,7 +166,7 @@ public interface WorldMapConfig extends Config @ConfigItem( keyName = WorldMapPlugin.CONFIG_KEY_SCROLL_TELEPORT_ICON, - name = "Show teleport scroll locations", + name = "Teleport scroll destinations", description = "Show icons at the destinations for teleports from scrolls", position = 13 ) @@ -177,7 +177,7 @@ public interface WorldMapConfig extends Config @ConfigItem( keyName = WorldMapPlugin.CONFIG_KEY_MISC_TELEPORT_ICON, - name = "Show misc teleport locations", + name = "Misc teleport destinations", description = "Show icons at the destinations for miscellaneous teleport items", position = 14 ) @@ -188,7 +188,7 @@ public interface WorldMapConfig extends Config @ConfigItem( keyName = WorldMapPlugin.CONFIG_KEY_QUEST_START_TOOLTIPS, - name = "Show quest names and status", + name = "Quest names and status", description = "Indicates the names of quests and shows completion status", position = 15 ) @@ -199,7 +199,7 @@ public interface WorldMapConfig extends Config @ConfigItem( keyName = WorldMapPlugin.CONFIG_KEY_FARMING_PATCH_TOOLTIPS, - name = "Show farming patch type", + name = "Farming patch type", description = "Display the type of farming patches in the icon tooltip", position = 16 ) @@ -210,7 +210,7 @@ public interface WorldMapConfig extends Config @ConfigItem( keyName = WorldMapPlugin.CONFIG_KEY_RARE_TREE_TOOLTIPS, - name = "Show rare tree type", + name = "Rare tree type", description = "Display the type of rare tree in the icon tooltip", position = 17 ) @@ -232,7 +232,7 @@ public interface WorldMapConfig extends Config @ConfigItem( keyName = WorldMapPlugin.CONFIG_KEY_TRANSPORTATION_TELEPORT_TOOLTIPS, - name = "Show transportation tooltips", + name = "Transportation tooltips", description = "Indicates types and destinations of Transportation", position = 19 ) @@ -243,7 +243,7 @@ public interface WorldMapConfig extends Config @ConfigItem( keyName = WorldMapPlugin.CONFIG_KEY_RUNECRAFTING_ALTAR_ICON, - name = "Show runecrafting altar locations", + name = "Runecrafting altar locations", description = "Show the icons of runecrafting altars", position = 20 ) @@ -254,7 +254,7 @@ public interface WorldMapConfig extends Config @ConfigItem( keyName = WorldMapPlugin.CONFIG_KEY_MINING_SITE_TOOLTIPS, - name = "Show mining site tooltips", + name = "Mining site tooltips", description = "Indicates the ore available at mining sites", position = 21 ) @@ -265,7 +265,7 @@ public interface WorldMapConfig extends Config @ConfigItem( keyName = WorldMapPlugin.CONFIG_KEY_DUNGEON_TOOLTIPS, - name = "Show dungeon tooltips", + name = "Dungeon tooltips", description = "Indicates the names of dungeons", position = 22 ) @@ -276,7 +276,7 @@ public interface WorldMapConfig extends Config @ConfigItem( keyName = WorldMapPlugin.CONFIG_KEY_HUNTER_AREA_TOOLTIPS, - name = "Show hunter area tooltips", + name = "Hunter area tooltips", description = "Indicates the creatures inside a hunting area", position = 23 ) @@ -287,7 +287,7 @@ public interface WorldMapConfig extends Config @ConfigItem( keyName = WorldMapPlugin.CONFIG_KEY_FISHING_SPOT_TOOLTIPS, - name = "Show fishing spot tooltips", + name = "Fishing spot tooltips", description = "Indicates the type of fish fishable at the fishing spot", position = 24 ) @@ -298,7 +298,7 @@ public interface WorldMapConfig extends Config @ConfigItem( keyName = WorldMapPlugin.CONFIG_KEY_KOUREND_TASK_TOOLTIPS, - name = "Show Kourend task tooltips", + name = "Kourend task tooltips", description = "Indicates the task or unlock for Kourend Favour locations", position = 25 ) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/WorldMapPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/WorldMapPlugin.java index 518edd0668..dcac0c700f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/WorldMapPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/WorldMapPlugin.java @@ -29,21 +29,23 @@ import com.google.inject.Inject; import com.google.inject.Provides; import java.awt.image.BufferedImage; import java.util.Arrays; +import java.util.function.Predicate; import net.runelite.api.Client; import net.runelite.api.GameState; import net.runelite.api.Quest; import net.runelite.api.QuestState; import net.runelite.api.Skill; -import net.runelite.client.events.ConfigChanged; import net.runelite.api.events.StatChanged; import net.runelite.api.events.WidgetLoaded; import net.runelite.api.widgets.WidgetID; import net.runelite.client.callback.ClientThread; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.events.ConfigChanged; import net.runelite.client.game.AgilityShortcut; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.ui.overlay.worldmap.WorldMapPoint; import net.runelite.client.ui.overlay.worldmap.WorldMapPointManager; import net.runelite.client.util.ImageUtil; @@ -161,18 +163,7 @@ public class WorldMapPlugin extends Plugin @Override protected void shutDown() throws Exception { - worldMapPointManager.removeIf(FairyRingPoint.class::isInstance); - worldMapPointManager.removeIf(AgilityShortcutPoint.class::isInstance); - worldMapPointManager.removeIf(QuestStartPoint.class::isInstance); - worldMapPointManager.removeIf(TeleportPoint.class::isInstance); - worldMapPointManager.removeIf(TransportationPoint.class::isInstance); - worldMapPointManager.removeIf(MinigamePoint.class::isInstance); - worldMapPointManager.removeIf(FarmingPatchPoint.class::isInstance); - worldMapPointManager.removeIf(RareTreePoint.class::isInstance); - worldMapPointManager.removeIf(RunecraftingAltarPoint.class::isInstance); - worldMapPointManager.removeIf(DungeonPoint.class::isInstance); - worldMapPointManager.removeIf(FishingSpotPoint.class::isInstance); - worldMapPointManager.removeIf(AgilityCoursePoint.class::isInstance); + worldMapPointManager.removeIf(MapPoint.class::isInstance); agilityLevel = 0; woodcuttingLevel = 0; } @@ -195,7 +186,7 @@ public class WorldMapPlugin extends Plugin { case AGILITY: { - int newAgilityLevel = statChanged.getLevel(); + int newAgilityLevel = statChanged.getBoostedLevel(); if (newAgilityLevel != agilityLevel) { agilityLevel = newAgilityLevel; @@ -205,7 +196,7 @@ public class WorldMapPlugin extends Plugin } case WOODCUTTING: { - int newWoodcutLevel = statChanged.getLevel(); + int newWoodcutLevel = statChanged.getBoostedLevel(); if (newWoodcutLevel != woodcuttingLevel) { woodcuttingLevel = newWoodcutLevel; @@ -229,47 +220,61 @@ public class WorldMapPlugin extends Plugin private void updateAgilityIcons() { - worldMapPointManager.removeIf(AgilityShortcutPoint.class::isInstance); + worldMapPointManager.removeIf(isType(MapPoint.Type.AGILITY_SHORTCUT)); if (config.agilityShortcutLevelIcon() || config.agilityShortcutTooltips()) { Arrays.stream(AgilityShortcut.values()) .filter(value -> value.getWorldMapLocation() != null) - .map(value -> new AgilityShortcutPoint(value, - agilityLevel > 0 && config.agilityShortcutLevelIcon() && value.getLevel() > agilityLevel ? NOPE_ICON : BLANK_ICON, - config.agilityShortcutTooltips())) + .map(l -> + MapPoint.builder() + .type(MapPoint.Type.AGILITY_SHORTCUT) + .worldPoint(l.getWorldMapLocation()) + .image(agilityLevel > 0 && config.agilityShortcutLevelIcon() && l.getLevel() > agilityLevel ? NOPE_ICON : BLANK_ICON) + .tooltip(config.agilityShortcutTooltips() ? l.getTooltip() : null) + .build() + ) .forEach(worldMapPointManager::add); } } private void updateAgilityCourseIcons() { - worldMapPointManager.removeIf(AgilityCoursePoint.class::isInstance); + worldMapPointManager.removeIf(isType(MapPoint.Type.AGILITY_COURSE)); if (config.agilityCourseTooltip() || config.agilityCourseRooftop()) { Arrays.stream(AgilityCourseLocation.values()) .filter(value -> value.getLocation() != null) - .map(value -> new AgilityCoursePoint(value, - config.agilityCourseRooftop() && value.isRooftopCourse() ? ROOFTOP_COURSE_ICON : BLANK_ICON, - config.agilityCourseTooltip())) + .map(l -> + MapPoint.builder() + .type(MapPoint.Type.AGILITY_COURSE) + .worldPoint(l.getLocation()) + .image(config.agilityCourseRooftop() && l.isRooftopCourse() ? ROOFTOP_COURSE_ICON : BLANK_ICON) + .tooltip(config.agilityCourseTooltip() ? l.getTooltip() : null) + .build() + ) .forEach(worldMapPointManager::add); } } private void updateRareTreeIcons() { - worldMapPointManager.removeIf(RareTreePoint.class::isInstance); + worldMapPointManager.removeIf(isType(MapPoint.Type.RARE_TREE)); if (config.rareTreeLevelIcon() || config.rareTreeTooltips()) { Arrays.stream(RareTreeLocation.values()).forEach(rareTree -> Arrays.stream(rareTree.getLocations()) - .map(point -> new RareTreePoint(point, - rareTree.getTooltip(), - woodcuttingLevel > 0 && config.rareTreeLevelIcon() && - rareTree.getLevelReq() > woodcuttingLevel ? NOPE_ICON : BLANK_ICON, - config.rareTreeTooltips())) + .map(point -> + MapPoint.builder() + .type(MapPoint.Type.RARE_TREE) + .worldPoint(point) + .image(woodcuttingLevel > 0 && config.rareTreeLevelIcon() && + rareTree.getLevelReq() > woodcuttingLevel ? NOPE_ICON : BLANK_ICON) + .tooltip(config.rareTreeTooltips() ? rareTree.getTooltip() : null) + .build() + ) .forEach(worldMapPointManager::add)); } } @@ -281,43 +286,71 @@ public class WorldMapPlugin extends Plugin updateRareTreeIcons(); updateQuestStartPointIcons(); - worldMapPointManager.removeIf(FairyRingPoint.class::isInstance); + worldMapPointManager.removeIf(isType(MapPoint.Type.FAIRY_RING)); if (config.fairyRingIcon() || config.fairyRingTooltips()) { Arrays.stream(FairyRingLocation.values()) - .map(value -> new FairyRingPoint(value, - config.fairyRingIcon() ? FAIRY_TRAVEL_ICON : BLANK_ICON, - config.fairyRingTooltips())) + .map(l -> + MapPoint.builder() + .type(MapPoint.Type.FAIRY_RING) + .worldPoint(l.getLocation()) + .image(config.fairyRingIcon() ? FAIRY_TRAVEL_ICON : BLANK_ICON) + .tooltip(config.fairyRingTooltips() ? "Fairy Ring - " + l.getCode() : null) + .build() + ) .forEach(worldMapPointManager::add); } - worldMapPointManager.removeIf(MinigamePoint.class::isInstance); + worldMapPointManager.removeIf(isType(MapPoint.Type.MINIGAME)); if (config.minigameTooltip()) { Arrays.stream(MinigameLocation.values()) - .map(value -> new MinigamePoint(value, BLANK_ICON)) + .map(l -> + MapPoint.builder() + .type(MapPoint.Type.MINIGAME) + .worldPoint(l.getLocation()) + .image(BLANK_ICON) + .tooltip(l.getTooltip()) + .build() + ) .forEach(worldMapPointManager::add); } - worldMapPointManager.removeIf(TransportationPoint.class::isInstance); + worldMapPointManager.removeIf(isType(MapPoint.Type.TRANSPORTATION)); if (config.transportationTeleportTooltips()) { Arrays.stream(TransportationPointLocation.values()) - .map(value -> new TransportationPoint(value, BLANK_ICON)) - .forEach((worldMapPointManager::add)); + .map(l -> + MapPoint.builder() + .type(MapPoint.Type.TRANSPORTATION) + .worldPoint(l.getLocation()) + .image(BLANK_ICON) + .target(l.getTarget()) + .jumpOnClick(l.getTarget() != null) + .tooltip(l.getTooltip()) + .build() + ) + .forEach((worldMapPointManager::add)); } - worldMapPointManager.removeIf(FarmingPatchPoint.class::isInstance); + worldMapPointManager.removeIf(isType(MapPoint.Type.FARMING_PATCH)); if (config.farmingPatchTooltips()) { Arrays.stream(FarmingPatchLocation.values()).forEach(location -> Arrays.stream(location.getLocations()) - .map(point -> new FarmingPatchPoint(point, location.getTooltip(), BLANK_ICON)) + .map(point -> + MapPoint.builder() + .type(MapPoint.Type.FARMING_PATCH) + .worldPoint(point) + .image(BLANK_ICON) + .tooltip(location.getTooltip()) + .build() + ) .forEach(worldMapPointManager::add) ); } - worldMapPointManager.removeIf(TeleportPoint.class::isInstance); + worldMapPointManager.removeIf(isType(MapPoint.Type.TELEPORT)); Arrays.stream(TeleportLocationData.values()) .filter(data -> { @@ -340,63 +373,113 @@ public class WorldMapPlugin extends Plugin default: return false; } - }).map(TeleportPoint::new) + }) + .map(l -> + MapPoint.builder() + .type(MapPoint.Type.TELEPORT) + .worldPoint(l.getLocation()) + .tooltip(l.getTooltip()) + .image(ImageUtil.loadImageResource(WorldMapPlugin.class, l.getIconPath())) + .build() + ) .forEach(worldMapPointManager::add); - worldMapPointManager.removeIf(RunecraftingAltarPoint.class::isInstance); + worldMapPointManager.removeIf(isType(MapPoint.Type.RUNECRAFT_ALTAR)); if (config.runecraftingAltarIcon()) { Arrays.stream(RunecraftingAltarLocation.values()) - .map(RunecraftingAltarPoint::new) + .map(l -> + MapPoint.builder() + .type(MapPoint.Type.RUNECRAFT_ALTAR) + .worldPoint(l.getLocation()) + .image(ImageUtil.loadImageResource(WorldMapPlugin.class, l.getIconPath())) + .tooltip(l.getTooltip()) + .build() + ) .forEach(worldMapPointManager::add); } - worldMapPointManager.removeIf(MiningSitePoint.class::isInstance); + worldMapPointManager.removeIf(isType(MapPoint.Type.MINING_SITE)); if (config.miningSiteTooltips()) { Arrays.stream(MiningSiteLocation.values()) - .map(value -> new MiningSitePoint(value, value.isIconRequired() ? MINING_SITE_ICON : BLANK_ICON)) + .map(l -> + MapPoint.builder() + .type(MapPoint.Type.MINING_SITE) + .worldPoint(l.getLocation()) + .image(l.isIconRequired() ? MINING_SITE_ICON : BLANK_ICON) + .tooltip(l.getTooltip()) + .build() + ) .forEach(worldMapPointManager::add); } - worldMapPointManager.removeIf(DungeonPoint.class::isInstance); + worldMapPointManager.removeIf(isType(MapPoint.Type.DUNGEON)); if (config.dungeonTooltips()) { Arrays.stream(DungeonLocation.values()) - .map(value -> new DungeonPoint(value, BLANK_ICON)) + .map(l -> + MapPoint.builder() + .type(MapPoint.Type.DUNGEON) + .worldPoint(l.getLocation()) + .image(BLANK_ICON) + .tooltip(l.getTooltip()) + .build() + ) .forEach(worldMapPointManager::add); } - worldMapPointManager.removeIf(HunterAreaPoint.class::isInstance); + worldMapPointManager.removeIf(isType(MapPoint.Type.HUNTER)); if (config.hunterAreaTooltips()) { Arrays.stream(HunterAreaLocation.values()) - .map(value -> new HunterAreaPoint(value, BLANK_ICON)) + .map(l -> + MapPoint.builder() + .type(MapPoint.Type.HUNTER) + .worldPoint(l.getLocation()) + .image(BLANK_ICON) + .tooltip(l.getTooltip()) + .build() + ) .forEach(worldMapPointManager::add); } - worldMapPointManager.removeIf(FishingSpotPoint.class::isInstance); + worldMapPointManager.removeIf(isType(MapPoint.Type.FISHING)); if (config.fishingSpotTooltips()) { Arrays.stream(FishingSpotLocation.values()).forEach(location -> Arrays.stream(location.getLocations()) - .map(point -> new FishingSpotPoint(point, location.getTooltip(), BLANK_ICON)) + .map(point -> + MapPoint.builder() + .type(MapPoint.Type.FISHING) + .worldPoint(point) + .image(BLANK_ICON) + .tooltip(location.getTooltip()) + .build() + ) .forEach(worldMapPointManager::add) ); } - worldMapPointManager.removeIf(KourendTaskPoint.class::isInstance); + worldMapPointManager.removeIf(isType(MapPoint.Type.KOUREND_TASK)); if (config.kourendTaskTooltips()) { Arrays.stream(KourendTaskLocation.values()) - .map(KourendTaskPoint::new) + .map(l -> + MapPoint.builder() + .type(MapPoint.Type.KOUREND_TASK) + .worldPoint(l.getLocation()) + .image(BLANK_ICON) + .tooltip(l.getTooltip()) + .build() + ) .forEach(worldMapPointManager::add); } } private void updateQuestStartPointIcons() { - worldMapPointManager.removeIf(QuestStartPoint.class::isInstance); + worldMapPointManager.removeIf(isType(MapPoint.Type.QUEST)); if (!config.questStartTooltips()) { @@ -418,7 +501,7 @@ public class WorldMapPlugin extends Plugin }); } - private QuestStartPoint createQuestStartPoint(QuestStartLocation data) + private MapPoint createQuestStartPoint(QuestStartLocation data) { Quest[] quests = data.getQuests(); @@ -459,6 +542,16 @@ public class WorldMapPlugin extends Plugin } } - return new QuestStartPoint(data.getLocation(), icon, tooltip); + return MapPoint.builder() + .type(MapPoint.Type.QUEST) + .worldPoint(data.getLocation()) + .image(icon) + .tooltip(tooltip) + .build(); + } + + private static Predicate isType(MapPoint.Type type) + { + return w -> w instanceof MapPoint && ((MapPoint) w).getType() == type; } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xpglobes/XpGlobesConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/xpglobes/XpGlobesConfig.java index c32a8c598a..2a956da851 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xpglobes/XpGlobesConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xpglobes/XpGlobesConfig.java @@ -89,11 +89,22 @@ public interface XpGlobesConfig extends Config return false; } + @ConfigItem( + keyName = "showVirtualLevel", + name = "Show virtual level", + description = "Shows virtual level if over 99 in a skill and Hide maxed skill is not checked", + position = 5 + ) + default boolean showVirtualLevel() + { + return false; + } + @ConfigItem( keyName = "enableCustomArcColor", name = "Enable custom arc color", description = "Enables the custom coloring of the globe's arc instead of using the skill's default color.", - position = 5 + position = 6 ) default boolean enableCustomArcColor() { @@ -105,7 +116,7 @@ public interface XpGlobesConfig extends Config keyName = "Progress arc color", name = "Progress arc color", description = "Change the color of the progress arc in the xp orb", - position = 6 + position = 7 ) default Color progressArcColor() { @@ -117,7 +128,7 @@ public interface XpGlobesConfig extends Config keyName = "Progress orb outline color", name = "Progress orb outline color", description = "Change the color of the progress orb outline", - position = 7 + position = 8 ) default Color progressOrbOutLineColor() { @@ -129,7 +140,7 @@ public interface XpGlobesConfig extends Config keyName = "Progress orb background color", name = "Progress orb background color", description = "Change the color of the progress orb background", - position = 8 + position = 9 ) default Color progressOrbBackgroundColor() { @@ -140,7 +151,7 @@ public interface XpGlobesConfig extends Config keyName = "Progress arc width", name = "Progress arc width", description = "Change the stroke width of the progress arc", - position = 9 + position = 10 ) @Units(Units.PIXELS) default int progressArcStrokeWidth() @@ -152,7 +163,7 @@ public interface XpGlobesConfig extends Config keyName = "Orb size", name = "Size of orbs", description = "Change the size of the xp orbs", - position = 10 + position = 11 ) @Units(Units.PIXELS) default int xpOrbSize() @@ -164,7 +175,7 @@ public interface XpGlobesConfig extends Config keyName = "Orb duration", name = "Duration of orbs", description = "Change the duration the xp orbs are visible", - position = 11 + position = 12 ) @Units(Units.SECONDS) default int xpOrbDuration() diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xpglobes/XpGlobesPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/xpglobes/XpGlobesPlugin.java index 46b514151e..39b947616a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xpglobes/XpGlobesPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xpglobes/XpGlobesPlugin.java @@ -106,9 +106,17 @@ public class XpGlobesPlugin extends Plugin return; } - if (config.hideMaxed() && currentLevel >= Experience.MAX_REAL_LEVEL) + if (currentLevel >= Experience.MAX_REAL_LEVEL) { - return; + if (config.hideMaxed()) + { + return; + } + + if (config.showVirtualLevel()) + { + currentLevel = Experience.getLevelForXp(currentXp); + } } if (cachedGlobe != null) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpState.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpState.java index fac3c16410..1fbbdb2c49 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpState.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpState.java @@ -159,8 +159,8 @@ class XpState } /** - * Update number of actions performed for skill (e.g amount of kills in this case) if last interacted - * NPC died + * Update number of actions performed for skill if last interacted NPC died. + * (eg. amount of kills in this case) * @param skill skill to update actions for * @param npc npc that just died * @param npcHealth max health of npc that just died diff --git a/runelite-client/src/main/java/net/runelite/client/rs/ClientLoader.java b/runelite-client/src/main/java/net/runelite/client/rs/ClientLoader.java index af99a64106..e3569398c4 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/ClientLoader.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/ClientLoader.java @@ -140,7 +140,7 @@ public class ClientLoader implements Supplier // in the jar. Otherwise the jar can change on disk and can break future classloads. File oprsInjected = new File(System.getProperty("user.home") + "/.openosrs/cache/injected-client.jar"); InputStream initialStream = RuneLite.class.getResourceAsStream("injected-client.oprs"); - if (oprsInjected.length() != RuneLite.class.getResource("injected-client.oprs").getFile().length()) + if (!oprsInjected.exists() || oprsInjected.length() != RuneLite.class.getResource("injected-client.oprs").getFile().length()) FileUtils.copyInputStreamToFile(initialStream, oprsInjected); classLoader = createJarClassLoader(oprsInjected); diff --git a/runelite-client/src/main/java/net/runelite/client/ui/ColorScheme.java b/runelite-client/src/main/java/net/runelite/client/ui/ColorScheme.java index b66c62d7fd..538a59b1c5 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/ColorScheme.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/ColorScheme.java @@ -38,10 +38,10 @@ public class ColorScheme public static final Color BRAND_BLUE_TRANSPARENT = new Color(25, 194, 255, 120); /* The orange color used for the branding's accents */ - public static final Color BRAND_ORANGE = new Color(220, 138, 0); + public static final Color BRAND_ORANGE = BRAND_BLUE; /* The orange color used for the branding's accents, with lowered opacity */ - public static final Color BRAND_ORANGE_TRANSPARENT = new Color(220, 138, 0, 120); + public static final Color BRAND_ORANGE_TRANSPARENT = BRAND_BLUE_TRANSPARENT; public static final Color DARKER_GRAY_COLOR = new Color(30, 30, 30); public static final Color DARK_GRAY_COLOR = new Color(40, 40, 40); diff --git a/runelite-client/src/main/java/net/runelite/client/ui/FontManager.java b/runelite-client/src/main/java/net/runelite/client/ui/FontManager.java index 564ebcba62..5305506a41 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/FontManager.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/FontManager.java @@ -24,17 +24,25 @@ */ package net.runelite.client.ui; -import javax.swing.text.StyleContext; import java.awt.Font; import java.awt.FontFormatException; import java.awt.GraphicsEnvironment; import java.io.IOException; +import javax.swing.text.StyleContext; +import lombok.Getter; public class FontManager { + @Getter private static final Font runescapeFont; + @Getter private static final Font runescapeSmallFont; + @Getter private static final Font runescapeBoldFont; + @Getter + private static final Font defaultFont; + @Getter + private static final Font defaultBoldFont; static { @@ -48,7 +56,7 @@ public class FontManager ge.registerFont(font); runescapeFont = StyleContext.getDefaultStyleContext() - .getFont(font.getName(), Font.PLAIN, 16); + .getFont(font.getName(), Font.PLAIN, 16); ge.registerFont(runescapeFont); Font smallFont = Font.createFont(Font.TRUETYPE_FONT, @@ -57,16 +65,16 @@ public class FontManager ge.registerFont(smallFont); runescapeSmallFont = StyleContext.getDefaultStyleContext() - .getFont(smallFont.getName(), Font.PLAIN, 16); + .getFont(smallFont.getName(), Font.PLAIN, 16); ge.registerFont(runescapeSmallFont); Font boldFont = Font.createFont(Font.TRUETYPE_FONT, - FontManager.class.getResourceAsStream("runescape_bold.ttf")) - .deriveFont(Font.BOLD, 16); + FontManager.class.getResourceAsStream("runescape_bold.ttf")) + .deriveFont(Font.BOLD, 16); ge.registerFont(boldFont); runescapeBoldFont = StyleContext.getDefaultStyleContext() - .getFont(boldFont.getName(), Font.BOLD, 16); + .getFont(boldFont.getName(), Font.BOLD, 16); ge.registerFont(runescapeBoldFont); } catch (FontFormatException ex) @@ -77,20 +85,8 @@ public class FontManager { throw new RuntimeException("Font file not found.", ex); } - } - public static Font getRunescapeFont() - { - return runescapeFont; - } - - public static Font getRunescapeSmallFont() - { - return runescapeSmallFont; - } - - public static Font getRunescapeBoldFont() - { - return runescapeBoldFont; + defaultFont = new Font(Font.DIALOG, Font.PLAIN, 16); + defaultBoldFont = new Font(Font.DIALOG, Font.BOLD, 16); } } diff --git a/runelite-client/src/main/java/net/runelite/client/ui/SplashScreen.java b/runelite-client/src/main/java/net/runelite/client/ui/SplashScreen.java index 2163e7b491..9c86509080 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/SplashScreen.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/SplashScreen.java @@ -69,7 +69,7 @@ public class SplashScreen extends JFrame implements ActionListener private SplashScreen() throws IOException { - BufferedImage logo = ImageUtil.getResourceStreamFromClass(SplashScreen.class, "runelite_transparent.png"); + BufferedImage logo = ImageUtil.loadImageResource(SplashScreen.class, "runelite_transparent.png"); setTitle("RuneLite Launcher"); diff --git a/runelite-client/src/main/java/net/runelite/client/ui/components/ComboBoxListRenderer.java b/runelite-client/src/main/java/net/runelite/client/ui/components/ComboBoxListRenderer.java index 5aeb710115..b73700134c 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/components/ComboBoxListRenderer.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/components/ComboBoxListRenderer.java @@ -39,11 +39,11 @@ import net.runelite.client.util.Text; * was very hard to see in the dark gray background, this makes the selected * item white and adds some padding to the elements for more readable list. */ -public final class ComboBoxListRenderer extends JLabel implements ListCellRenderer +public final class ComboBoxListRenderer extends JLabel implements ListCellRenderer { @Override - public Component getListCellRendererComponent(JList list, Object o, int index, boolean isSelected, boolean cellHasFocus) + public Component getListCellRendererComponent(JList list, T o, int index, boolean isSelected, boolean cellHasFocus) { if (isSelected) { diff --git a/runelite-client/src/main/java/net/runelite/client/ui/components/IconTextField.java b/runelite-client/src/main/java/net/runelite/client/ui/components/IconTextField.java index cb317b8afd..05806ada73 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/components/IconTextField.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/components/IconTextField.java @@ -29,17 +29,16 @@ package net.runelite.client.ui.components; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; +import java.awt.Font; import java.awt.event.ActionListener; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; -import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.ArrayList; import java.util.List; -import java.util.function.Consumer; import javax.swing.DefaultListModel; import javax.swing.ImageIcon; import javax.swing.JButton; @@ -125,7 +124,7 @@ public class IconTextField extends JPanel textField.addMouseListener(hoverEffect); innerTxt.addMouseListener(hoverEffect); - clearButton = createRHSButton(ColorScheme.PROGRESS_ERROR_COLOR, Color.PINK); + clearButton = createRHSButton(ColorScheme.PROGRESS_ERROR_COLOR, Color.PINK, FontManager.getRunescapeBoldFont()); clearButton.setText("×"); clearButton.addActionListener(evt -> { @@ -192,7 +191,7 @@ public class IconTextField extends JPanel } }); - suggestionButton = createRHSButton(ColorScheme.LIGHT_GRAY_COLOR, ColorScheme.MEDIUM_GRAY_COLOR); + suggestionButton = createRHSButton(ColorScheme.LIGHT_GRAY_COLOR, ColorScheme.MEDIUM_GRAY_COLOR, FontManager.getDefaultBoldFont()); suggestionButton.setText("▾"); suggestionButton.addActionListener(e -> { @@ -237,11 +236,11 @@ public class IconTextField extends JPanel add(rhsButtons, BorderLayout.EAST); } - private JButton createRHSButton(Color fg, Color rollover) + private JButton createRHSButton(Color fg, Color rollover, Font font) { JButton b = new JButton(); b.setPreferredSize(new Dimension(30, 0)); - b.setFont(FontManager.getRunescapeBoldFont()); + b.setFont(font); b.setBorder(null); b.setRolloverEnabled(true); SwingUtil.removeButtonDecorations(b); @@ -334,30 +333,6 @@ public class IconTextField extends JPanel clearListeners.add(clearListener); } - public void addKeyListener(Consumer keyEventConsumer) - { - addKeyListener(new net.runelite.client.input.KeyListener() - { - @Override - public void keyTyped(KeyEvent e) - { - keyEventConsumer.accept(e); - } - - @Override - public void keyPressed(KeyEvent e) - { - keyEventConsumer.accept(e); - } - - @Override - public void keyReleased(KeyEvent e) - { - keyEventConsumer.accept(e); - } - }); - } - @Override public void removeKeyListener(KeyListener keyListener) { diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/Overlay.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/Overlay.java index 151c5eae97..41944b5cd7 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/Overlay.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/Overlay.java @@ -57,7 +57,7 @@ public abstract class Overlay implements LayoutableRenderableEntity private boolean resettable = true; /** - * Whether this overlay can be dragged onto other overlays & have + * Whether this overlay can be dragged onto other overlays & have * other overlays dragged onto it. */ @Setter(AccessLevel.PROTECTED) diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayPanel.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayPanel.java index 6d749b765f..41afe1149c 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayPanel.java @@ -41,7 +41,7 @@ public abstract class OverlayPanel extends Overlay protected final PanelComponent panelComponent = new PanelComponent(); /** - * Enables/disables automatic clearing of {@link this#getPanelComponent()} children after rendering (enabled by default) + * Enables/disables automatic clearing of {@link OverlayPanel#getPanelComponent()} children after rendering (enabled by default) */ private boolean clearChildren = true; diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/WidgetOverlay.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/WidgetOverlay.java index c1c1028375..7f5ba0a4c2 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/WidgetOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/WidgetOverlay.java @@ -65,7 +65,8 @@ public class WidgetOverlay extends Overlay new WidgetOverlay(client, WidgetInfo.VOLCANIC_MINE_VENTS_INFOBOX_GROUP, OverlayPosition.BOTTOM_RIGHT), new WidgetOverlay(client, WidgetInfo.VOLCANIC_MINE_STABILITY_INFOBOX_GROUP, OverlayPosition.BOTTOM_LEFT), new WidgetOverlay(client, WidgetInfo.MULTICOMBAT_FIXED, OverlayPosition.BOTTOM_RIGHT), - new WidgetOverlay(client, WidgetInfo.MULTICOMBAT_RESIZEABLE, OverlayPosition.CANVAS_TOP_RIGHT) + new WidgetOverlay(client, WidgetInfo.MULTICOMBAT_RESIZEABLE_MODERN, OverlayPosition.CANVAS_TOP_RIGHT), + new WidgetOverlay(client, WidgetInfo.MULTICOMBAT_RESIZEABLE_CLASSIC, OverlayPosition.CANVAS_TOP_RIGHT) ); } diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/LineComponent.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/LineComponent.java index 20638e7874..83c67c09e0 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/LineComponent.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/LineComponent.java @@ -28,6 +28,7 @@ import com.google.common.base.MoreObjects; import com.google.common.base.Strings; import java.awt.Color; import java.awt.Dimension; +import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.Point; @@ -50,6 +51,10 @@ public class LineComponent implements LayoutableRenderableEntity @Builder.Default private Color rightColor = Color.WHITE; + private Font leftFont; + + private Font rightFont; + @Builder.Default private Point preferredLocation = new Point(); @@ -67,13 +72,16 @@ public class LineComponent implements LayoutableRenderableEntity final String left = MoreObjects.firstNonNull(this.left, ""); final String right = MoreObjects.firstNonNull(this.right, ""); - final FontMetrics metrics = graphics.getFontMetrics(); + final Font leftFont = MoreObjects.firstNonNull(this.leftFont, graphics.getFont()); + final Font rightFont = MoreObjects.firstNonNull(this.rightFont, graphics.getFont()); + final FontMetrics lfm = graphics.getFontMetrics(leftFont), rfm = graphics.getFontMetrics(rightFont); + final int fmHeight = Math.max(lfm.getHeight(), rfm.getHeight()); final int baseX = preferredLocation.x; - final int baseY = preferredLocation.y + metrics.getHeight(); + final int baseY = preferredLocation.y + fmHeight; int x = baseX; int y = baseY; - final int leftFullWidth = getLineWidth(left, metrics); - final int rightFullWidth = getLineWidth(right, metrics); + final int leftFullWidth = getLineWidth(left, lfm); + final int rightFullWidth = getLineWidth(right, rfm); final TextComponent textComponent = new TextComponent(); if (preferredSize.width < leftFullWidth + rightFullWidth) @@ -87,8 +95,8 @@ public class LineComponent implements LayoutableRenderableEntity leftSmallWidth -= rightSmallWidth; } - final String[] leftSplitLines = lineBreakText(left, leftSmallWidth, metrics); - final String[] rightSplitLines = lineBreakText(right, rightSmallWidth, metrics); + final String[] leftSplitLines = lineBreakText(left, leftSmallWidth, lfm); + final String[] rightSplitLines = lineBreakText(right, rightSmallWidth, rfm); int lineCount = Math.max(leftSplitLines.length, rightSplitLines.length); @@ -100,19 +108,21 @@ public class LineComponent implements LayoutableRenderableEntity textComponent.setPosition(new Point(x, y)); textComponent.setText(leftText); textComponent.setColor(leftColor); + textComponent.setFont(leftFont); textComponent.render(graphics); } if (i < rightSplitLines.length) { final String rightText = rightSplitLines[i]; - textComponent.setPosition(new Point(x + preferredSize.width - getLineWidth(rightText, metrics), y)); + textComponent.setPosition(new Point(x + preferredSize.width - getLineWidth(rightText, rfm), y)); textComponent.setText(rightText); textComponent.setColor(rightColor); + textComponent.setFont(rightFont); textComponent.render(graphics); } - y += metrics.getHeight(); + y += fmHeight; } final Dimension dimension = new Dimension(preferredSize.width, y - baseY); @@ -126,6 +136,7 @@ public class LineComponent implements LayoutableRenderableEntity textComponent.setPosition(new Point(x, y)); textComponent.setText(left); textComponent.setColor(leftColor); + textComponent.setFont(leftFont); textComponent.render(graphics); } @@ -134,10 +145,11 @@ public class LineComponent implements LayoutableRenderableEntity textComponent.setPosition(new Point(x + preferredSize.width - rightFullWidth, y)); textComponent.setText(right); textComponent.setColor(rightColor); + textComponent.setFont(rightFont); textComponent.render(graphics); } - y += metrics.getHeight(); + y += fmHeight; final Dimension dimension = new Dimension(preferredSize.width, y - baseY); bounds.setLocation(preferredLocation); diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/TextComponent.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/TextComponent.java index 45326fea28..0b6054a466 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/TextComponent.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/TextComponent.java @@ -26,10 +26,12 @@ package net.runelite.client.ui.overlay.components; import java.awt.Color; import java.awt.Dimension; +import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.Point; import java.util.regex.Pattern; +import javax.annotation.Nullable; import lombok.Setter; import net.runelite.client.ui.overlay.RenderableEntity; import net.runelite.client.util.ColorUtil; @@ -45,10 +47,22 @@ public class TextComponent implements RenderableEntity private Point position = new Point(); private Color color = Color.WHITE; private boolean outline; + /** + * The text font. + */ + @Nullable + private Font font; @Override public Dimension render(Graphics2D graphics) { + Font originalFont = null; + if (font != null) + { + originalFont = graphics.getFont(); + graphics.setFont(font); + } + final FontMetrics fontMetrics = graphics.getFontMetrics(); if (COL_TAG_PATTERN_W_LOOKAHEAD.matcher(text).find()) @@ -105,6 +119,14 @@ public class TextComponent implements RenderableEntity graphics.drawString(text, position.x, position.y); } - return new Dimension(fontMetrics.stringWidth(text), fontMetrics.getHeight()); + int width = fontMetrics.stringWidth(text); + int height = fontMetrics.getHeight(); + + if (originalFont != null) + { + graphics.setFont(originalFont); + } + + return new Dimension(width, height); } } diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/worldmap/WorldMapPoint.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/worldmap/WorldMapPoint.java index 878b0125a0..836bcd1ef5 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/worldmap/WorldMapPoint.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/worldmap/WorldMapPoint.java @@ -27,12 +27,14 @@ package net.runelite.client.ui.overlay.worldmap; import java.awt.Rectangle; import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; +import javax.annotation.Nullable; import lombok.Data; +import lombok.experimental.SuperBuilder; import net.runelite.api.Point; import net.runelite.api.coords.WorldPoint; -import javax.annotation.Nullable; @Data +@SuperBuilder public class WorldMapPoint { private BufferedImage image; diff --git a/runelite-client/src/main/java/net/runelite/client/util/DeferredDocumentChangedListener.java b/runelite-client/src/main/java/net/runelite/client/util/DeferredDocumentChangedListener.java new file mode 100644 index 0000000000..a0cddbf5f4 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/util/DeferredDocumentChangedListener.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2019, Owain van Brakel + * 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.util; + +import java.util.ArrayList; +import java.util.List; +import javax.swing.Timer; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; + +public class DeferredDocumentChangedListener implements DocumentListener +{ + private final Timer timer; + private final List listeners; + + public DeferredDocumentChangedListener() + { + listeners = new ArrayList<>(25); + timer = new Timer(200, e -> fireStateChanged()); + timer.setRepeats(false); + } + + public void addChangeListener(ChangeListener listener) + { + listeners.add(listener); + } + + private void fireStateChanged() + { + if (!listeners.isEmpty()) + { + ChangeEvent evt = new ChangeEvent(this); + for (ChangeListener listener : listeners) + { + listener.stateChanged(evt); + } + } + } + + @Override + public void insertUpdate(DocumentEvent e) + { + timer.restart(); + } + + @Override + public void removeUpdate(DocumentEvent e) + { + timer.restart(); + } + + @Override + public void changedUpdate(DocumentEvent e) + { + timer.restart(); + } + +} diff --git a/runelite-client/src/main/java/net/runelite/client/util/ImageCapture.java b/runelite-client/src/main/java/net/runelite/client/util/ImageCapture.java index dfee412c03..e842005dba 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/ImageCapture.java +++ b/runelite-client/src/main/java/net/runelite/client/util/ImageCapture.java @@ -26,6 +26,7 @@ package net.runelite.client.util; import com.google.common.base.Strings; +import com.google.gson.Gson; import java.awt.Toolkit; import java.awt.TrayIcon; import java.awt.datatransfer.Clipboard; @@ -54,7 +55,6 @@ import net.runelite.api.GameState; import net.runelite.api.WorldType; import net.runelite.client.Notifier; import static net.runelite.client.RuneLite.SCREENSHOT_DIR; -import net.runelite.http.api.RuneLiteAPI; import okhttp3.Call; import okhttp3.Callback; import okhttp3.HttpUrl; @@ -75,6 +75,7 @@ public class ImageCapture private final Client client; private final Notifier notifier; private final OkHttpClient okHttpClient; + private final Gson gson; private final String imgurClientId; @Inject @@ -82,12 +83,14 @@ public class ImageCapture final Client client, final Notifier notifier, final OkHttpClient okHttpClient, + final Gson gson, @Named("runelite.imgur.client.id") final String imgurClientId ) { this.client = client; this.notifier = notifier; this.okHttpClient = okHttpClient; + this.gson = gson; this.imgurClientId = imgurClientId; } @@ -204,7 +207,7 @@ public class ImageCapture */ private void uploadScreenshot(File screenshotFile, boolean notify) throws IOException { - String json = RuneLiteAPI.GSON.toJson(new ImageUploadRequest(screenshotFile)); + String json = gson.toJson(new ImageUploadRequest(screenshotFile)); Request request = new Request.Builder() .url(IMGUR_IMAGE_UPLOAD_URL) @@ -225,8 +228,8 @@ public class ImageCapture { try (InputStream in = response.body().byteStream()) { - ImageUploadResponse imageUploadResponse = RuneLiteAPI.GSON - .fromJson(new InputStreamReader(in, StandardCharsets.UTF_8), ImageUploadResponse.class); + ImageUploadResponse imageUploadResponse = + gson.fromJson(new InputStreamReader(in, StandardCharsets.UTF_8), ImageUploadResponse.class); if (imageUploadResponse.isSuccess()) { diff --git a/runelite-client/src/main/java/net/runelite/client/util/ImageUtil.java b/runelite-client/src/main/java/net/runelite/client/util/ImageUtil.java index 3efeabcfa4..219e0e2e48 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/ImageUtil.java +++ b/runelite-client/src/main/java/net/runelite/client/util/ImageUtil.java @@ -34,10 +34,12 @@ import java.awt.image.BufferedImage; import java.awt.image.DirectColorModel; import java.awt.image.PixelGrabber; import java.awt.image.RescaleOp; +import java.awt.image.WritableRaster; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.function.Predicate; import javax.imageio.ImageIO; import javax.swing.GrayFilter; import lombok.extern.slf4j.Slf4j; @@ -395,8 +397,9 @@ public class ImageUtil { for (int y = 0; y < filledImage.getHeight(); y++) { - final Color pixelColor = new Color(image.getRGB(x, y), true); - if (pixelColor.getAlpha() == 0) + int pixel = image.getRGB(x, y); + int a = pixel >>> 24; + if (a == 0) { continue; } @@ -524,4 +527,184 @@ public class ImageUtil return sprite; } + + /** + * Recolors pixels of the given image with the given color based on a given recolor condition + * predicate. + * + * @param image The image which should have its non-transparent pixels recolored. + * @param color The color with which to recolor pixels. + * @param recolorCondition The condition on which to recolor pixels with the given color. + * @return The given image with all pixels fulfilling the recolor condition predicate + * set to the given color. + */ + public static BufferedImage recolorImage(final BufferedImage image, final Color color, final Predicate recolorCondition) + { + final BufferedImage recoloredImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB); + for (int x = 0; x < recoloredImage.getWidth(); x++) + { + for (int y = 0; y < recoloredImage.getHeight(); y++) + { + final Color pixelColor = new Color(image.getRGB(x, y), true); + if (!recolorCondition.test(pixelColor)) + { + recoloredImage.setRGB(x, y, image.getRGB(x, y)); + continue; + } + + recoloredImage.setRGB(x, y, color.getRGB()); + } + } + return recoloredImage; + } + + public static BufferedImage recolorImage(BufferedImage image, final Color color) + { + int width = image.getWidth(); + int height = image.getHeight(); + WritableRaster raster = image.getRaster(); + + for (int xx = 0; xx < width; xx++) + { + for (int yy = 0; yy < height; yy++) + { + int[] pixels = raster.getPixel(xx, yy, (int[]) null); + pixels[0] = color.getRed(); + pixels[1] = color.getGreen(); + pixels[2] = color.getBlue(); + raster.setPixel(xx, yy, pixels); + } + } + return image; + } + + /** + * Draw fg centered on top of bg + */ + public static SpritePixels mergeSprites(final Client client, final SpritePixels bg, final SpritePixels fg) + { + assert fg.getHeight() <= bg.getHeight() && fg.getWidth() <= bg.getWidth() : "Background has to be larger than foreground"; + + final int[] canvas = Arrays.copyOf(bg.getPixels(), bg.getWidth() * bg.getHeight()); + final SpritePixels result = client.createSpritePixels(canvas, bg.getWidth(), bg.getHeight()); + + final int bgWid = bg.getWidth(); + final int fgHgt = fg.getHeight(); + final int fgWid = fg.getWidth(); + + final int xOffset = (bgWid - fgWid) / 2; + final int yOffset = (bg.getHeight() - fgHgt) / 2; + + final int[] fgPixels = fg.getPixels(); + + for (int y1 = yOffset, y2 = 0; y2 < fgHgt; y1++, y2++) + { + int i1 = y1 * bgWid + xOffset; + int i2 = y2 * fgWid; + + for (int x = 0; x < fgWid; x++, i1++, i2++) + { + if (fgPixels[i2] > 0) + { + canvas[i1] = fgPixels[i2]; + } + } + } + + return result; + } + + /** + * Resize Sprite sprite to given width (newW) and height (newH) + */ + public static SpritePixels resizeSprite(final Client client, final SpritePixels sprite, int newW, int newH) + { + assert newW > 0 && newH > 0; + + final int oldW = sprite.getWidth(); + final int oldH = sprite.getHeight(); + + if (oldW == newW && oldH == newH) + { + return sprite; + } + + final int[] canvas = new int[newW * newH]; + final int[] pixels = sprite.getPixels(); + + final SpritePixels result = client.createSpritePixels(canvas, newW, newH); + + int pixelX = 0; + int pixelY = 0; + + final int oldMaxW = sprite.getMaxWidth(); + final int oldMaxH = sprite.getMaxHeight(); + + final int pixelW = (oldMaxW << 16) / newW; + final int pixelH = (oldMaxH << 16) / newH; + + int xOffset = 0; + int yOffset = 0; + + int canvasIdx; + if (sprite.getOffsetX() > 0) + { + canvasIdx = (pixelW + (sprite.getOffsetX() << 16) - 1) / pixelW; + xOffset += canvasIdx; + pixelX += canvasIdx * pixelW - (sprite.getOffsetX() << 16); + } + + if (sprite.getOffsetY() > 0) + { + canvasIdx = (pixelH + (sprite.getOffsetY() << 16) - 1) / pixelH; + yOffset += canvasIdx; + pixelY += canvasIdx * pixelH - (sprite.getOffsetY() << 16); + } + + if (oldW < oldMaxW) + { + newW = (pixelW + ((oldW << 16) - pixelX) - 1) / pixelW; + } + + if (oldH < oldMaxH) + { + newH = (pixelH + ((oldH << 16) - pixelY) - 1) / pixelH; + } + + canvasIdx = xOffset + yOffset * newW; + int canvasOffset = 0; + if (yOffset + newH > newH) + { + newH -= yOffset + newH - newH; + } + + int tmp; + if (yOffset < 0) + { + tmp = -yOffset; + newH -= tmp; + canvasIdx += tmp * newW; + pixelY += pixelH * tmp; + } + + if (newW + xOffset > newW) + { + tmp = newW + xOffset - newW; + newW -= tmp; + canvasOffset += tmp; + } + + if (xOffset < 0) + { + tmp = -xOffset; + newW -= tmp; + canvasIdx += tmp; + pixelX += pixelW * tmp; + canvasOffset += tmp; + } + + client.scaleSprite(canvas, pixels, 0, pixelX, pixelY, canvasIdx, canvasOffset, newW, newH, pixelW, pixelH, oldW); + + return result; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/util/LinkBrowser.java b/runelite-client/src/main/java/net/runelite/client/util/LinkBrowser.java index e8965029c1..24828baa51 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/LinkBrowser.java +++ b/runelite-client/src/main/java/net/runelite/client/util/LinkBrowser.java @@ -207,4 +207,54 @@ public class LinkBrowser } }); } + + /** + * Tries to open the specified {@code File} with the systems default text editor. If operation fails + * an error message is displayed with the option to copy the absolute file path to clipboard. + * + * @param file the File instance of the log file + * @return did the file open successfully? + */ + public static boolean openLocalFile(final File file) + { + if (file == null || !file.exists()) + { + return false; + } + + if (attemptOpenLocalFile(file)) + { + log.debug("Opened log file through Desktop#open to {}", file); + return true; + } + + showMessageBox("Unable to open file. Press 'OK' and the file path will be copied to your clipboard", file.getAbsolutePath()); + return false; + } + + private static boolean attemptOpenLocalFile(final File file) + { + if (!Desktop.isDesktopSupported()) + { + return false; + } + + final Desktop desktop = Desktop.getDesktop(); + + if (!desktop.isSupported(Desktop.Action.OPEN)) + { + return false; + } + + try + { + desktop.open(file); + return true; + } + catch (IOException ex) + { + log.warn("Failed to open Desktop#open {}", file, ex); + return false; + } + } } diff --git a/runelite-client/src/main/java/net/runelite/client/util/PvPUtil.java b/runelite-client/src/main/java/net/runelite/client/util/PvPUtil.java new file mode 100644 index 0000000000..3380cf5a8f --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/util/PvPUtil.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2019, PKLite + * Copyright (c) 2020, ThatGamerBlue + * 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.util; + +import java.awt.Polygon; +import net.runelite.api.Client; +import net.runelite.api.Player; +import net.runelite.api.Varbits; +import net.runelite.api.WorldType; +import net.runelite.api.coords.WorldPoint; +import net.runelite.api.geometry.Cuboid; + +public class PvPUtil +{ + private static final Polygon NOT_WILDERNESS_BLACK_KNIGHTS = new Polygon( // this is black knights castle + new int[]{2994, 2995, 2996, 2996, 2994, 2994, 2997, 2998, 2998, 2999, 3000, 3001, 3002, 3003, 3004, 3005, 3005, + 3005, 3019, 3020, 3022, 3023, 3024, 3025, 3026, 3026, 3027, 3027, 3028, 3028, 3029, 3029, 3030, 3030, 3031, + 3031, 3032, 3033, 3034, 3035, 3036, 3037, 3037}, + new int[]{3525, 3526, 3527, 3529, 3529, 3534, 3534, 3535, 3536, 3537, 3538, 3539, 3540, 3541, 3542, 3543, 3544, + 3545, 3545, 3546, 3546, 3545, 3544, 3543, 3543, 3542, 3541, 3540, 3539, 3537, 3536, 3535, 3534, 3533, 3532, + 3531, 3530, 3529, 3528, 3527, 3526, 3526, 3525}, + 43 + ); + private static final Cuboid MAIN_WILDERNESS_CUBOID = new Cuboid(2944, 3525, 0, 3391, 4351, 3); + private static final Cuboid GOD_WARS_WILDERNESS_CUBOID = new Cuboid(3008, 10112, 0, 3071, 10175, 3); + private static final Cuboid WILDERNESS_UNDERGROUND_CUBOID = new Cuboid(2944, 9920, 0, 3391, 10879, 3); + + /** + * Gets the wilderness level based on a world point + * Java reimplementation of clientscript 384 [proc,wilderness_level] + * + * @param point the point in the world to get the wilderness level for + * @return the int representing the wilderness level + */ + public static int getWildernessLevelFrom(WorldPoint point) + { + if (MAIN_WILDERNESS_CUBOID.contains(point)) + { + if (NOT_WILDERNESS_BLACK_KNIGHTS.contains(point.getX(), point.getY())) + { + return 0; + } + + return ((point.getY() - 3520) / 8) + 1; // calc(((coordz(coord) - (55 * 64)) / 8) + 1) + } + else if (GOD_WARS_WILDERNESS_CUBOID.contains(point)) + { + return ((point.getY() - 9920) / 8) - 1; // calc(((coordz(coord) - (155 * 64)) / 8) - 1) + } + else if (WILDERNESS_UNDERGROUND_CUBOID.contains(point)) + { + return ((point.getY() - 9920) / 8) + 1; // calc(((coordz(coord) - (155 * 64)) / 8) + 1) + } + return 0; + } + + /** + * Determines if another player is attackable based off of wilderness level and combat levels + * + * @param client The client of the local player + * @param player the player to determine attackability + * @return returns true if the player is attackable, false otherwise + */ + public static boolean isAttackable(Client client, Player player) + { + int wildernessLevel = 0; + + if (WorldType.isDeadmanWorld(client.getWorldType())) + { + return true; + } + if (WorldType.isPvpWorld(client.getWorldType())) + { + wildernessLevel += 15; + } + if (client.getVar(Varbits.IN_WILDERNESS) == 1) + { + wildernessLevel += getWildernessLevelFrom(client.getLocalPlayer().getWorldLocation()); + } + return wildernessLevel != 0 && Math.abs(client.getLocalPlayer().getCombatLevel() - player.getCombatLevel()) <= wildernessLevel; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/util/QuantityFormatter.java b/runelite-client/src/main/java/net/runelite/client/util/QuantityFormatter.java index 49823b5cca..2b838e409c 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/QuantityFormatter.java +++ b/runelite-client/src/main/java/net/runelite/client/util/QuantityFormatter.java @@ -182,7 +182,7 @@ public class QuantityFormatter } /** - * Calculates, given a string with a value denominator (ex. 20K) + * Calculates, given a string with a value denominator (for example, 20K) * the multiplier that the denominator represents (in this case 1000). * * @param string The string to check. diff --git a/runelite-client/src/main/java/net/runelite/client/util/ReflectUtil.java b/runelite-client/src/main/java/net/runelite/client/util/ReflectUtil.java index 60b3b305f1..fbcc28d28d 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/ReflectUtil.java +++ b/runelite-client/src/main/java/net/runelite/client/util/ReflectUtil.java @@ -25,6 +25,8 @@ */ package net.runelite.client.util; +import com.google.common.io.ByteStreams; +import java.io.IOException; import java.lang.invoke.MethodHandles; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -36,7 +38,7 @@ public class ReflectUtil { } - public static MethodHandles.Lookup privateLookupIn(Class clazz) + public static MethodHandles.Lookup privateLookupIn(Class clazz) { try { @@ -44,7 +46,16 @@ public class ReflectUtil // we need to access it via reflection. This is preferred way because it's Java 9+ public api and is // likely to not change final Method privateLookupIn = MethodHandles.class.getMethod("privateLookupIn", Class.class, MethodHandles.Lookup.class); - return (MethodHandles.Lookup) privateLookupIn.invoke(null, clazz, MethodHandles.lookup()); + MethodHandles.Lookup caller; + if (clazz.getClassLoader() instanceof PrivateLookupableClassLoader) + { + caller = ((PrivateLookupableClassLoader) clazz.getClassLoader()).getLookup(); + } + else + { + caller = MethodHandles.lookup(); + } + return (MethodHandles.Lookup) privateLookupIn.invoke(null, clazz, caller); } catch (InvocationTargetException | IllegalAccessException e) { @@ -69,4 +80,51 @@ public class ReflectUtil } } } + + public interface PrivateLookupableClassLoader + { + // define class is protected final so this needs a different name to become public + Class defineClass0(String name, byte[] b, int off, int len) throws ClassFormatError; + + MethodHandles.Lookup getLookup(); + void setLookup(MethodHandles.Lookup lookup); + } + + /** + * Allows private Lookups to be created for classes in this ClassLoader + *

+ * Due to JDK-8173978 it is impossible to create get a lookup with module scoped permissions when teleporting + * between modules. Since external plugins are loaded in a separate classloader to us they are contained in unique + * unnamed modules. Since we (via LambdaMetafactory) are creating a hidden class in that module, we require module + * scoped access to it, and since the methods can be private, we also require private access. The only way to get + * MODULE|PRIVATE is to either 1) invokedynamic in that class, 2) call MethodHandles.lookup() from that class, or + * 3) call privateLookupIn with an existing lookup with PRIVATE|MODULE created from a class in the same module. + * Our solution is to make classloaders call this method which will define a class in the classloader's unnamed + * module that calls MethodHandles.lookup() and stores it in the classloader for later use. + */ + public static void installLookupHelper(PrivateLookupableClassLoader cl) + { + try + { + String name = PrivateLookupHelper.class.getName(); + byte[] classData = ByteStreams.toByteArray(ReflectUtil.class.getResourceAsStream("/" + name.replace('.', '/') + ".class")); + Class clazz = cl.defineClass0(name, classData, 0, classData.length); + + // force to run + clazz.getConstructor().newInstance(); + } + catch (IOException | ReflectiveOperationException e) + { + throw new RuntimeException("unable to install lookup helper", e); + } + } + + public static class PrivateLookupHelper + { + static + { + PrivateLookupableClassLoader pcl = (PrivateLookupableClassLoader) PrivateLookupHelper.class.getClassLoader(); + pcl.setLookup(MethodHandles.lookup()); + } + } } diff --git a/runelite-client/src/main/java/net/runelite/client/util/SwingUtil.java b/runelite-client/src/main/java/net/runelite/client/util/SwingUtil.java index 5f226a40c9..1f33ce9638 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/SwingUtil.java +++ b/runelite-client/src/main/java/net/runelite/client/util/SwingUtil.java @@ -40,6 +40,7 @@ import java.awt.TrayIcon; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; +import java.lang.reflect.InvocationTargetException; import java.util.Enumeration; import java.util.function.BiConsumer; import javax.annotation.Nonnull; @@ -302,4 +303,19 @@ public class SwingUtil l.enter(); } } + + /** + * Executes a runnable on the EDT, blocking until it finishes. + */ + public static void syncExec(final Runnable r) throws InvocationTargetException, InterruptedException + { + if (EventQueue.isDispatchThread()) + { + r.run(); + } + else + { + EventQueue.invokeAndWait(r); + } + } } diff --git a/runelite-client/src/main/resources/item_variations.json b/runelite-client/src/main/resources/item_variations.json index 62877d1869..9543697a90 100644 --- a/runelite-client/src/main/resources/item_variations.json +++ b/runelite-client/src/main/resources/item_variations.json @@ -2727,6 +2727,10 @@ 2464, 8936 ], + "black dhide vambraces": [ + 2491, + 25494 + ], "blue dhide chaps": [ 2493, 7382, @@ -2743,7 +2747,8 @@ 2497, 12383, 12387, - 20424 + 20424, + 25493 ], "blue dhide body": [ 2499, @@ -2761,7 +2766,8 @@ 2503, 12381, 12385, - 20423 + 20423, + 25492 ], "dragon chainbody": [ 2513, @@ -7760,7 +7766,15 @@ ], "toxic blowpipe": [ 12924, - 12926 + 12926, + 25484, + 25485, + 25486, + 25487, + 25488, + 25489, + 25490, + 25491 ], "serpentine helm": [ 12929, @@ -9240,21 +9254,24 @@ 23887, 23888, 23971, - 23973 + 23973, + 25495 ], "crystal body": [ 23889, 23890, 23891, 23975, - 23977 + 23977, + 25496 ], "crystal legs": [ 23892, 23893, 23894, 23979, - 23981 + 23981, + 25497 ], "crystal staff": [ 23898, @@ -9623,10 +9640,6 @@ 25319, 25338 ], - "gnome child": [ - 25320, - 25321 - ], "soul cape": [ 25344, 25346 @@ -9635,5 +9648,25 @@ 25380, 25383, 25386 + ], + "bronze coffin": [ + 25459, + 25469 + ], + "steel coffin": [ + 25461, + 25470 + ], + "black coffin": [ + 25463, + 25471 + ], + "silver coffin": [ + 25465, + 25472 + ], + "gold coffin": [ + 25467, + 25473 ] } \ No newline at end of file diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/fork_and_knife.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/fork_and_knife.png index f82589d6c3..6f11400816 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/fork_and_knife.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/fork_and_knife.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/spoon.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/spoon.png new file mode 100644 index 0000000000..dc40dd32d4 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/spoon.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/weary_face.png b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/weary_face.png new file mode 100644 index 0000000000..f8b113ea2d Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/emojis/weary_face.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/cl_types.cl b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/cl_types.cl new file mode 100644 index 0000000000..7f41acab49 --- /dev/null +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/cl_types.cl @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2021, Adam + * 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. + */ + +struct uniform { + int cameraYaw; + int cameraPitch; + int centerX; + int centerY; + int zoom; + int cameraX; + int cameraY; + int cameraZ; + int4 sinCosTable[2048]; +}; + +struct shared_data { + int totalNum[12]; // number of faces with a given priority + int totalDistance[12]; // sum of distances to faces of a given priority + int totalMappedNum[18]; // number of faces with a given adjusted priority + int min10; // minimum distance to a face of priority 10 + int dfs[0]; // packed face id and distance, size 512 for small, 4096 for large +}; + +struct modelinfo { + int offset; // offset into buffer + int uvOffset; // offset into uv buffer + int size; // length in faces + int idx; // write idx in target buffer + int flags; // radius, orientation + int x; // scene position x + int y; // scene position y + int z; // scene position z +}; diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/common.cl b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/common.cl new file mode 100644 index 0000000000..f499599cd2 --- /dev/null +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/common.cl @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2021, Adam + * 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. + */ + +#define PI 3.1415926535897932384626433832795f +#define UNIT PI / 1024.0f + +float3 toScreen(int4 vertex, int cameraYaw, int cameraPitch, int centerX, int centerY, int zoom) { + float yawSin = sin(cameraYaw * UNIT); + float yawCos = cos(cameraYaw * UNIT); + + float pitchSin = sin(cameraPitch * UNIT); + float pitchCos = cos(cameraPitch * UNIT); + + float rotatedX = (vertex.z * yawSin) + (vertex.x * yawCos); + float rotatedZ = (vertex.z * yawCos) - (vertex.x * yawSin); + + float var13 = (vertex.y * pitchCos) - (rotatedZ * pitchSin); + float var12 = (vertex.y * pitchSin) + (rotatedZ * pitchCos); + + float x = rotatedX * zoom / var12 + centerX; + float y = var13 * zoom / var12 + centerY; + float z = -var12; // in OpenGL depth is negative + + return (float3) (x, y, z); +} + +/* + * Rotate a vertex by a given orientation in JAU + */ +int4 rotate_vertex(__constant struct uniform *uni, int4 vertex, int orientation) { + int4 sinCos = uni->sinCosTable[orientation]; + int s = sinCos.x; + int c = sinCos.y; + int x = vertex.z * s + vertex.x * c >> 16; + int z = vertex.z * c - vertex.x * s >> 16; + return (int4)(x, vertex.y, z, vertex.w); +} + +/* + * Calculate the distance to a vertex given the camera angle + */ +int vertex_distance(int4 vertex, int cameraYaw, int cameraPitch) { + int yawSin = (int)(65536.0f * sin(cameraYaw * UNIT)); + int yawCos = (int)(65536.0f * cos(cameraYaw * UNIT)); + + int pitchSin = (int)(65536.0f * sin(cameraPitch * UNIT)); + int pitchCos = (int)(65536.0f * cos(cameraPitch * UNIT)); + + int j = vertex.z * yawCos - vertex.x * yawSin >> 16; + int l = vertex.y * pitchSin + j * pitchCos >> 16; + + return l; +} + +/* + * Calculate the distance to a face + */ +int face_distance(int4 vA, int4 vB, int4 vC, int cameraYaw, int cameraPitch) { + int dvA = vertex_distance(vA, cameraYaw, cameraPitch); + int dvB = vertex_distance(vB, cameraYaw, cameraPitch); + int dvC = vertex_distance(vC, cameraYaw, cameraPitch); + int faceDistance = (dvA + dvB + dvC) / 3; + return faceDistance; +} + +/* + * Test if a face is visible (not backward facing) + */ +bool face_visible(__constant struct uniform *uni, int4 vA, int4 vB, int4 vC, int4 position) { + // Move model to scene location, and account for camera offset + int4 cameraPos = (int4)(uni->cameraX, uni->cameraY, uni->cameraZ, 0); + vA += position - cameraPos; + vB += position - cameraPos; + vC += position - cameraPos; + + float3 sA = toScreen(vA, uni->cameraYaw, uni->cameraPitch, uni->centerX, uni->centerY, uni->zoom); + float3 sB = toScreen(vB, uni->cameraYaw, uni->cameraPitch, uni->centerX, uni->centerY, uni->zoom); + float3 sC = toScreen(vC, uni->cameraYaw, uni->cameraPitch, uni->centerX, uni->centerY, uni->zoom); + + return (sA.x - sB.x) * (sC.y - sB.y) - (sC.x - sB.x) * (sA.y - sB.y) > 0; +} + diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/comp.cl b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/comp.cl new file mode 100644 index 0000000000..1212123f25 --- /dev/null +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/comp.cl @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2021, Adam + * 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. + */ + +#include FACE_COUNT + +#include cl_types.cl +#include to_screen.cl +#include common.cl +#include priority_render.cl + +__kernel +__attribute__((work_group_size_hint(256, 1, 1))) +void computeLarge( + __local struct shared_data *shared, + __global const struct modelinfo *ol, + __global const int4 *vb, + __global const int4 *tempvb, + __global const float4 *uv, + __global const float4 *tempuv, + __global int4 *vout, + __global float4 *uvout, + __constant struct uniform *uni) { + + size_t groupId = get_group_id(0); + size_t localId = get_local_id(0) * FACE_COUNT; + struct modelinfo minfo = ol[groupId]; + int4 pos = (int4)(minfo.x, minfo.y, minfo.z, 0); + + if (localId == 0) { + shared->min10 = 1600; + for (int i = 0; i < 12; ++i) { + shared->totalNum[i] = 0; + shared->totalDistance[i] = 0; + } + for (int i = 0; i < 18; ++i) { + shared->totalMappedNum[i] = 0; + } + } + + int prio[FACE_COUNT]; + int dis[FACE_COUNT]; + int4 v1[FACE_COUNT]; + int4 v2[FACE_COUNT]; + int4 v3[FACE_COUNT]; + + for (int i = 0; i < FACE_COUNT; i++) { + get_face(shared, uni, vb, tempvb, localId + i, minfo, uni->cameraYaw, uni->cameraPitch, &prio[i], &dis[i], &v1[i], &v2[i], &v3[i]); + } + + barrier(CLK_LOCAL_MEM_FENCE); + + for (int i = 0; i < FACE_COUNT; i++) { + add_face_prio_distance(shared, uni, localId + i, minfo, v1[i], v2[i], v3[i], prio[i], dis[i], pos); + } + + barrier(CLK_LOCAL_MEM_FENCE); + + int prioAdj[FACE_COUNT]; + int idx[FACE_COUNT]; + for (int i = 0; i < FACE_COUNT; i++) { + idx[i] = map_face_priority(shared, localId + i, minfo, prio[i], dis[i], &prioAdj[i]); + } + + barrier(CLK_LOCAL_MEM_FENCE); + + for (int i = 0; i < FACE_COUNT; i++) { + insert_dfs(shared, localId + i, minfo, prioAdj[i], dis[i], idx[i]); + } + + barrier(CLK_LOCAL_MEM_FENCE); + + for (int i = 0; i < FACE_COUNT; i++) { + sort_and_insert(shared, uv, tempuv, vout, uvout, localId + i, minfo, prioAdj[i], dis[i], v1[i], v2[i], v3[i]); + } +} diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/comp_unordered.cl b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/comp_unordered.cl new file mode 100644 index 0000000000..436f9a7d72 --- /dev/null +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/comp_unordered.cl @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2021, Adam + * 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. + */ + +#include cl_types.cl + +__kernel +__attribute__((reqd_work_group_size(6, 1, 1))) +void computeUnordered(__global const struct modelinfo *ol, + __global const int4 *vb, + __global const int4 *tempvb, + __global const float4 *uv, + __global const float4 *tempuv, + __global int4 *vout, + __global float4 *uvout) { + size_t groupId = get_group_id(0); + size_t localId = get_local_id(0); + struct modelinfo minfo = ol[groupId]; + + int offset = minfo.offset; + int size = minfo.size; + int outOffset = minfo.idx; + int uvOffset = minfo.uvOffset; + int flags = minfo.flags; + int4 pos = (int4)(minfo.x, minfo.y, minfo.z, 0); + + if (localId >= size) { + return; + } + + uint ssboOffset = localId; + int4 thisA, thisB, thisC; + + // Grab triangle vertices from the correct buffer + if (flags < 0) { + thisA = vb[offset + ssboOffset * 3]; + thisB = vb[offset + ssboOffset * 3 + 1]; + thisC = vb[offset + ssboOffset * 3 + 2]; + } else { + thisA = tempvb[offset + ssboOffset * 3]; + thisB = tempvb[offset + ssboOffset * 3 + 1]; + thisC = tempvb[offset + ssboOffset * 3 + 2]; + } + + uint myOffset = localId; + + // position vertices in scene and write to out buffer + vout[outOffset + myOffset * 3] = pos + thisA; + vout[outOffset + myOffset * 3 + 1] = pos + thisB; + vout[outOffset + myOffset * 3 + 2] = pos + thisC; + + if (uvOffset < 0) { + uvout[outOffset + myOffset * 3] = (float4)(0.0f, 0.0f, 0.0f, 0.0f); + uvout[outOffset + myOffset * 3 + 1] = (float4)(0.0f, 0.0f, 0.0f, 0.0f); + uvout[outOffset + myOffset * 3 + 2] = (float4)(0.0f, 0.0f, 0.0f, 0.0f); + } else if (flags >= 0) { + uvout[outOffset + myOffset * 3] = tempuv[uvOffset + localId * 3]; + uvout[outOffset + myOffset * 3 + 1] = tempuv[uvOffset + localId * 3 + 1]; + uvout[outOffset + myOffset * 3 + 2] = tempuv[uvOffset + localId * 3 + 2]; + } else { + uvout[outOffset + myOffset * 3] = uv[uvOffset + localId * 3]; + uvout[outOffset + myOffset * 3 + 1] = uv[uvOffset + localId * 3 + 1]; + uvout[outOffset + myOffset * 3 + 2] = uv[uvOffset + localId * 3 + 2]; + } +} diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/priority_render.cl b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/priority_render.cl new file mode 100644 index 0000000000..6f1a04470c --- /dev/null +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/priority_render.cl @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2021, Adam + * 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. + */ + +// Calculate adjusted priority for a face with a given priority, distance, and +// model global min10 and face distance averages. This allows positioning faces +// with priorities 10/11 into the correct 'slots' resulting in 18 possible +// adjusted priorities +int priority_map(int p, int distance, int _min10, int avg1, int avg2, int avg3) { + // (10, 11) 0 1 2 (10, 11) 3 4 (10, 11) 5 6 7 8 9 (10, 11) + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 + switch (p) { + case 0: return 2; + case 1: return 3; + case 2: return 4; + case 3: return 7; + case 4: return 8; + case 5: return 11; + case 6: return 12; + case 7: return 13; + case 8: return 14; + case 9: return 15; + case 10: + if (distance > avg1) { + return 0; + } else if (distance > avg2) { + return 5; + } else if (distance > avg3) { + return 9; + } else { + return 16; + } + case 11: + if (distance > avg1 && _min10 > avg1) { + return 1; + } else if (distance > avg2 && (_min10 > avg1 || _min10 > avg2)) { + return 6; + } else if (distance > avg3 && (_min10 > avg1 || _min10 > avg2 || _min10 > avg3)) { + return 10; + } else { + return 17; + } + default: + return -1; + } +} + +// calculate the number of faces with a lower adjusted priority than +// the given adjusted priority +int count_prio_offset(__local struct shared_data *shared, int priority) { + int total = 0; + switch (priority) { + case 17: + total += shared->totalMappedNum[16]; + case 16: + total += shared->totalMappedNum[15]; + case 15: + total += shared->totalMappedNum[14]; + case 14: + total += shared->totalMappedNum[13]; + case 13: + total += shared->totalMappedNum[12]; + case 12: + total += shared->totalMappedNum[11]; + case 11: + total += shared->totalMappedNum[10]; + case 10: + total += shared->totalMappedNum[9]; + case 9: + total += shared->totalMappedNum[8]; + case 8: + total += shared->totalMappedNum[7]; + case 7: + total += shared->totalMappedNum[6]; + case 6: + total += shared->totalMappedNum[5]; + case 5: + total += shared->totalMappedNum[4]; + case 4: + total += shared->totalMappedNum[3]; + case 3: + total += shared->totalMappedNum[2]; + case 2: + total += shared->totalMappedNum[1]; + case 1: + total += shared->totalMappedNum[0]; + case 0: + return total; + } +} + +void get_face( + __local struct shared_data *shared, + __constant struct uniform *uni, + __global const int4 *vb, + __global const int4 *tempvb, + uint localId, struct modelinfo minfo, int cameraYaw, int cameraPitch, + /* out */ int *prio, int *dis, int4 *o1, int4 *o2, int4 *o3) { + int size = minfo.size; + int offset = minfo.offset; + int flags = minfo.flags; + uint ssboOffset; + + if (localId < size) { + ssboOffset = localId; + } else { + ssboOffset = 0; + } + + int4 thisA; + int4 thisB; + int4 thisC; + + // Grab triangle vertices from the correct buffer + if (flags < 0) { + thisA = vb[offset + ssboOffset * 3]; + thisB = vb[offset + ssboOffset * 3 + 1]; + thisC = vb[offset + ssboOffset * 3 + 2]; + } else { + thisA = tempvb[offset + ssboOffset * 3]; + thisB = tempvb[offset + ssboOffset * 3 + 1]; + thisC = tempvb[offset + ssboOffset * 3 + 2]; + } + + if (localId < size) { + int radius = (flags & 0x7fffffff) >> 12; + int orientation = flags & 0x7ff; + + // rotate for model orientation + int4 thisrvA = rotate_vertex(uni, thisA, orientation); + int4 thisrvB = rotate_vertex(uni, thisB, orientation); + int4 thisrvC = rotate_vertex(uni, thisC, orientation); + + // calculate distance to face + int thisPriority = (thisA.w >> 16) & 0xff;// all vertices on the face have the same priority + int thisDistance; + if (radius == 0) { + thisDistance = 0; + } else { + thisDistance = face_distance(thisrvA, thisrvB, thisrvC, cameraYaw, cameraPitch) + radius; + } + + *o1 = thisrvA; + *o2 = thisrvB; + *o3 = thisrvC; + + *prio = thisPriority; + *dis = thisDistance; + } else { + *o1 = (int4)(0, 0, 0, 0); + *o2 = (int4)(0, 0, 0, 0); + *o3 = (int4)(0, 0, 0, 0); + *prio = 0; + *dis = 0; + } +} + +void add_face_prio_distance( + __local struct shared_data *shared, + __constant struct uniform *uni, + uint localId, struct modelinfo minfo, int4 thisrvA, int4 thisrvB, int4 thisrvC, int thisPriority, int thisDistance, int4 pos) { + if (localId < minfo.size) { + // if the face is not culled, it is calculated into priority distance averages + if (face_visible(uni, thisrvA, thisrvB, thisrvC, pos)) { + atomic_add(&shared->totalNum[thisPriority], 1); + atomic_add(&shared->totalDistance[thisPriority], thisDistance); + + // calculate minimum distance to any face of priority 10 for positioning the 11 faces later + if (thisPriority == 10) { + atomic_min(&shared->min10, thisDistance); + } + } + } +} + +int map_face_priority(__local struct shared_data *shared, uint localId, struct modelinfo minfo, int thisPriority, int thisDistance, int *prio) { + int size = minfo.size; + + // Compute average distances for 0/2, 3/4, and 6/8 + + if (localId < size) { + int avg1 = 0; + int avg2 = 0; + int avg3 = 0; + + if (shared->totalNum[1] > 0 || shared->totalNum[2] > 0) { + avg1 = (shared->totalDistance[1] + shared->totalDistance[2]) / (shared->totalNum[1] + shared->totalNum[2]); + } + + if (shared->totalNum[3] > 0 || shared->totalNum[4] > 0) { + avg2 = (shared->totalDistance[3] + shared->totalDistance[4]) / (shared->totalNum[3] + shared->totalNum[4]); + } + + if (shared->totalNum[6] > 0 || shared->totalNum[8] > 0) { + avg3 = (shared->totalDistance[6] + shared->totalDistance[8]) / (shared->totalNum[6] + shared->totalNum[8]); + } + + int adjPrio = priority_map(thisPriority, thisDistance, shared->min10, avg1, avg2, avg3); + int prioIdx = atomic_add(&shared->totalMappedNum[adjPrio], 1); + + *prio = adjPrio; + return prioIdx; + } + + *prio = 0; + return 0; +} + +void insert_dfs(__local struct shared_data *shared, uint localId, struct modelinfo minfo, int adjPrio, int distance, int prioIdx) { + int size = minfo.size; + + if (localId < size) { + // calculate base offset into dfs based on number of faces with a lower priority + int baseOff = count_prio_offset(shared, adjPrio); + // store into face array offset array by unique index + shared->dfs[baseOff + prioIdx] = ((int) localId << 16) | distance; + } +} + +void sort_and_insert( + __local struct shared_data *shared, + __global const float4 *uv, + __global const float4 *tempuv, + __global int4 *vout, + __global float4 *uvout, + uint localId, struct modelinfo minfo, int thisPriority, int thisDistance, int4 thisrvA, int4 thisrvB, int4 thisrvC) { + /* compute face distance */ + int size = minfo.size; + + if (localId < size) { + int outOffset = minfo.idx; + int uvOffset = minfo.uvOffset; + int flags = minfo.flags; + int4 pos = (int4)(minfo.x, minfo.y, minfo.z, 0); + + const int priorityOffset = count_prio_offset(shared, thisPriority); + const int numOfPriority = shared->totalMappedNum[thisPriority]; + int start = priorityOffset; // index of first face with this priority + int end = priorityOffset + numOfPriority; // index of last face with this priority + int myOffset = priorityOffset; + + // we only have to order faces against others of the same priority + // calculate position this face will be in + for (int i = start; i < end; ++i) { + int d1 = shared->dfs[i]; + int theirId = d1 >> 16; + int theirDistance = d1 & 0xffff; + + // the closest faces draw last, so have the highest index + // if two faces have the same distance, the one with the + // higher id draws last + if ((theirDistance > thisDistance) + || (theirDistance == thisDistance && theirId < localId)) { + ++myOffset; + } + } + + // position vertices in scene and write to out buffer + vout[outOffset + myOffset * 3] = pos + thisrvA; + vout[outOffset + myOffset * 3 + 1] = pos + thisrvB; + vout[outOffset + myOffset * 3 + 2] = pos + thisrvC; + + if (uvOffset < 0) { + uvout[outOffset + myOffset * 3] = (float4)(0, 0, 0, 0); + uvout[outOffset + myOffset * 3 + 1] = (float4)(0, 0, 0, 0); + uvout[outOffset + myOffset * 3 + 2] = (float4)(0, 0, 0, 0); + } else if (flags >= 0) { + uvout[outOffset + myOffset * 3] = tempuv[uvOffset + localId * 3]; + uvout[outOffset + myOffset * 3 + 1] = tempuv[uvOffset + localId * 3 + 1]; + uvout[outOffset + myOffset * 3 + 2] = tempuv[uvOffset + localId * 3 + 2]; + } else { + uvout[outOffset + myOffset * 3] = uv[uvOffset + localId * 3]; + uvout[outOffset + myOffset * 3 + 1] = uv[uvOffset + localId * 3 + 1]; + uvout[outOffset + myOffset * 3 + 2] = uv[uvOffset + localId * 3 + 2]; + } + } +} diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/abyssal_sire.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/abyssal_sire.png index 3e41077561..c5b238a9d0 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/abyssal_sire.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/abyssal_sire.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/alchemical_hydra.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/alchemical_hydra.png index 3032e57ec4..b34ed9c93e 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/alchemical_hydra.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/alchemical_hydra.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/barrows_chests.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/barrows_chests.png index ba5c55efae..1560f1aaaa 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/barrows_chests.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/barrows_chests.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/bryophyta.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/bryophyta.png index 8cebd91ecf..68c4e2c904 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/bryophyta.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/bryophyta.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/callisto.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/callisto.png index 6f307a26d5..2248304cfe 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/callisto.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/callisto.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/cerberus.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/cerberus.png index 4f7ef937cd..f7dc1f8047 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/cerberus.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/cerberus.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/chambers_of_xeric.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/chambers_of_xeric.png index a7240d11f0..71bfdd30cf 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/chambers_of_xeric.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/chambers_of_xeric.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/chambers_of_xeric_challenge_mode.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/chambers_of_xeric_challenge_mode.png index c298966a16..31cc4b9cca 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/chambers_of_xeric_challenge_mode.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/chambers_of_xeric_challenge_mode.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/chaos_elemental.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/chaos_elemental.png index cc36114993..92ed8353fe 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/chaos_elemental.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/chaos_elemental.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/chaos_fanatic.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/chaos_fanatic.png index 73e680aef6..b712e9b70a 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/chaos_fanatic.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/chaos_fanatic.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/commander_zilyana.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/commander_zilyana.png index e207d7e791..9f1d6d20cc 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/commander_zilyana.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/commander_zilyana.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/corporeal_beast.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/corporeal_beast.png index cd113c8ad9..26c69b2e5c 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/corporeal_beast.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/corporeal_beast.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/crazy_archaeologist.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/crazy_archaeologist.png index 53d758bf8e..d7cd6eaf1a 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/crazy_archaeologist.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/crazy_archaeologist.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/dagannoth_prime.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/dagannoth_prime.png index 6b5543b5e1..bc6612dbf4 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/dagannoth_prime.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/dagannoth_prime.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/dagannoth_rex.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/dagannoth_rex.png index fc2bcbc3a0..a18662f702 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/dagannoth_rex.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/dagannoth_rex.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/dagannoth_supreme.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/dagannoth_supreme.png index 044291cc4a..4cb52e4156 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/dagannoth_supreme.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/dagannoth_supreme.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/deranged_archaeologist.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/deranged_archaeologist.png index 8dfae8c2fb..10ee3e8fb0 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/deranged_archaeologist.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/deranged_archaeologist.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/general_graardor.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/general_graardor.png index 1d8e4334fa..cefbc3c19b 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/general_graardor.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/general_graardor.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/giant_mole.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/giant_mole.png index f814bbd2d5..48619319dc 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/giant_mole.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/giant_mole.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/grotesque_guardians.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/grotesque_guardians.png index 98606aed11..cf0bd826d5 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/grotesque_guardians.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/grotesque_guardians.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/hespori.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/hespori.png index dffc71404c..a85a83ce3c 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/hespori.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/hespori.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/kalphite_queen.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/kalphite_queen.png index a6b77f9426..c88f0bb448 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/kalphite_queen.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/kalphite_queen.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/king_black_dragon.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/king_black_dragon.png index 3bc8a77466..c162208002 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/king_black_dragon.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/king_black_dragon.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/kraken.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/kraken.png index c42e5d3fc9..b45dd224fb 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/kraken.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/kraken.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/kreearra.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/kreearra.png index 74b9eae788..2bc9631476 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/kreearra.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/kreearra.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/kril_tsutsaroth.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/kril_tsutsaroth.png index dfe129ae77..878a14c18b 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/kril_tsutsaroth.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/kril_tsutsaroth.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/mimic.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/mimic.png index 3d2c0a4606..7f523c6b87 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/mimic.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/mimic.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/nightmare.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/nightmare.png index 22907bb92f..c0f7645c02 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/nightmare.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/nightmare.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/obor.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/obor.png index 8c9ea13036..eb9fc64725 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/obor.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/obor.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/sarachnis.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/sarachnis.png index e74c398976..cbea6a8024 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/sarachnis.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/sarachnis.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/scorpia.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/scorpia.png index eeb6310454..f39f9baa6e 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/scorpia.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/scorpia.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/skotizo.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/skotizo.png index cd96bbcca0..8888d2c315 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/skotizo.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/skotizo.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/the_corrupted_gauntlet.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/the_corrupted_gauntlet.png index 9553dde2c1..f1e2b6ec3a 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/the_corrupted_gauntlet.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/the_corrupted_gauntlet.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/the_gauntlet.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/the_gauntlet.png index e34fbe3d15..3e03f805c1 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/the_gauntlet.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/the_gauntlet.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/theatre_of_blood.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/theatre_of_blood.png index 0d05a8ab1e..5234c59637 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/theatre_of_blood.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/theatre_of_blood.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/thermonuclear_smoke_devil.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/thermonuclear_smoke_devil.png index 7869a9a817..d7315af194 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/thermonuclear_smoke_devil.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/thermonuclear_smoke_devil.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/tzkal_zuk.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/tzkal_zuk.png index 8b3262cd8b..1c6a966f19 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/tzkal_zuk.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/tzkal_zuk.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/tztok_jad.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/tztok_jad.png index 6ccee5515e..d181c8d93c 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/tztok_jad.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/tztok_jad.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/venenatis.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/venenatis.png index df08980743..76dbc9fac3 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/venenatis.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/venenatis.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/vetion.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/vetion.png index 383d30a119..67a7b3d645 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/vetion.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/vetion.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/vorkath.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/vorkath.png index 03bcc75ed4..c3732b1d02 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/vorkath.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/vorkath.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/wintertodt.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/wintertodt.png index eb1d8f47bb..478e0f968d 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/wintertodt.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/wintertodt.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/zalcano.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/zalcano.png index c4d6e21be0..72a0a1714b 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/zalcano.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/zalcano.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/zulrah.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/zulrah.png index 83d939a1ac..44a28c4cbd 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/zulrah.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/bosses/zulrah.png differ diff --git a/runelite-client/src/main/resources/com/openosrs/client/plugins/openosrs/externalmanager_icon.png b/runelite-client/src/main/resources/net/runelite/client/plugins/openosrs/externalmanager_icon.png similarity index 100% rename from runelite-client/src/main/resources/com/openosrs/client/plugins/openosrs/externalmanager_icon.png rename to runelite-client/src/main/resources/net/runelite/client/plugins/openosrs/externalmanager_icon.png diff --git a/runelite-client/src/main/resources/com/openosrs/client/plugins/openosrs/externals/add_icon.png b/runelite-client/src/main/resources/net/runelite/client/plugins/openosrs/externals/add_icon.png similarity index 100% rename from runelite-client/src/main/resources/com/openosrs/client/plugins/openosrs/externals/add_icon.png rename to runelite-client/src/main/resources/net/runelite/client/plugins/openosrs/externals/add_icon.png diff --git a/runelite-client/src/main/resources/com/openosrs/client/plugins/openosrs/externals/add_raw_icon.png b/runelite-client/src/main/resources/net/runelite/client/plugins/openosrs/externals/add_raw_icon.png similarity index 100% rename from runelite-client/src/main/resources/com/openosrs/client/plugins/openosrs/externals/add_raw_icon.png rename to runelite-client/src/main/resources/net/runelite/client/plugins/openosrs/externals/add_raw_icon.png diff --git a/runelite-client/src/main/resources/com/openosrs/client/plugins/openosrs/externals/delete_icon.png b/runelite-client/src/main/resources/net/runelite/client/plugins/openosrs/externals/delete_icon.png similarity index 100% rename from runelite-client/src/main/resources/com/openosrs/client/plugins/openosrs/externals/delete_icon.png rename to runelite-client/src/main/resources/net/runelite/client/plugins/openosrs/externals/delete_icon.png diff --git a/runelite-client/src/main/resources/com/openosrs/client/plugins/openosrs/externals/discord_icon.png b/runelite-client/src/main/resources/net/runelite/client/plugins/openosrs/externals/discord_icon.png similarity index 100% rename from runelite-client/src/main/resources/com/openosrs/client/plugins/openosrs/externals/discord_icon.png rename to runelite-client/src/main/resources/net/runelite/client/plugins/openosrs/externals/discord_icon.png diff --git a/runelite-client/src/main/resources/com/openosrs/client/plugins/openosrs/externals/gh_icon.png b/runelite-client/src/main/resources/net/runelite/client/plugins/openosrs/externals/gh_icon.png similarity index 100% rename from runelite-client/src/main/resources/com/openosrs/client/plugins/openosrs/externals/gh_icon.png rename to runelite-client/src/main/resources/net/runelite/client/plugins/openosrs/externals/gh_icon.png diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/timetracking/notify_icon.png b/runelite-client/src/main/resources/net/runelite/client/plugins/timetracking/notify_icon.png new file mode 100644 index 0000000000..4a4667bedb Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/timetracking/notify_icon.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/timetracking/notify_selected_icon.png b/runelite-client/src/main/resources/net/runelite/client/plugins/timetracking/notify_selected_icon.png new file mode 100644 index 0000000000..1fee9d1f8d Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/timetracking/notify_selected_icon.png differ diff --git a/runelite-client/src/main/resources/openosrs.properties b/runelite-client/src/main/resources/openosrs.properties new file mode 100644 index 0000000000..ad6f017739 --- /dev/null +++ b/runelite-client/src/main/resources/openosrs.properties @@ -0,0 +1 @@ +oprs.version=@open.osrs.version@ \ No newline at end of file diff --git a/runelite-client/src/main/scripts/NewOptionsPanelZoomListener.hash b/runelite-client/src/main/scripts/NewOptionsPanelZoomListener.hash new file mode 100644 index 0000000000..83a3a4c586 --- /dev/null +++ b/runelite-client/src/main/scripts/NewOptionsPanelZoomListener.hash @@ -0,0 +1 @@ +5464D17DCD348F352EFFE6AA6AEEC5A5609ECBA30EAC2CB2B3D479D2C0DDDA9A \ No newline at end of file diff --git a/runelite-client/src/main/scripts/NewOptionsPanelZoomListener.rs2asm b/runelite-client/src/main/scripts/NewOptionsPanelZoomListener.rs2asm new file mode 100644 index 0000000000..1763832ed6 --- /dev/null +++ b/runelite-client/src/main/scripts/NewOptionsPanelZoomListener.rs2asm @@ -0,0 +1,75 @@ +.id 3898 +.int_stack_count 6 +.string_stack_count 0 +.int_var_count 11 +.string_var_count 0 + get_varbit 4606 + iconst 0 + if_icmpne LABEL4 + jump LABEL5 +LABEL4: + return +LABEL5: + iconst 512 + istore 6 + iconst 512 + istore 7 + iload 2 + iconst 16 + sub + istore 8 + iconst 0 + iload 3 + invoke 1045 + istore 3 + iload 2 + iconst 16 + sub + iload 3 + invoke 1046 + istore 3 + iconst 896 + sconst "innerZoomLimit" + runelite_callback + iconst 128 + sconst "outerZoomLimit" + runelite_callback + sub + istore 9 + iconst 896 + sconst "innerZoomLimit" + runelite_callback + iconst 128 + sconst "outerZoomLimit" + runelite_callback + sub + istore 10 + iload 3 + iload 9 + multiply + iload 8 + div + iconst 128 + sconst "outerZoomLimit" + runelite_callback + add + istore 6 + iload 3 + iload 10 + multiply + iload 8 + div + iconst 128 + sconst "outerZoomLimit" + runelite_callback + add + istore 7 + iload 0 + iload 1 + iload 7 + iload 6 + iload 2 + iload 4 + iload 5 + invoke 3899 + return diff --git a/runelite-client/src/main/scripts/NewOptionsPanelZoomSetter.hash b/runelite-client/src/main/scripts/NewOptionsPanelZoomSetter.hash new file mode 100644 index 0000000000..e6ff467a74 --- /dev/null +++ b/runelite-client/src/main/scripts/NewOptionsPanelZoomSetter.hash @@ -0,0 +1 @@ +AA98471D04D9CB1172253D0B479EFD2D58394BDD2852F3AE8CD2B2D46FA826C3 \ No newline at end of file diff --git a/runelite-client/src/main/scripts/NewOptionsPanelZoomSetter.rs2asm b/runelite-client/src/main/scripts/NewOptionsPanelZoomSetter.rs2asm new file mode 100644 index 0000000000..aef3b1ab39 --- /dev/null +++ b/runelite-client/src/main/scripts/NewOptionsPanelZoomSetter.rs2asm @@ -0,0 +1,96 @@ +.id 3899 +.int_stack_count 7 +.string_stack_count 0 +.int_var_count 11 +.string_var_count 0 + get_varbit 4606 + iconst 0 + if_icmpne LABEL4 + jump LABEL5 +LABEL4: + return +LABEL5: + iconst 896 + sconst "innerZoomLimit" + runelite_callback + iload 2 + invoke 1046 + istore 2 + iconst 128 + sconst "outerZoomLimit" + runelite_callback + iload 2 + invoke 1045 + istore 2 + iconst 896 + sconst "innerZoomLimit" + runelite_callback + iload 3 + invoke 1046 + istore 3 + iconst 128 + sconst "outerZoomLimit" + runelite_callback + iload 3 + invoke 1045 + istore 3 + iload 2 + iload 3 + viewport_setfov + iconst 0 + istore 7 + iconst 0 + istore 8 + viewport_geteffectivesize + istore 8 + istore 7 + iload 8 + iconst 334 + sub + istore 9 + iload 9 + iconst 0 + if_icmplt LABEL39 + jump LABEL42 +LABEL39: + iconst 0 + istore 9 + jump LABEL48 +LABEL42: + iload 9 + iconst 100 + if_icmpgt LABEL46 + jump LABEL48 +LABEL46: + iconst 100 + istore 9 +LABEL48: + iload 2 + iload 3 + iload 2 + sub + iload 9 + multiply + iconst 100 + div + add + istore 10 + iconst 25 + iconst 25 + iload 10 + multiply + iconst 256 + div + add + cam_setfollowheight + iload 2 + iload 3 + set_varc_int 74 + set_varc_int 73 + iload 0 + iload 1 + iload 4 + iload 5 + iload 6 + invoke 3900 + return diff --git a/runelite-client/src/main/scripts/NewOptionsPanelZoomSlider.hash b/runelite-client/src/main/scripts/NewOptionsPanelZoomSlider.hash new file mode 100644 index 0000000000..6b984c313e --- /dev/null +++ b/runelite-client/src/main/scripts/NewOptionsPanelZoomSlider.hash @@ -0,0 +1 @@ +03D7F1AF9E8405CB4A74779254E8C65563123F865CC0181186238B038A740755 \ No newline at end of file diff --git a/runelite-client/src/main/scripts/NewOptionsPanelZoomSlider.rs2asm b/runelite-client/src/main/scripts/NewOptionsPanelZoomSlider.rs2asm new file mode 100644 index 0000000000..84406d0edc --- /dev/null +++ b/runelite-client/src/main/scripts/NewOptionsPanelZoomSlider.rs2asm @@ -0,0 +1,78 @@ +.id 3900 +.int_stack_count 5 +.string_stack_count 0 +.int_var_count 11 +.string_var_count 0 + iconst 896 + sconst "innerZoomLimit" + runelite_callback + iconst 128 + sconst "outerZoomLimit" + runelite_callback + sub + istore 5 + iconst 896 + sconst "innerZoomLimit" + runelite_callback + iconst 128 + sconst "outerZoomLimit" + runelite_callback + sub + istore 6 + iload 2 + iconst 16 + sub + istore 7 + iconst 0 + istore 8 + iconst 0 + istore 9 + viewport_geteffectivesize + istore 9 + istore 8 + iconst 0 + istore 10 + iload 8 + iconst 334 + if_icmpgt LABEL25 + jump LABEL34 +LABEL25: + get_varc_int 74 + iconst 128 + sconst "outerZoomLimit" + runelite_callback + sub + iload 7 + multiply + iload 5 + div + istore 10 + jump LABEL42 +LABEL34: + get_varc_int 73 + iconst 128 + sconst "outerZoomLimit" + runelite_callback + sub + iload 7 + multiply + iload 6 + div + istore 10 +LABEL42: + iload 0 + iload 1 + cc_find + iconst 1 + if_icmpeq LABEL48 + jump LABEL55 +LABEL48: + iload 4 + iload 10 + add + iload 3 + iconst 0 + iconst 0 + cc_setposition +LABEL55: + return diff --git a/runelite-client/src/main/scripts/OptionsPanelZoomUpdater.hash b/runelite-client/src/main/scripts/OptionsPanelZoomUpdater.hash new file mode 100644 index 0000000000..1f6beef765 --- /dev/null +++ b/runelite-client/src/main/scripts/OptionsPanelZoomUpdater.hash @@ -0,0 +1 @@ +A1B6D1B291AA3594728DDEA47049E17119F5CCB6F8E757E1524FA89DE92F9A34 \ No newline at end of file diff --git a/runelite-client/src/test/java/net/runelite/client/chat/ChatMessageManagerTest.java b/runelite-client/src/test/java/net/runelite/client/chat/ChatMessageManagerTest.java new file mode 100644 index 0000000000..b75c79b277 --- /dev/null +++ b/runelite-client/src/test/java/net/runelite/client/chat/ChatMessageManagerTest.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2019, Adam + * 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.chat; + +import com.google.inject.Guice; +import com.google.inject.Inject; +import com.google.inject.testing.fieldbinder.Bind; +import com.google.inject.testing.fieldbinder.BoundFieldModule; +import java.awt.Color; +import net.runelite.api.ChatMessageType; +import net.runelite.api.Client; +import net.runelite.api.MessageNode; +import net.runelite.api.Player; +import net.runelite.api.events.ChatMessage; +import net.runelite.client.config.ChatColorConfig; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class ChatMessageManagerTest +{ + @Mock + @Bind + private Client client; + + @Mock + @Bind + private ChatColorConfig chatColorConfig; + + @Inject + private ChatMessageManager chatMessageManager; + + @Before + public void before() + { + Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); + + chatMessageManager.loadColors(); + } + + @Test + public void testMessageRecoloring() + { + when(chatColorConfig.opaqueServerMessage()).thenReturn(Color.decode("#b20000")); + + chatMessageManager.loadColors(); + + ChatMessage chatMessage = new ChatMessage(); + chatMessage.setType(ChatMessageType.GAMEMESSAGE); + + MessageNode messageNode = mock(MessageNode.class); + chatMessage.setMessageNode(messageNode); + + when(messageNode.getValue()).thenReturn("Your dodgy necklace protects you. It has 1 charge left."); + chatMessageManager.onChatMessage(chatMessage); + + verify(messageNode).setValue("Your dodgy necklace protects you. It has 1 charge left."); + } + + @Test + public void testPublicFriendUsernameRecolouring() + { + final String localPlayerName = "RuneLite"; + final String friendName = "Zezima"; + + when(chatColorConfig.opaquePublicFriendUsernames()).thenReturn(Color.decode("#b20000")); + + chatMessageManager.loadColors(); + + // Setup message + ChatMessage chatMessage = new ChatMessage(); + chatMessage.setType(ChatMessageType.PUBLICCHAT); + chatMessage.setName(friendName); + + MessageNode messageNode = mock(MessageNode.class); + chatMessage.setMessageNode(messageNode); + when(messageNode.getName()).thenReturn(friendName); + + // Setup friend checking + Player localPlayer = mock(Player.class); + + when(client.isFriended(friendName, true)).thenReturn(true); + when(client.getLocalPlayer()).thenReturn(localPlayer); + when(localPlayer.getName()).thenReturn(localPlayerName); + + chatMessageManager.onChatMessage(chatMessage); + + verify(messageNode).setName("" + friendName + ""); + } + + @Test + public void testPublicIronmanFriendUsernameRecolouring() + { + final String localPlayerName = "RuneLite"; + final String friendName = "BuddhaPuck"; + final String sanitizedFriendName = "BuddhaPuck"; + + when(chatColorConfig.opaquePublicFriendUsernames()).thenReturn(Color.decode("#b20000")); + + chatMessageManager.loadColors(); + + // Setup message + ChatMessage chatMessage = new ChatMessage(); + chatMessage.setType(ChatMessageType.PUBLICCHAT); + chatMessage.setName(friendName); + + MessageNode messageNode = mock(MessageNode.class); + chatMessage.setMessageNode(messageNode); + when(messageNode.getName()).thenReturn(friendName); + + // Setup friend checking + Player localPlayer = mock(Player.class); + + when(client.isFriended(sanitizedFriendName, true)).thenReturn(true); + when(client.getLocalPlayer()).thenReturn(localPlayer); + when(localPlayer.getName()).thenReturn(localPlayerName); + + chatMessageManager.onChatMessage(chatMessage); + + verify(messageNode).setName("" + friendName + ""); + } +} \ No newline at end of file diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/chatcommands/ChatCommandsPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/chatcommands/ChatCommandsPluginTest.java new file mode 100644 index 0000000000..5792a72679 --- /dev/null +++ b/runelite-client/src/test/java/net/runelite/client/plugins/chatcommands/ChatCommandsPluginTest.java @@ -0,0 +1,663 @@ +/* + * Copyright (c) 2018, Adam + * 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.chatcommands; + +import com.google.common.collect.Sets; +import com.google.inject.Guice; +import com.google.inject.testing.fieldbinder.Bind; +import com.google.inject.testing.fieldbinder.BoundFieldModule; +import java.io.IOException; +import java.util.concurrent.ScheduledExecutorService; +import javax.inject.Inject; +import net.runelite.api.ChatMessageType; +import static net.runelite.api.ChatMessageType.FRIENDSCHATNOTIFICATION; +import static net.runelite.api.ChatMessageType.GAMEMESSAGE; +import static net.runelite.api.ChatMessageType.TRADE; +import net.runelite.api.Client; +import net.runelite.api.MessageNode; +import net.runelite.api.Player; +import net.runelite.api.events.ChatMessage; +import net.runelite.api.events.GameTick; +import net.runelite.api.events.WidgetLoaded; +import net.runelite.api.widgets.Widget; +import static net.runelite.api.widgets.WidgetID.ADVENTURE_LOG_ID; +import static net.runelite.api.widgets.WidgetID.GENERIC_SCROLL_GROUP_ID; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.chat.ChatCommandManager; +import net.runelite.client.chat.ChatMessageManager; +import net.runelite.client.config.ChatColorConfig; +import net.runelite.client.config.ConfigManager; +import net.runelite.http.api.chat.ChatClient; +import net.runelite.http.api.hiscore.HiscoreClient; +import net.runelite.http.api.hiscore.HiscoreSkill; +import net.runelite.http.api.hiscore.SingleHiscoreSkillResult; +import net.runelite.http.api.hiscore.Skill; +import static org.junit.Assert.assertEquals; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class ChatCommandsPluginTest +{ + private static final String PLAYER_NAME = "Adam"; + + @Mock + @Bind + Client client; + + @Mock + @Bind + ConfigManager configManager; + + @Mock + @Bind + ScheduledExecutorService scheduledExecutorService; + + @Mock + @Bind + ChatColorConfig chatColorConfig; + + @Mock + @Bind + ChatCommandManager chatCommandManager; + + @Mock + @Bind + HiscoreClient hiscoreClient; + + @Mock + @Bind + ChatMessageManager chatMessageManager; + + @Mock + @Bind + ChatClient chatClient; + + @Mock + @Bind + ChatCommandsConfig chatCommandsConfig; + + @Inject + ChatCommandsPlugin chatCommandsPlugin; + + @Before + public void before() + { + Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); + + Player player = mock(Player.class); + when(player.getName()).thenReturn(PLAYER_NAME); + when(client.getLocalPlayer()).thenReturn(player); + } + + @Test + public void testStartupShutdown() + { + chatCommandsPlugin.startUp(); + chatCommandsPlugin.shutDown(); + + ArgumentCaptor registerCaptor = ArgumentCaptor.forClass(String.class); + verify(chatCommandManager, atLeastOnce()).registerCommand(registerCaptor.capture(), any()); + verify(chatCommandManager, atLeastOnce()).registerCommandAsync(registerCaptor.capture(), any()); + verify(chatCommandManager, atLeastOnce()).registerCommandAsync(registerCaptor.capture(), any(), any()); + + ArgumentCaptor unregisterCaptor = ArgumentCaptor.forClass(String.class); + verify(chatCommandManager, atLeastOnce()).unregisterCommand(unregisterCaptor.capture()); + + assertEquals(Sets.newHashSet(registerCaptor.getAllValues()), Sets.newHashSet(unregisterCaptor.getAllValues())); + } + + @Test + public void testCorporealBeastKill() + { + ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", "Your Corporeal Beast kill count is: 4.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessageEvent); + + verify(configManager).setRSProfileConfiguration("killcount", "corporeal beast", 4); + } + + @Test + public void testTheatreOfBlood() + { + ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Wave 'The Final Challenge' complete! Duration: 5:04
Theatre of Blood wave completion time: 37:04 (Personal best!)", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", "Your completed Theatre of Blood count is: 73.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessageEvent); + + verify(configManager).setRSProfileConfiguration("killcount", "theatre of blood", 73); + verify(configManager).setRSProfileConfiguration("personalbest", "theatre of blood", 37 * 60 + 4); + } + + @Test + public void testTheatreOfBloodNoPb() + { + ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Wave 'The Final Challenge' complete! Duration: 5:04
Theatre of Blood wave completion time: 38:17
Personal best: 37:04", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", "Your completed Theatre of Blood count is: 73.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessageEvent); + + verify(configManager).setRSProfileConfiguration("killcount", "theatre of blood", 73); + verify(configManager).setRSProfileConfiguration("personalbest", "theatre of blood", 37 * 60 + 4); + } + + @Test + public void testWintertodt() + { + ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", "Your subdued Wintertodt count is: 4.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessageEvent); + + verify(configManager).setRSProfileConfiguration("killcount", "wintertodt", 4); + } + + @Test + public void testKreearra() + { + ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", "Your Kree'arra kill count is: 4.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessageEvent); + + verify(configManager).setRSProfileConfiguration("killcount", "kree'arra", 4); + } + + @Test + public void testBarrows() + { + ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", "Your Barrows chest count is: 277.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessageEvent); + + verify(configManager).setRSProfileConfiguration("killcount", "barrows chests", 277); + } + + @Test + public void testHerbiboar() + { + ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", "Your herbiboar harvest count is: 4091.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessageEvent); + + verify(configManager).setRSProfileConfiguration("killcount", "herbiboar", 4091); + } + + @Test + public void testGauntlet() + { + ChatMessage gauntletMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Gauntlet completion count is: 123.", null, 0); + chatCommandsPlugin.onChatMessage(gauntletMessage); + + verify(configManager).setRSProfileConfiguration("killcount", "gauntlet", 123); + } + + @Test + public void testCorruptedGauntlet() + { + ChatMessage corruptedGauntletMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Corrupted Gauntlet completion count is: 4729.", null, 0); + chatCommandsPlugin.onChatMessage(corruptedGauntletMessage); + + verify(configManager).setRSProfileConfiguration("killcount", "corrupted gauntlet", 4729); + } + + @Test + public void testPersonalBest() + { + final String FIGHT_DURATION = "Fight duration: 2:06. Personal best: 1:19."; + + // This sets lastBoss + ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Kree'arra kill count is: 4.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + chatMessage = new ChatMessage(null, GAMEMESSAGE, "", FIGHT_DURATION, null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + verify(configManager).setRSProfileConfiguration("personalbest", "kree'arra", 79); + } + + @Test + public void testPersonalBestNoTrailingPeriod() + { + final String FIGHT_DURATION = "Fight duration: 0:59. Personal best: 0:55"; + + // This sets lastBoss + ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Zulrah kill count is: 4.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + chatMessage = new ChatMessage(null, GAMEMESSAGE, "", FIGHT_DURATION, null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + verify(configManager).setRSProfileConfiguration("personalbest", "zulrah", 55); + } + + @Test + public void testNewPersonalBest() + { + final String NEW_PB = "Fight duration: 3:01 (new personal best)."; + + // This sets lastBoss + ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Kree'arra kill count is: 4.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + chatMessage = new ChatMessage(null, GAMEMESSAGE, "", NEW_PB, null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + verify(configManager).setRSProfileConfiguration("personalbest", "kree'arra", 181); + } + + @Test + public void testDuelArenaWin() + { + ChatMessage chatMessageEvent = new ChatMessage(null, TRADE, "", "You won! You have now won 27 duels.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessageEvent); + + verify(configManager).setRSProfileConfiguration("killcount", "duel arena wins", 27); + verify(configManager).setRSProfileConfiguration("killcount", "duel arena win streak", 1); + } + + @Test + public void testDuelArenaWin2() + { + ChatMessage chatMessageEvent = new ChatMessage(null, TRADE, "", "You were defeated! You have won 22 duels.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessageEvent); + + verify(configManager).setRSProfileConfiguration("killcount", "duel arena wins", 22); + } + + @Test + public void testDuelArenaLose() + { + ChatMessage chatMessageEvent = new ChatMessage(null, TRADE, "", "You have now lost 999 duels.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessageEvent); + + verify(configManager).setRSProfileConfiguration("killcount", "duel arena losses", 999); + } + + @Test + public void testAgilityLap() + { + final String NEW_PB = "Lap duration: 1:01 (new personal best)."; + + // This sets lastBoss + ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Prifddinas Agility Course lap count is: 2.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + chatMessage = new ChatMessage(null, GAMEMESSAGE, "", NEW_PB, null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + verify(configManager).setRSProfileConfiguration("personalbest", "prifddinas agility course", 61); + verify(configManager).setRSProfileConfiguration("killcount", "prifddinas agility course", 2); + } + + @Test + public void testZukNewPb() + { + ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your TzKal-Zuk kill count is: 2.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Duration: 104:31 (new personal best)", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + verify(configManager).setRSProfileConfiguration("personalbest", "tzkal-zuk", 104 * 60 + 31); + verify(configManager).setRSProfileConfiguration("killcount", "tzkal-zuk", 2); + } + + @Test + public void testZukKill() + { + ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your TzKal-Zuk kill count is: 3.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Duration: 172:18. Personal best: 134:52", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + verify(configManager).setRSProfileConfiguration("personalbest", "tzkal-zuk", 134 * 60 + 52); + verify(configManager).setRSProfileConfiguration("killcount", "tzkal-zuk", 3); + } + + @Test + public void testGgNewPb() + { + ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Fight duration: 1:36 (new personal best)", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Grotesque Guardians kill count is: 179.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + verify(configManager).setRSProfileConfiguration("personalbest", "grotesque guardians", 96); + verify(configManager).setRSProfileConfiguration("killcount", "grotesque guardians", 179); + } + + @Test + public void testGgKill() + { + ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Fight duration: 2:41. Personal best: 2:14", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Grotesque Guardians kill count is: 32.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + verify(configManager).setRSProfileConfiguration("personalbest", "grotesque guardians", 2 * 60 + 14); + verify(configManager).setRSProfileConfiguration("killcount", "grotesque guardians", 32); + } + + @Test + public void testGuantletPersonalBest() + { + ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Challenge duration: 10:24. Personal best: 7:59.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Gauntlet completion count is: 124.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + verify(configManager).setRSProfileConfiguration("killcount", "gauntlet", 124); + verify(configManager).setRSProfileConfiguration("personalbest", "gauntlet", 7 * 60 + 59); + } + + @Test + public void testGuantletNewPersonalBest() + { + ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Challenge duration: 10:24 (new personal best).", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Gauntlet completion count is: 124.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + verify(configManager).setRSProfileConfiguration("personalbest", "gauntlet", 10 * 60 + 24); + verify(configManager).setRSProfileConfiguration("killcount", "gauntlet", 124); + } + + @Test + public void testCoXKill() + { + ChatMessage chatMessage = new ChatMessage(null, FRIENDSCHATNOTIFICATION, "", "Congratulations - your raid is complete!
Team size: 24+ players Duration: 37:04 (new personal best)>", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your completed Chambers of Xeric count is: 51.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + verify(configManager).setRSProfileConfiguration("killcount", "chambers of xeric", 51); + verify(configManager).setRSProfileConfiguration("personalbest", "chambers of xeric", 37 * 60 + 4); + } + + @Test + public void testCoXKillNoPb() + { + ChatMessage chatMessage = new ChatMessage(null, FRIENDSCHATNOTIFICATION, "", "Congratulations - your raid is complete!
Team size: 11-15 players Duration: 23:25 Personal best: 20:19", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your completed Chambers of Xeric count is: 52.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + verify(configManager).setRSProfileConfiguration("killcount", "chambers of xeric", 52); + verify(configManager).setRSProfileConfiguration("personalbest", "chambers of xeric", 20 * 60 + 19); + } + + @Test + public void testAdventureLogCountersPage() + { + Widget advLogWidget = mock(Widget.class); + Widget advLogExploitsTextWidget = mock(Widget.class); + when(advLogWidget.getChild(ChatCommandsPlugin.ADV_LOG_EXPLOITS_TEXT_INDEX)).thenReturn(advLogExploitsTextWidget); + when(advLogExploitsTextWidget.getText()).thenReturn("The Exploits of " + PLAYER_NAME); + when(client.getWidget(WidgetInfo.ADVENTURE_LOG)).thenReturn(advLogWidget); + when(configManager.getRSProfileConfiguration(anyString(), anyString(), any(Class.class))).thenReturn(2224); + + WidgetLoaded advLogEvent = new WidgetLoaded(); + advLogEvent.setGroupId(ADVENTURE_LOG_ID); + chatCommandsPlugin.onWidgetLoaded(advLogEvent); + chatCommandsPlugin.onGameTick(new GameTick()); + + String COUNTER_TEXT = "Duel Arena
Wins: 4
Losses: 2" + + "

Last Man Standing
Rank: 0" + + "

Treasure Trails
Beginner: 0
Easy: 7" + + "
Medium: 28
Hard: 108
Elite: 15" + + "
Master: 27
Rank: Novice" + + "

Chompy Hunting
Kills: 1,000
Rank: Ogre Expert" + + "

Order of the White Knights
Rank: Master
with a kill score of 1,300" + + "

TzHaar Fight Cave
Fastest run: 38:10" + + "

Inferno
Fastest run: -

Zulrah
" + + "Fastest kill: 5:48

Vorkath
Fastest kill: 1:21" + + "

Galvek
Fastest kill: -

Grotesque Guardians
" + + "Fastest kill: 2:49

Alchemical Hydra
Fastest kill: -" + + "

Hespori
Fastest kill: 0:57

Nightmare
" + + "Fastest kill: 3:30

The Gauntlet
Fastest run: -" + + "

The Corrupted Gauntlet
Fastest run: -

Fragment of Seren
Fastest kill: -" + + "

Chambers of Xeric
Fastest run - (Team size: 24+ players): 24:17" + + "

Chambers of Xeric - Challenge mode
Fastest run - (Team size: Solo): 22:15" + + "

Barbarian Assault
High-level gambles: 0

Fremennik spirits rested: 0"; + + Widget countersPage = mock(Widget.class); + when(countersPage.getText()).thenReturn(COUNTER_TEXT); + when(client.getWidget(WidgetInfo.GENERIC_SCROLL_TEXT)).thenReturn(countersPage); + + WidgetLoaded countersLogEvent = new WidgetLoaded(); + countersLogEvent.setGroupId(GENERIC_SCROLL_GROUP_ID); + chatCommandsPlugin.onWidgetLoaded(countersLogEvent); + chatCommandsPlugin.onGameTick(new GameTick()); + + verify(configManager).setRSProfileConfiguration("personalbest", "tztok-jad", 38 * 60 + 10); + verify(configManager).setRSProfileConfiguration("personalbest", "zulrah", 5 * 60 + 48); + verify(configManager).setRSProfileConfiguration("personalbest", "vorkath", 1 * 60 + 21); + verify(configManager).setRSProfileConfiguration("personalbest", "grotesque guardians", 2 * 60 + 49); + verify(configManager).setRSProfileConfiguration("personalbest", "hespori", 57); + verify(configManager).setRSProfileConfiguration("personalbest", "nightmare", 3 * 60 + 30); + verify(configManager).setRSProfileConfiguration("personalbest", "chambers of xeric", 24 * 60 + 17); + verify(configManager).setRSProfileConfiguration("personalbest", "chambers of xeric challenge mode", 22 * 60 + 15); + } + + @Test + public void testAdventurerLogCountersPage2() + { + Widget advLogWidget = mock(Widget.class); + Widget advLogExploitsTextWidget = mock(Widget.class); + when(advLogWidget.getChild(ChatCommandsPlugin.ADV_LOG_EXPLOITS_TEXT_INDEX)).thenReturn(advLogExploitsTextWidget); + when(advLogExploitsTextWidget.getText()).thenReturn("The Exploits of " + PLAYER_NAME); + when(client.getWidget(WidgetInfo.ADVENTURE_LOG)).thenReturn(advLogWidget); + + WidgetLoaded advLogEvent = new WidgetLoaded(); + advLogEvent.setGroupId(ADVENTURE_LOG_ID); + chatCommandsPlugin.onWidgetLoaded(advLogEvent); + chatCommandsPlugin.onGameTick(new GameTick()); + + String COUNTER_TEXT = "Duel Arena
Wins: 12
Losses: 20" + + "

Last Man Standing
Rank: 0" + + "

Treasure Trails
Beginner: 1
Easy: 4" + + "
Medium: 35
Hard: 66
Elite: 2" + + "
Master: 0
Rank: Novice" + + "

Chompy Hunting
Kills: 300
Rank: Ogre Forester" + + "

Order of the White Knights
Rank: Unrated
with a kill score of 99" + + "

TzHaar Fight Cave
Fastest run: 65:12" + + "

Inferno
Fastest run: -

Zulrah
" + + "Fastest kill: 2:55

Vorkath
Fastest kill: 1:37" + + "

Galvek
Fastest kill: -

Grotesque Guardians
" + + "Fastest kill: -

Alchemical Hydra
Fastest kill: -" + + "

Hespori
Fastest kill: 1:42

Nightmare
" + + "Fastest kill: -

The Gauntlet
Fastest run: -" + + "

The Corrupted Gauntlet
Fastest run: -

Fragment of Seren
Fastest kill: -" + + "

Chambers of Xeric
Fastest run - (Team size: Solo): 21:23
Fastest run - (Team size: 3 players): 27:16" + + "

Chambers of Xeric - Challenge mode
Fastest run - (Team size: Solo): 34:30
Fastest run - (Team size: 4 players): 21:26" + + "

Barbarian Assault
High-level gambles: 0

Fremennik spirits rested: 0"; + + Widget countersPage = mock(Widget.class); + when(countersPage.getText()).thenReturn(COUNTER_TEXT); + when(client.getWidget(WidgetInfo.GENERIC_SCROLL_TEXT)).thenReturn(countersPage); + + WidgetLoaded countersLogEvent = new WidgetLoaded(); + countersLogEvent.setGroupId(GENERIC_SCROLL_GROUP_ID); + chatCommandsPlugin.onWidgetLoaded(countersLogEvent); + chatCommandsPlugin.onGameTick(new GameTick()); + + verify(configManager).setRSProfileConfiguration("personalbest", "tztok-jad", 65 * 60 + 12); + verify(configManager).setRSProfileConfiguration("personalbest", "zulrah", 2 * 60 + 55); + verify(configManager).setRSProfileConfiguration("personalbest", "vorkath", 1 * 60 + 37); + verify(configManager).setRSProfileConfiguration("personalbest", "hespori", 1 * 60 + 42); + verify(configManager).setRSProfileConfiguration("personalbest", "chambers of xeric", 21 * 60 + 23); + verify(configManager).setRSProfileConfiguration("personalbest", "chambers of xeric challenge mode", 21 * 60 + 26); + } + + @Test + public void testNotYourAdventureLogCountersPage() + { + Widget advLogWidget = mock(Widget.class); + Widget advLogExploitsTextWidget = mock(Widget.class); + when(advLogWidget.getChild(ChatCommandsPlugin.ADV_LOG_EXPLOITS_TEXT_INDEX)).thenReturn(advLogExploitsTextWidget); + when(advLogExploitsTextWidget.getText()).thenReturn("The Exploits of " + "not the player"); + when(client.getWidget(WidgetInfo.ADVENTURE_LOG)).thenReturn(advLogWidget); + + WidgetLoaded advLogEvent = new WidgetLoaded(); + advLogEvent.setGroupId(ADVENTURE_LOG_ID); + chatCommandsPlugin.onWidgetLoaded(advLogEvent); + chatCommandsPlugin.onGameTick(new GameTick()); + + WidgetLoaded countersLogEvent = new WidgetLoaded(); + countersLogEvent.setGroupId(GENERIC_SCROLL_GROUP_ID); + chatCommandsPlugin.onWidgetLoaded(countersLogEvent); + chatCommandsPlugin.onGameTick(new GameTick()); + + verifyNoMoreInteractions(configManager); + } + + @Test + public void testPlayerSkillLookup() throws IOException + { + when(chatCommandsConfig.lvl()).thenReturn(true); + + SingleHiscoreSkillResult skillResult = new SingleHiscoreSkillResult(); + skillResult.setPlayer(PLAYER_NAME); + skillResult.setSkill(new Skill(10, 1000, -1)); + + when(hiscoreClient.lookup(PLAYER_NAME, HiscoreSkill.ZULRAH, null)).thenReturn(skillResult); + + MessageNode messageNode = mock(MessageNode.class); + + ChatMessage chatMessage = new ChatMessage(); + chatMessage.setType(ChatMessageType.PUBLICCHAT); + chatMessage.setName(PLAYER_NAME); + chatMessage.setMessageNode(messageNode); + chatCommandsPlugin.playerSkillLookup(chatMessage, "!lvl zulrah"); + + verify(messageNode).setRuneLiteFormatMessage("Level Zulrah: 1000 Rank: 10"); + } + + @Test + public void testHsFloorNoPb() + { + ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Floor 1 time: 1:19. Personal best: 0:28", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre floor 1", 28); + } + + @Test + public void testHsFloorPb() + { + ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Floor 2 time: 0:47 (new personal best)", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre floor 2", 47); + } + + @Test + public void testHsOverallPb_Pb() + { + ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Floor 5 time: 4:46 (new personal best)
Overall time: 9:53 (new personal best)
", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre floor 5", 4 * 60 + 46); + verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre", 9 * 60 + 53); + } + + @Test + public void testHsOverallPb_NoPb() + { + ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Floor 5 time: 3:26 (new personal best)
Overall time: 9:17. Personal best: 9:15
", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre floor 5", 3 * 60 + 26); + verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre", 9 * 60 + 15); + } + + @Test + public void testHsOverallNoPb_NoPb() + { + ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Floor 5 time: 3:56. Personal best: 3:05
Overall time: 9:14. Personal best: 7:49
", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre floor 5", 3 * 60 + 5); + verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre", 7 * 60 + 49); + } + + @Test + public void testHsOverallNoPb_Pb() + { + ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Floor 5 time: 3:10. Personal best: 3:04
Overall time: 7:47 (new personal best)
", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre floor 5", 3 * 60 + 4); + verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre", 7 * 60 + 47); + } + + @Test + public void testHsFloorKc() + { + ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "You have completed Floor 5 of the Hallowed Sepulchre! Total completions: 81.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + verify(configManager).setRSProfileConfiguration("killcount", "hallowed sepulchre floor 5", 81); + } + + @Test + public void testHsGhcKc() + { + ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "You have opened the Grand Hallowed Coffin 36 times!", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + verify(configManager).setRSProfileConfiguration("killcount", "hallowed sepulchre", 36); + } + + @Test + public void testJadNewPbWithLeagueTask() + { + ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your TzTok-Jad kill count is: 2.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Congratulations, you've completed a master task: Complete the Fight Caves in 25:00.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Duration: 21:58 (new personal best)", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + verify(configManager).setRSProfileConfiguration("personalbest", "tztok-jad", 21 * 60 + 58); + verify(configManager).setRSProfileConfiguration("killcount", "tztok-jad", 2); + } +} diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/chatfilter/ChatFilterPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/chatfilter/ChatFilterPluginTest.java new file mode 100644 index 0000000000..f12ae93e4a --- /dev/null +++ b/runelite-client/src/test/java/net/runelite/client/plugins/chatfilter/ChatFilterPluginTest.java @@ -0,0 +1,424 @@ +/* + * Copyright (c) 2019, Adam + * Copyright (c) 2019, osrs-music-map + * 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.chatfilter; + +import com.google.inject.Guice; +import com.google.inject.testing.fieldbinder.Bind; +import com.google.inject.testing.fieldbinder.BoundFieldModule; +import javax.inject.Inject; +import net.runelite.api.ChatMessageType; +import net.runelite.api.Client; +import net.runelite.api.IterableHashTable; +import net.runelite.api.MessageNode; +import net.runelite.api.Player; +import net.runelite.api.events.ChatMessage; +import net.runelite.api.events.ScriptCallbackEvent; +import net.runelite.client.game.FriendChatManager; +import static net.runelite.client.plugins.chatfilter.ChatFilterPlugin.CENSOR_MESSAGE; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class ChatFilterPluginTest +{ + @Mock + @Bind + private Client client; + + @Mock + @Bind + private ChatFilterConfig chatFilterConfig; + + @Mock + @Bind + private FriendChatManager friendChatManager; + + @Mock + private Player localPlayer; + + @Inject + private ChatFilterPlugin chatFilterPlugin; + + @Before + public void before() + { + Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); + + when(chatFilterConfig.filterType()).thenReturn(ChatFilterType.CENSOR_WORDS); + when(chatFilterConfig.filteredWords()).thenReturn(""); + when(chatFilterConfig.filteredRegex()).thenReturn(""); + when(chatFilterConfig.filteredNames()).thenReturn(""); + when(client.getLocalPlayer()).thenReturn(localPlayer); + } + + private ScriptCallbackEvent createCallbackEvent(final String sender, final String chatMessage, final ChatMessageType messageType) + { + ScriptCallbackEvent event = new ScriptCallbackEvent(); + event.setScript(null); + event.setEventName("chatFilterCheck"); + int[] simulatedIntStack = + new int[]{1, messageType.getType(), 1}; // is msg allowed to show, ChatMessageType.PUBLICCHAT, message id + String[] simulatedStringStack = new String[]{chatMessage}; + IterableHashTable messageTable = mock(IterableHashTable.class); + MessageNode mockedMsgNode = mockMessageNode(sender); + when(client.getIntStack()).thenReturn(simulatedIntStack); + when(client.getIntStackSize()).thenReturn(simulatedIntStack.length); + when(client.getStringStack()).thenReturn(simulatedStringStack); + when(client.getStringStackSize()).thenReturn(simulatedStringStack.length); + when(client.getMessages()).thenReturn(messageTable); + when(messageTable.get(1)).thenReturn(mockedMsgNode); + return event; + } + + private MessageNode mockMessageNode(String sender) + { + MessageNode node = mock(MessageNode.class); + when(node.getName()).thenReturn(sender); + return node; + } + + private MessageNode mockMessageNode(int id) + { + MessageNode node = mock(MessageNode.class); + when(node.getId()).thenReturn(id); + return node; + } + + private MessageNode mockMessageNode(int id, String sender, String value) + { + MessageNode node = mock(MessageNode.class); + when(node.getId()).thenReturn(id); + when(node.getName()).thenReturn(sender); + when(node.getValue()).thenReturn(value); + return node; + } + + @Test + public void testCensorWords() + { + when(chatFilterConfig.filteredWords()).thenReturn("hat"); + + chatFilterPlugin.updateFilteredPatterns(); + assertEquals("w***s up", chatFilterPlugin.censorMessage("Blue", "whats up")); + } + + @Test + public void testCensorRegex() + { + when(chatFilterConfig.filterType()).thenReturn(ChatFilterType.REMOVE_MESSAGE); + when(chatFilterConfig.filteredRegex()).thenReturn("5[0-9]x2\n("); + + chatFilterPlugin.updateFilteredPatterns(); + assertNull(chatFilterPlugin.censorMessage("Blue", "55X2 Dicing | Trusted Ranks | Huge Pay Outs!")); + } + + @Test + public void testBrokenRegex() + { + when(chatFilterConfig.filteredRegex()).thenReturn("Test\n)\n73"); + + chatFilterPlugin.updateFilteredPatterns(); + assertEquals("** isn't funny", chatFilterPlugin.censorMessage("Blue", "73 isn't funny")); + } + + @Test + public void testCaseSensitivity() + { + when(chatFilterConfig.filterType()).thenReturn(ChatFilterType.CENSOR_MESSAGE); + when(chatFilterConfig.filteredWords()).thenReturn("ReGeX!!!"); + + chatFilterPlugin.updateFilteredPatterns(); + assertEquals(CENSOR_MESSAGE, chatFilterPlugin.censorMessage("Blue", "I love regex!!!!!!!!")); + } + + @Test + public void testNonPrintableCharacters() + { + when(chatFilterConfig.filterType()).thenReturn(ChatFilterType.REMOVE_MESSAGE); + when(chatFilterConfig.filteredWords()).thenReturn("test"); + + chatFilterPlugin.updateFilteredPatterns(); + assertNull(chatFilterPlugin.censorMessage("Blue", "te\u008Cst")); + } + + @Test + public void testReplayedMessage() + { + when(chatFilterConfig.filterType()).thenReturn(ChatFilterType.REMOVE_MESSAGE); + when(chatFilterConfig.filteredWords()).thenReturn("hello osrs"); + + chatFilterPlugin.updateFilteredPatterns(); + assertNull(chatFilterPlugin.censorMessage("Blue", "hello\u00A0osrs")); + } + + @Test + public void testMessageFromFriendIsFiltered() + { + when(friendChatManager.isMember("Iron Mammal")).thenReturn(false); + when(chatFilterConfig.filterFriends()).thenReturn(true); + assertTrue(chatFilterPlugin.shouldFilterPlayerMessage("Iron Mammal")); + } + + @Test + public void testMessageFromFriendIsNotFiltered() + { + when(client.isFriended("Iron Mammal", false)).thenReturn(true); + when(chatFilterConfig.filterFriends()).thenReturn(false); + assertFalse(chatFilterPlugin.shouldFilterPlayerMessage("Iron Mammal")); + } + + @Test + public void testMessageFromFriendsChatIsFiltered() + { + when(client.isFriended("B0aty", false)).thenReturn(false); + when(chatFilterConfig.filterFriendsChat()).thenReturn(true); + assertTrue(chatFilterPlugin.shouldFilterPlayerMessage("B0aty")); + } + + @Test + public void testMessageFromFriendsChatIsNotFiltered() + { + when(friendChatManager.isMember("B0aty")).thenReturn(true); + when(chatFilterConfig.filterFriendsChat()).thenReturn(false); + assertFalse(chatFilterPlugin.shouldFilterPlayerMessage("B0aty")); + } + + @Test + public void testMessageFromSelfIsNotFiltered() + { + when(localPlayer.getName()).thenReturn("Swampletics"); + assertFalse(chatFilterPlugin.shouldFilterPlayerMessage("Swampletics")); + } + + @Test + public void testMessageFromNonFriendNonFCIsFiltered() + { + when(client.isFriended("Woox", false)).thenReturn(false); + when(friendChatManager.isMember("Woox")).thenReturn(false); + assertTrue(chatFilterPlugin.shouldFilterPlayerMessage("Woox")); + } + + @Test + public void testShouldFilterByName() + { + when(chatFilterConfig.filteredNames()).thenReturn("Gamble [0-9]*"); + + chatFilterPlugin.updateFilteredPatterns(); + assertTrue(chatFilterPlugin.shouldFilterByName("Gamble 1234")); + assertFalse(chatFilterPlugin.shouldFilterByName("Adam")); + } + + @Test + public void testCensorWordsByName() + { + when(chatFilterConfig.filteredNames()).thenReturn("Blue"); + chatFilterPlugin.updateFilteredPatterns(); + assertEquals("************", chatFilterPlugin.censorMessage("Blue", "Gamble today")); + } + + @Test + public void textCensorMessageByName() + { + when(chatFilterConfig.filteredNames()).thenReturn("Blue"); + chatFilterPlugin.updateFilteredPatterns(); + when(chatFilterConfig.filterType()).thenReturn(ChatFilterType.CENSOR_MESSAGE); + assertEquals(CENSOR_MESSAGE, + chatFilterPlugin.censorMessage("Blue", "Meet swampletics, my morytania locked ultimate ironman")); + } + + @Test + public void testRemoveMessageByName() + { + when(chatFilterConfig.filteredNames()).thenReturn("Blue"); + chatFilterPlugin.updateFilteredPatterns(); + when(chatFilterConfig.filterType()).thenReturn(ChatFilterType.REMOVE_MESSAGE); + assertNull( + chatFilterPlugin.censorMessage("Blue", "What about now it's time to rock with the biggity buck bumble")); + } + + @Test + public void testEventRemoveByName() + { + when(chatFilterConfig.filteredNames()).thenReturn("Gamble [0-9]*"); + when(chatFilterConfig.filterType()).thenReturn(ChatFilterType.REMOVE_MESSAGE); + + chatFilterPlugin.updateFilteredPatterns(); + ScriptCallbackEvent event = createCallbackEvent("Gamble 1234", "filterme", ChatMessageType.PUBLICCHAT); + chatFilterPlugin.onScriptCallbackEvent(event); + assertEquals(0, client.getIntStack()[client.getIntStackSize() - 3]); + } + + @Test + public void testEventRemoveByText() + { + when(chatFilterConfig.filteredWords()).thenReturn("filterme"); + when(chatFilterConfig.filterType()).thenReturn(ChatFilterType.REMOVE_MESSAGE); + + chatFilterPlugin.updateFilteredPatterns(); + ScriptCallbackEvent event = createCallbackEvent("Adam", "please filterme plugin", ChatMessageType.PUBLICCHAT); + chatFilterPlugin.onScriptCallbackEvent(event); + assertEquals(0, client.getIntStack()[client.getIntStackSize() - 3]); + } + + @Test + public void testEventCensorWordsByName() + { + when(chatFilterConfig.filteredNames()).thenReturn("Gamble [0-9]*"); + when(chatFilterConfig.filterType()).thenReturn(ChatFilterType.CENSOR_WORDS); + + chatFilterPlugin.updateFilteredPatterns(); + ScriptCallbackEvent event = createCallbackEvent("Gamble 1234", "filterme", ChatMessageType.PUBLICCHAT); + chatFilterPlugin.onScriptCallbackEvent(event); + assertEquals("********", client.getStringStack()[client.getStringStackSize() - 1]); + } + + @Test + public void testEventCensorWordsByText() + { + when(chatFilterConfig.filteredWords()).thenReturn("filterme"); + when(chatFilterConfig.filterType()).thenReturn(ChatFilterType.CENSOR_WORDS); + + chatFilterPlugin.updateFilteredPatterns(); + ScriptCallbackEvent event = createCallbackEvent("Adam", "please filterme plugin", ChatMessageType.PUBLICCHAT); + chatFilterPlugin.onScriptCallbackEvent(event); + assertEquals("please ******** plugin", client.getStringStack()[client.getStringStackSize() - 1]); + } + + @Test + public void testEventCensorMessageByName() + { + when(chatFilterConfig.filteredNames()).thenReturn("Gamble [0-9]*"); + when(chatFilterConfig.filterType()).thenReturn(ChatFilterType.CENSOR_MESSAGE); + + chatFilterPlugin.updateFilteredPatterns(); + ScriptCallbackEvent event = createCallbackEvent("Gamble 1234", "filterme", ChatMessageType.PUBLICCHAT); + chatFilterPlugin.onScriptCallbackEvent(event); + assertEquals(CENSOR_MESSAGE, client.getStringStack()[client.getStringStackSize() - 1]); + } + + @Test + public void testEventCensorMessageByText() + { + when(chatFilterConfig.filteredWords()).thenReturn("filterme"); + when(chatFilterConfig.filterType()).thenReturn(ChatFilterType.CENSOR_MESSAGE); + + chatFilterPlugin.updateFilteredPatterns(); + ScriptCallbackEvent event = createCallbackEvent("Adam", "please filterme plugin", ChatMessageType.PUBLICCHAT); + chatFilterPlugin.onScriptCallbackEvent(event); + assertEquals(CENSOR_MESSAGE, client.getStringStack()[client.getStringStackSize() - 1]); + } + + @Test + public void testDuplicateChatFiltered() + { + when(chatFilterConfig.collapseGameChat()).thenReturn(true); + chatFilterPlugin.onChatMessage(new ChatMessage(mockMessageNode(0, null, "testMessage"), ChatMessageType.GAMEMESSAGE, null, null, null, 0)); + ScriptCallbackEvent event = createCallbackEvent(null, "testMessage", ChatMessageType.GAMEMESSAGE); + chatFilterPlugin.onScriptCallbackEvent(event); + + assertEquals(0, client.getIntStack()[client.getIntStackSize() - 3]); + } + + @Test + public void testNoDuplicate() + { + when(chatFilterConfig.collapseGameChat()).thenReturn(true); + chatFilterPlugin.onChatMessage(new ChatMessage(mockMessageNode(1), ChatMessageType.GAMEMESSAGE, null, "testMessage", null, 0)); + ScriptCallbackEvent event = createCallbackEvent(null, "testMessage", ChatMessageType.GAMEMESSAGE); + chatFilterPlugin.onScriptCallbackEvent(event); + + assertEquals(1, client.getIntStack()[client.getIntStackSize() - 3]); + assertEquals("testMessage", client.getStringStack()[client.getStringStackSize() - 1]); + } + + @Test + public void testDuplicateChatCount() + { + when(chatFilterConfig.collapseGameChat()).thenReturn(true); + chatFilterPlugin.onChatMessage(new ChatMessage(mockMessageNode(4, null, "testMessage"), ChatMessageType.GAMEMESSAGE, null, null, null, 0)); + chatFilterPlugin.onChatMessage(new ChatMessage(mockMessageNode(3, null, "testMessage"), ChatMessageType.GAMEMESSAGE, null, null, null, 0)); + chatFilterPlugin.onChatMessage(new ChatMessage(mockMessageNode(2, null, "testMessage"), ChatMessageType.GAMEMESSAGE, null, null, null, 0)); + chatFilterPlugin.onChatMessage(new ChatMessage(mockMessageNode(1, null, "testMessage"), ChatMessageType.GAMEMESSAGE, null, null, null, 0)); + ScriptCallbackEvent event = createCallbackEvent(null, "testMessage", ChatMessageType.GAMEMESSAGE); + chatFilterPlugin.onScriptCallbackEvent(event); + + assertEquals(1, client.getIntStack()[client.getIntStackSize() - 3]); + assertEquals("testMessage (4)", client.getStringStack()[client.getStringStackSize() - 1]); + } + + @Test + public void publicChatFilteredOnDuplicate() + { + when(chatFilterConfig.collapsePlayerChat()).thenReturn(true); + when(chatFilterConfig.maxRepeatedPublicChats()).thenReturn(2); + chatFilterPlugin.onChatMessage(new ChatMessage(mockMessageNode(1, "testName", "testMessage"), ChatMessageType.PUBLICCHAT, null, null, null, 0)); + chatFilterPlugin.onChatMessage(new ChatMessage(mockMessageNode(1, "testName", "testMessage"), ChatMessageType.PUBLICCHAT, null, null, null, 0)); + chatFilterPlugin.onChatMessage(new ChatMessage(mockMessageNode(1, "testName", "testMessage"), ChatMessageType.PUBLICCHAT, null, null, null, 0)); + ScriptCallbackEvent event = createCallbackEvent("testName", "testMessage", ChatMessageType.PUBLICCHAT); + chatFilterPlugin.onScriptCallbackEvent(event); + + assertEquals(0, client.getIntStack()[client.getIntStackSize() - 3]); + } + + @Test + public void testDuplicateChatFilterIgnoresFormatting() + { + when(chatFilterConfig.collapseGameChat()).thenReturn(true); + chatFilterPlugin.onChatMessage(new ChatMessage(mockMessageNode(4, null, "testMessage"), ChatMessageType.GAMEMESSAGE, null, null, null, 0)); + chatFilterPlugin.onChatMessage(new ChatMessage(mockMessageNode(3, null, "testMessage"), ChatMessageType.GAMEMESSAGE, null, null, null, 0)); + chatFilterPlugin.onChatMessage(new ChatMessage(mockMessageNode(2, null, "testMessage"), ChatMessageType.GAMEMESSAGE, null, null, null, 0)); + chatFilterPlugin.onChatMessage(new ChatMessage(mockMessageNode(1, null, "testMessage"), ChatMessageType.GAMEMESSAGE, null, null, null, 0)); + ScriptCallbackEvent event = createCallbackEvent(null, "testMessage", ChatMessageType.GAMEMESSAGE); + chatFilterPlugin.onScriptCallbackEvent(event); + + assertEquals(1, client.getIntStack()[client.getIntStackSize() - 3]); + assertEquals("testMessage (4)", client.getStringStack()[client.getStringStackSize() - 1]); + } + + @Test + public void testChatIcons() + { + when(chatFilterConfig.filteredWords()).thenReturn("test"); + // if this test is broken, this stubbing is required to trip the assert + lenient().when(chatFilterConfig.filterType()).thenReturn(ChatFilterType.REMOVE_MESSAGE); + when(friendChatManager.isMember("Lazark")).thenReturn(true); + + chatFilterPlugin.updateFilteredPatterns(); + ScriptCallbackEvent event = createCallbackEvent("Lazark", "test", ChatMessageType.PUBLICCHAT); + chatFilterPlugin.onScriptCallbackEvent(event); + assertEquals(1, client.getIntStack()[client.getIntStackSize() - 3]); // not filtered + } +} \ No newline at end of file diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/chatnotifications/ChatNotificationsPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/chatnotifications/ChatNotificationsPluginTest.java new file mode 100644 index 0000000000..61606df725 --- /dev/null +++ b/runelite-client/src/test/java/net/runelite/client/plugins/chatnotifications/ChatNotificationsPluginTest.java @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2018, Adam + * 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.chatnotifications; + +import com.google.inject.Guice; +import com.google.inject.testing.fieldbinder.Bind; +import com.google.inject.testing.fieldbinder.BoundFieldModule; +import java.util.Iterator; +import java.util.List; +import javax.inject.Inject; +import javax.inject.Named; +import net.runelite.api.ChatMessageType; +import net.runelite.api.Client; +import net.runelite.api.MessageNode; +import net.runelite.api.Player; +import net.runelite.api.events.ChatMessage; +import net.runelite.client.Notifier; +import net.runelite.client.chat.ChatMessageManager; +import net.runelite.client.util.Text; +import static org.junit.Assert.assertEquals; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class ChatNotificationsPluginTest +{ + @Mock + @Bind + private Client client; + + @Mock + @Bind + private ChatNotificationsConfig config; + + @Mock + @Bind + private ChatMessageManager chatMessageManager; + + @Mock + @Bind + private Notifier notifier; + + @Bind + @Named("runelite.title") + private String runeliteTitle = "RuneLite"; + + @Inject + private ChatNotificationsPlugin chatNotificationsPlugin; + + @Before + public void before() + { + Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); + } + + @Test + public void onChatMessage() + { + when(config.highlightWordsString()).thenReturn("Deathbeam, Deathbeam OSRS , test"); + + MessageNode messageNode = mock(MessageNode.class); + when(messageNode.getValue()).thenReturn("Deathbeam, Deathbeam OSRS"); + + ChatMessage chatMessage = new ChatMessage(); + chatMessage.setType(ChatMessageType.PUBLICCHAT); + chatMessage.setMessageNode(messageNode); + + chatNotificationsPlugin.startUp(); // load highlight config + chatNotificationsPlugin.onChatMessage(chatMessage); + + verify(messageNode).setValue("Deathbeam, Deathbeam OSRS"); + } + + @Test + public void testLtGt() + { + when(config.highlightWordsString()).thenReturn(""); + + String message = "test test test"; + MessageNode messageNode = mock(MessageNode.class); + when(messageNode.getValue()).thenReturn(message); + + ChatMessage chatMessage = new ChatMessage(); + chatMessage.setType(ChatMessageType.PUBLICCHAT); + chatMessage.setMessageNode(messageNode); + + chatNotificationsPlugin.startUp(); // load highlight config + chatNotificationsPlugin.onChatMessage(chatMessage); + + verify(messageNode).setValue("test test test"); + } + + @Test + public void testMatchEntireMessage() + { + when(config.highlightWordsString()).thenReturn(".Your divine potion effect is about to expire."); + + String message = ".Your divine potion effect is about to expire."; + MessageNode messageNode = mock(MessageNode.class); + when(messageNode.getValue()).thenReturn(message); + + ChatMessage chatMessage = new ChatMessage(); + chatMessage.setType(ChatMessageType.PUBLICCHAT); + chatMessage.setMessageNode(messageNode); + + chatNotificationsPlugin.startUp(); // load highlight config + chatNotificationsPlugin.onChatMessage(chatMessage); + + verify(messageNode).setValue(".Your divine potion effect is about to expire."); + } + + @Test + public void testFullStop() + { + when(config.highlightWordsString()).thenReturn("test"); + + String message = "foo test. bar"; + MessageNode messageNode = mock(MessageNode.class); + when(messageNode.getValue()).thenReturn(message); + + ChatMessage chatMessage = new ChatMessage(); + chatMessage.setType(ChatMessageType.PUBLICCHAT); + chatMessage.setMessageNode(messageNode); + + chatNotificationsPlugin.startUp(); // load highlight config + chatNotificationsPlugin.onChatMessage(chatMessage); + + verify(messageNode).setValue("foo test. bar"); + } + + @Test + public void testColor() + { + when(config.highlightWordsString()).thenReturn("you. It"); + + String message = "Your dodgy necklace protects you. It has 1 charge left."; + MessageNode messageNode = mock(MessageNode.class); + when(messageNode.getValue()).thenReturn(message); + + ChatMessage chatMessage = new ChatMessage(); + chatMessage.setType(ChatMessageType.PUBLICCHAT); + chatMessage.setMessageNode(messageNode); + + chatNotificationsPlugin.startUp(); // load highlight config + chatNotificationsPlugin.onChatMessage(chatMessage); + + verify(messageNode).setValue("Your dodgy necklace protects you. It has 1 charge left."); + } + + @Test + public void testPreceedingColor() + { + when(config.highlightWordsString()).thenReturn("you. It"); + + String message = "Your dodgy necklace protects you. It has 1 charge left."; + MessageNode messageNode = mock(MessageNode.class); + when(messageNode.getValue()).thenReturn(message); + + ChatMessage chatMessage = new ChatMessage(); + chatMessage.setType(ChatMessageType.PUBLICCHAT); + chatMessage.setMessageNode(messageNode); + + chatNotificationsPlugin.startUp(); // load highlight config + chatNotificationsPlugin.onChatMessage(chatMessage); + + verify(messageNode).setValue("Your dodgy necklace protects you. It has 1 charge left."); + } + + @Test + public void testEmoji() + { + when(config.highlightWordsString()).thenReturn("test"); + + String message = "emoji test "; + MessageNode messageNode = mock(MessageNode.class); + when(messageNode.getValue()).thenReturn(message); + + ChatMessage chatMessage = new ChatMessage(); + chatMessage.setType(ChatMessageType.PUBLICCHAT); + chatMessage.setMessageNode(messageNode); + + chatNotificationsPlugin.startUp(); // load highlight config + chatNotificationsPlugin.onChatMessage(chatMessage); + + verify(messageNode).setValue("emoji test "); + } + + @Test + public void testNonMatchedColors() + { + when(config.highlightWordsString()).thenReturn("test"); + + String message = "color test "; + MessageNode messageNode = mock(MessageNode.class); + when(messageNode.getValue()).thenReturn(message); + + ChatMessage chatMessage = new ChatMessage(); + chatMessage.setType(ChatMessageType.PUBLICCHAT); + chatMessage.setMessageNode(messageNode); + + chatNotificationsPlugin.startUp(); // load highlight config + chatNotificationsPlugin.onChatMessage(chatMessage); + + verify(messageNode).setValue("color test "); + } + + @Test + public void highlightListTest() + { + when(config.highlightWordsString()).thenReturn("this,is, a , test, "); + final List higlights = Text.fromCSV(config.highlightWordsString()); + assertEquals(4, higlights.size()); + + final Iterator iterator = higlights.iterator(); + assertEquals("this", iterator.next()); + assertEquals("is", iterator.next()); + assertEquals("a", iterator.next()); + assertEquals("test", iterator.next()); + } + + @Test + public void testStripColor() + { + assertEquals("you. It", ChatNotificationsPlugin.stripColor("you. It")); + } + + @Test + public void testHighlightOwnName() + { + Player player = mock(Player.class); + when(player.getName()).thenReturn("Logic Knot"); + when(client.getLocalPlayer()).thenReturn(player); + + when(config.highlightOwnName()).thenReturn(true); + + MessageNode messageNode = mock(MessageNode.class); + when(messageNode.getValue()).thenReturn("Logic Knot received a drop: Adamant longsword"); + ChatMessage chatMessage = new ChatMessage(messageNode, ChatMessageType.GAMEMESSAGE, "", "", "", 0); + chatNotificationsPlugin.onChatMessage(chatMessage); + + verify(messageNode).setValue("Logic Knot received a drop: Adamant longsword"); + } + + @Test + public void testHighlightOwnNameNbsp() + { + Player player = mock(Player.class); + when(player.getName()).thenReturn("Logic Knot"); + when(client.getLocalPlayer()).thenReturn(player); + + when(config.highlightOwnName()).thenReturn(true); + + MessageNode messageNode = mock(MessageNode.class); + when(messageNode.getValue()).thenReturn("Logic\u00a0Knot received a drop: Adamant longsword"); + ChatMessage chatMessage = new ChatMessage(messageNode, ChatMessageType.GAMEMESSAGE, "", "", "", 0); + chatNotificationsPlugin.onChatMessage(chatMessage); + + // set value uses our player name, which has nbsp replaced + verify(messageNode).setValue("Logic Knot received a drop: Adamant longsword"); + } +} \ No newline at end of file diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/cluescrolls/ClueScrollPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/cluescrolls/ClueScrollPluginTest.java new file mode 100644 index 0000000000..1c3cd1ecd4 --- /dev/null +++ b/runelite-client/src/test/java/net/runelite/client/plugins/cluescrolls/ClueScrollPluginTest.java @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2019 Hydrox6 + * Copyright (c) 2019 Adam + * 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.cluescrolls; + +import com.google.inject.Guice; +import com.google.inject.Inject; +import com.google.inject.name.Named; +import com.google.inject.testing.fieldbinder.Bind; +import com.google.inject.testing.fieldbinder.BoundFieldModule; +import net.runelite.api.ChatMessageType; +import net.runelite.api.Client; +import net.runelite.api.NPC; +import net.runelite.api.Player; +import net.runelite.api.coords.WorldPoint; +import net.runelite.api.events.ChatMessage; +import net.runelite.api.events.GameTick; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.game.ItemManager; +import net.runelite.client.plugins.banktags.TagManager; +import net.runelite.client.plugins.cluescrolls.clues.hotcold.HotColdLocation; +import net.runelite.client.ui.overlay.OverlayManager; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import static org.mockito.ArgumentMatchers.any; +import org.mockito.Mock; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class ClueScrollPluginTest +{ + @Mock + @Bind + Client client; + + @Inject + ClueScrollPlugin plugin; + + @Bind + @Named("developerMode") + boolean developerMode; + + @Mock + @Bind + ClueScrollConfig config; + + @Mock + @Bind + OverlayManager overlayManager; + + @Mock + @Bind + ItemManager itemManager; + + @Mock + @Bind + TagManager tagManager; + + @Before + public void before() + { + Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); + } + + @Test + public void getGetMirrorPoint() + { + WorldPoint point, converted; + + // Zalcano's entrance portal + point = new WorldPoint(3282, 6058, 0); + converted = ClueScrollPlugin.getMirrorPoint(point, true); + assertNotEquals(point, converted); + + // Elven Crystal Chest, which is upstairs + point = new WorldPoint(3273, 6082, 2); + converted = ClueScrollPlugin.getMirrorPoint(point, true); + assertNotEquals(point, converted); + + // Around the area of the Elite coordinate clue + point = new WorldPoint(2185, 3280, 0); + // To overworld + converted = ClueScrollPlugin.getMirrorPoint(point, true); + assertEquals(point, converted); + // To real + converted = ClueScrollPlugin.getMirrorPoint(point, false); + assertNotEquals(point, converted); + + // Brugsen Bursen, Grand Exchange + point = new WorldPoint(3165, 3477, 0); + converted = ClueScrollPlugin.getMirrorPoint(point, false); + assertEquals(point, converted); + } + + @Test + public void testLocationHintArrowCleared() + { + final Widget clueWidget = mock(Widget.class); + when(clueWidget.getText()).thenReturn("Buried beneath the ground, who knows where it's found. Lucky for you, A man called Reldo may have a clue."); + final ChatMessage hotColdMessage = new ChatMessage(); + hotColdMessage.setType(ChatMessageType.GAMEMESSAGE); + final Player localPlayer = mock(Player.class); + + when(client.getWidget(WidgetInfo.CLUE_SCROLL_TEXT)).thenReturn(clueWidget); + when(client.getLocalPlayer()).thenReturn(localPlayer); + when(client.getPlane()).thenReturn(0); + when(client.getCachedNPCs()).thenReturn(new NPC[] {}); + when(config.displayHintArrows()).thenReturn(true); + + // The hint arrow should be reset each game tick from when the clue is read onward + // This is to verify the arrow is cleared the correct number of times during the clue updating process. + int clueSetupHintArrowClears = 0; + + // Initialize a beginner hot-cold clue (which will have an end point of LUMBRIDGE_COW_FIELD) + plugin.onGameTick(new GameTick()); + verify(client, times(++clueSetupHintArrowClears)).clearHintArrow(); + + // Perform the first hot-cold check in Lumbridge near sheep pen (get 2 possible points: LUMBRIDGE_COW_FIELD and DRAYNOR_WHEAT_FIELD) + when(localPlayer.getWorldLocation()).thenReturn(new WorldPoint(3208, 3254, 0)); + hotColdMessage.setMessage("The device is hot."); + plugin.onChatMessage(hotColdMessage); + + // Move to SW of DRAYNOR_WHEAT_FIELD (hint arrow should be visible here) + when(localPlayer.getWorldLocation()).thenReturn(new WorldPoint(3105, 3265, 0)); + when(client.getBaseX()).thenReturn(3056); + when(client.getBaseY()).thenReturn(3216); + plugin.onGameTick(new GameTick()); + verify(client, times(++clueSetupHintArrowClears)).clearHintArrow(); + verify(client).setHintArrow(HotColdLocation.DRAYNOR_WHEAT_FIELD.getWorldPoint()); + + // Test in that location (get 1 possible location: LUMBRIDGE_COW_FIELD) + hotColdMessage.setMessage("The device is hot, and warmer than last time."); + plugin.onChatMessage(hotColdMessage); + plugin.onGameTick(new GameTick()); + + // Hint arrow should be cleared and not re-set now as the only remaining location is outside of the current + // scene + verify(client, times(++clueSetupHintArrowClears)).clearHintArrow(); + verify(client, times(1)).setHintArrow(any(WorldPoint.class)); + } +} diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/discord/DiscordStateTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/discord/DiscordStateTest.java new file mode 100644 index 0000000000..815fff0639 --- /dev/null +++ b/runelite-client/src/test/java/net/runelite/client/plugins/discord/DiscordStateTest.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2018, Adam + * 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.discord; + +import com.google.inject.Guice; +import com.google.inject.testing.fieldbinder.Bind; +import com.google.inject.testing.fieldbinder.BoundFieldModule; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.UUID; +import javax.inject.Inject; +import javax.inject.Named; +import net.runelite.api.Client; +import net.runelite.client.discord.DiscordPresence; +import net.runelite.client.discord.DiscordService; +import net.runelite.client.ws.PartyService; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import static org.mockito.ArgumentMatchers.any; +import org.mockito.Mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class DiscordStateTest +{ + @Inject + DiscordState discordState; + + @Mock + @Bind + DiscordConfig discordConfig; + + @Mock + @Bind + DiscordService discordService; + + @Mock + @Bind + Client client; + + @Mock + @Bind + PartyService partyService; + + @Bind + @Named("runelite.title") + private String runeliteTitle = "RuneLite"; + + @Bind + @Named("runelite.version") + private String runeliteVersion = "version"; + + @Before + public void before() + { + Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); + when(partyService.getLocalPartyId()).thenReturn(UUID.nameUUIDFromBytes("test".getBytes(StandardCharsets.UTF_8))); + } + + @Test + public void testStatusReset() + { + when(discordConfig.actionTimeout()).thenReturn(-1); + when(discordConfig.elapsedTimeType()).thenReturn(DiscordConfig.ElapsedTimeType.ACTIVITY); + + discordState.triggerEvent(DiscordGameEventType.IN_MENU); + verify(discordService).updatePresence(any(DiscordPresence.class)); + + discordState.checkForTimeout(); + ArgumentCaptor captor = ArgumentCaptor.forClass(DiscordPresence.class); + verify(discordService, times(2)).updatePresence(captor.capture()); + List captured = captor.getAllValues(); + assertNull(captured.get(captured.size() - 1).getEndTimestamp()); + } + + @Test + public void testStatusTimeout() + { + when(discordConfig.actionTimeout()).thenReturn(-1); + when(discordConfig.elapsedTimeType()).thenReturn(DiscordConfig.ElapsedTimeType.ACTIVITY); + + discordState.triggerEvent(DiscordGameEventType.TRAINING_AGILITY); + verify(discordService).updatePresence(any(DiscordPresence.class)); + + discordState.checkForTimeout(); + verify(discordService, times(1)).clearPresence(); + } + + @Test + public void testAreaChange() + { + when(discordConfig.elapsedTimeType()).thenReturn(DiscordConfig.ElapsedTimeType.TOTAL); + + // Start with state of IN_GAME + ArgumentCaptor captor = ArgumentCaptor.forClass(DiscordPresence.class); + discordState.triggerEvent(DiscordGameEventType.IN_GAME); + verify(discordService, times(1)).updatePresence(captor.capture()); + assertEquals(DiscordGameEventType.IN_GAME.getState(), captor.getValue().getState()); + + // IN_GAME -> CITY + discordState.triggerEvent(DiscordGameEventType.CITY_VARROCK); + verify(discordService, times(2)).updatePresence(captor.capture()); + assertEquals(DiscordGameEventType.CITY_VARROCK.getState(), captor.getValue().getState()); + + // CITY -> IN_GAME + discordState.triggerEvent(DiscordGameEventType.IN_GAME); + verify(discordService, times(3)).updatePresence(captor.capture()); + assertEquals(DiscordGameEventType.IN_GAME.getState(), captor.getValue().getState()); + } +} diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/emojis/EmojiPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/emojis/EmojiPluginTest.java new file mode 100644 index 0000000000..99fc2dc174 --- /dev/null +++ b/runelite-client/src/test/java/net/runelite/client/plugins/emojis/EmojiPluginTest.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2019, Adam + * 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.emojis; + +import com.google.inject.Guice; +import com.google.inject.Inject; +import com.google.inject.testing.fieldbinder.Bind; +import com.google.inject.testing.fieldbinder.BoundFieldModule; +import net.runelite.api.ChatMessageType; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.IndexedSprite; +import net.runelite.api.MessageNode; +import net.runelite.api.events.ChatMessage; +import net.runelite.api.events.GameStateChanged; +import net.runelite.client.chat.ChatMessageManager; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import org.mockito.junit.MockitoJUnitRunner; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +@RunWith(MockitoJUnitRunner.class) +public class EmojiPluginTest +{ + @Mock + @Bind + private Client client; + + @Mock + @Bind + private ChatMessageManager chatMessageManager; + + @Inject + private EmojiPlugin emojiPlugin; + + @Before + public void before() + { + Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); + } + + @Test + public void testOnChatMessage() + { + when(client.getGameState()).thenReturn(GameState.LOGGED_IN); + when(client.getModIcons()).thenReturn(new IndexedSprite[0]); + when(client.createIndexedSprite()).thenReturn(mock(IndexedSprite.class)); + + // Trip emoji loading + GameStateChanged gameStateChanged = new GameStateChanged(); + gameStateChanged.setGameState(GameState.LOGGED_IN); + emojiPlugin.onGameStateChanged(gameStateChanged); + + MessageNode messageNode = mock(MessageNode.class); + // With chat recolor, message may be wrapped in col tags + when(messageNode.getValue()).thenReturn(":) :) :)"); + + ChatMessage chatMessage = new ChatMessage(); + chatMessage.setType(ChatMessageType.PUBLICCHAT); + chatMessage.setMessageNode(messageNode); + + emojiPlugin.onChatMessage(chatMessage); + + verify(messageNode).setValue(" "); + } + + @Test + public void testGtLt() + { + when(client.getGameState()).thenReturn(GameState.LOGGED_IN); + when(client.getModIcons()).thenReturn(new IndexedSprite[0]); + when(client.createIndexedSprite()).thenReturn(mock(IndexedSprite.class)); + + // Trip emoji loading + GameStateChanged gameStateChanged = new GameStateChanged(); + gameStateChanged.setGameState(GameState.LOGGED_IN); + emojiPlugin.onGameStateChanged(gameStateChanged); + + MessageNode messageNode = mock(MessageNode.class); + when(messageNode.getValue()).thenReturn(":D"); + + ChatMessage chatMessage = new ChatMessage(); + chatMessage.setType(ChatMessageType.PUBLICCHAT); + chatMessage.setMessageNode(messageNode); + + emojiPlugin.onChatMessage(chatMessage); + + verify(messageNode).setValue(""); + } + + @Test + public void testEmojiUpdateMessage() + { + String PARTY_POPPER = "'; + String OPEN_MOUTH = "'; + assertNull(emojiPlugin.updateMessage("@@@@@")); + assertEquals(PARTY_POPPER, emojiPlugin.updateMessage("@@@")); + assertEquals(PARTY_POPPER + ' ' + PARTY_POPPER, emojiPlugin.updateMessage("@@@ @@@")); + assertEquals(PARTY_POPPER + ' ' + OPEN_MOUTH, emojiPlugin.updateMessage("@@@\u00A0:O")); + assertEquals(PARTY_POPPER + ' ' + OPEN_MOUTH + ' ' + PARTY_POPPER, emojiPlugin.updateMessage("@@@\u00A0:O @@@")); + assertEquals(PARTY_POPPER + " Hello World " + PARTY_POPPER, emojiPlugin.updateMessage("@@@\u00A0Hello World\u00A0@@@")); + } +} \ No newline at end of file diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/grandexchange/GrandExchangePluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/grandexchange/GrandExchangePluginTest.java new file mode 100644 index 0000000000..e627dac19b --- /dev/null +++ b/runelite-client/src/test/java/net/runelite/client/plugins/grandexchange/GrandExchangePluginTest.java @@ -0,0 +1,332 @@ +/* + * Copyright (c) 2020, Adam + * 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.grandexchange; + +import com.google.inject.Guice; +import com.google.inject.testing.fieldbinder.Bind; +import com.google.inject.testing.fieldbinder.BoundFieldModule; +import java.util.Arrays; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ScheduledExecutorService; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.GrandExchangeOffer; +import net.runelite.api.GrandExchangeOfferState; +import net.runelite.api.ItemComposition; +import net.runelite.api.ItemID; +import net.runelite.api.WorldType; +import net.runelite.api.events.GameStateChanged; +import net.runelite.api.events.GrandExchangeOfferChanged; +import net.runelite.client.Notifier; +import net.runelite.client.account.SessionManager; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.config.RuneLiteConfig; +import net.runelite.client.game.ItemManager; +import net.runelite.client.input.KeyManager; +import net.runelite.client.input.MouseManager; +import static net.runelite.client.plugins.grandexchange.GrandExchangePlugin.findFuzzyIndices; +import static net.runelite.http.api.RuneLiteAPI.GSON; +import net.runelite.http.api.ge.GrandExchangeClient; +import net.runelite.http.api.ge.GrandExchangeTrade; +import net.runelite.http.api.osbuddy.OSBGrandExchangeClient; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import org.mockito.Mock; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class GrandExchangePluginTest +{ + @Inject + private GrandExchangePlugin grandExchangePlugin; + + @Mock + @Bind + private GrandExchangeConfig grandExchangeConfig; + + @Mock + @Bind + private Notifier notifier; + + @Mock + @Bind + private SessionManager sessionManager; + + @Mock + @Bind + private ConfigManager configManager; + + @Mock + @Bind + private ItemManager itemManager; + + @Mock + @Bind + private KeyManager keyManager; + + @Mock + @Bind + private MouseManager mouseManager; + + @Mock + @Bind + private ScheduledExecutorService scheduledExecutorService; + + @Mock + @Bind + private GrandExchangeClient grandExchangeClient; + + @Mock + @Bind + private OSBGrandExchangeClient osbGrandExchangeClient; + + @Mock + @Bind + private Client client; + + @Mock + @Bind + private RuneLiteConfig runeLiteConfig; + + @Before + public void setUp() + { + Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); + when(client.getWorldType()).thenReturn(EnumSet.noneOf(WorldType.class)); + } + + @Test + public void testFindFuzzyIndices() + { + List fuzzyIndices = findFuzzyIndices("Ancestral robe bottom", "obby"); + // robe bottom + assertEquals(Arrays.asList(11, 12, 15), fuzzyIndices); + } + + @Test + public void testSubmitTrade() + { + // 1 @ 25 + SavedOffer savedOffer = new SavedOffer(); + savedOffer.setItemId(ItemID.ABYSSAL_WHIP); + savedOffer.setQuantitySold(1); + savedOffer.setTotalQuantity(10); + savedOffer.setPrice(1000); + savedOffer.setSpent(25); + savedOffer.setState(GrandExchangeOfferState.BUYING); + when(configManager.getRSProfileConfiguration("geoffer", "0")).thenReturn(GSON.toJson(savedOffer)); + + // buy 2 @ 10/ea + GrandExchangeOffer grandExchangeOffer = mock(GrandExchangeOffer.class); + when(grandExchangeOffer.getQuantitySold()).thenReturn(1 + 2); + when(grandExchangeOffer.getItemId()).thenReturn(ItemID.ABYSSAL_WHIP); + when(grandExchangeOffer.getTotalQuantity()).thenReturn(10); + when(grandExchangeOffer.getPrice()).thenReturn(1000); + when(grandExchangeOffer.getSpent()).thenReturn(25 + 10 * 2); + when(grandExchangeOffer.getState()).thenReturn(GrandExchangeOfferState.BUYING); + grandExchangePlugin.submitTrade(0, grandExchangeOffer); + + ArgumentCaptor captor = ArgumentCaptor.forClass(GrandExchangeTrade.class); + verify(grandExchangeClient).submit(captor.capture()); + + GrandExchangeTrade trade = captor.getValue(); + assertTrue(trade.isBuy()); + assertEquals(ItemID.ABYSSAL_WHIP, trade.getItemId()); + assertEquals(2, trade.getDqty()); + assertEquals(10, trade.getTotal()); + assertEquals(45, trade.getSpent()); + assertEquals(20, trade.getDspent()); + } + + @Test + public void testDuplicateTrade() + { + SavedOffer savedOffer = new SavedOffer(); + savedOffer.setItemId(ItemID.ABYSSAL_WHIP); + savedOffer.setQuantitySold(1); + savedOffer.setTotalQuantity(10); + savedOffer.setPrice(1000); + savedOffer.setSpent(25); + savedOffer.setState(GrandExchangeOfferState.BUYING); + when(configManager.getRSProfileConfiguration("geoffer", "0")).thenReturn(GSON.toJson(savedOffer)); + + GrandExchangeOffer grandExchangeOffer = mock(GrandExchangeOffer.class); + when(grandExchangeOffer.getQuantitySold()).thenReturn(1); + when(grandExchangeOffer.getItemId()).thenReturn(ItemID.ABYSSAL_WHIP); + when(grandExchangeOffer.getTotalQuantity()).thenReturn(10); + when(grandExchangeOffer.getPrice()).thenReturn(1000); + lenient().when(grandExchangeOffer.getSpent()).thenReturn(25); + when(grandExchangeOffer.getState()).thenReturn(GrandExchangeOfferState.BUYING); + grandExchangePlugin.submitTrade(0, grandExchangeOffer); + + verify(grandExchangeClient, never()).submit(any(GrandExchangeTrade.class)); + } + + @Test + public void testCancelTrade() + { + SavedOffer savedOffer = new SavedOffer(); + savedOffer.setItemId(ItemID.ABYSSAL_WHIP); + savedOffer.setQuantitySold(1); + savedOffer.setTotalQuantity(10); + savedOffer.setPrice(1000); + savedOffer.setSpent(25); + savedOffer.setState(GrandExchangeOfferState.BUYING); + when(configManager.getRSProfileConfiguration("geoffer", "0")).thenReturn(GSON.toJson(savedOffer)); + + GrandExchangeOffer grandExchangeOffer = mock(GrandExchangeOffer.class); + when(grandExchangeOffer.getQuantitySold()).thenReturn(1); + when(grandExchangeOffer.getItemId()).thenReturn(ItemID.ABYSSAL_WHIP); + when(grandExchangeOffer.getTotalQuantity()).thenReturn(10); + when(grandExchangeOffer.getPrice()).thenReturn(1000); + when(grandExchangeOffer.getSpent()).thenReturn(25); + when(grandExchangeOffer.getState()).thenReturn(GrandExchangeOfferState.CANCELLED_BUY); + grandExchangePlugin.submitTrade(0, grandExchangeOffer); + + ArgumentCaptor captor = ArgumentCaptor.forClass(GrandExchangeTrade.class); + verify(grandExchangeClient).submit(captor.capture()); + + GrandExchangeTrade trade = captor.getValue(); + assertTrue(trade.isBuy()); + assertTrue(trade.isCancel()); + assertEquals(ItemID.ABYSSAL_WHIP, trade.getItemId()); + assertEquals(1, trade.getQty()); + assertEquals(10, trade.getTotal()); + assertEquals(25, trade.getSpent()); + } + + @Test + public void testHop() + { + when(client.getGameState()).thenReturn(GameState.HOPPING); + + GrandExchangeOffer grandExchangeOffer = mock(GrandExchangeOffer.class); + when(grandExchangeOffer.getState()).thenReturn(GrandExchangeOfferState.EMPTY); + + GrandExchangeOfferChanged grandExchangeOfferChanged = new GrandExchangeOfferChanged(); + grandExchangeOfferChanged.setOffer(grandExchangeOffer); + + grandExchangePlugin.onGrandExchangeOfferChanged(grandExchangeOfferChanged); + + verify(configManager, never()).unsetRSProfileConfiguration(anyString(), anyString()); + } + + @Test + public void testLogin() + { + GrandExchangePanel panel = mock(GrandExchangePanel.class); + when(panel.getOffersPanel()).thenReturn(mock(GrandExchangeOffersPanel.class)); + grandExchangePlugin.setPanel(panel); + + when(itemManager.getItemComposition(anyInt())).thenReturn(mock(ItemComposition.class)); + + // provide config support so getOffer and setOffer work + final Map config = new HashMap<>(); + doAnswer(a -> + { + Object[] arguments = a.getArguments(); + config.put((String) arguments[1], arguments[2]); + return null; + }).when(configManager).setRSProfileConfiguration(eq("geoffer"), anyString(), anyString()); + + when(configManager.getRSProfileConfiguration(eq("geoffer"), anyString())).thenAnswer(a -> + { + Object[] arguments = a.getArguments(); + return config.get((String) arguments[1]); + }); + + // set loginBurstGeUpdates + GameStateChanged gameStateChanged = new GameStateChanged(); + gameStateChanged.setGameState(GameState.LOGIN_SCREEN); + + grandExchangePlugin.onGameStateChanged(gameStateChanged); + + // 8x buy 10 whip @ 1k ea, bought 1 sofar. + for (int i = 0; i < GrandExchangePlugin.GE_SLOTS; ++i) + { + GrandExchangeOffer grandExchangeOffer = mock(GrandExchangeOffer.class); + when(grandExchangeOffer.getQuantitySold()).thenReturn(1); + when(grandExchangeOffer.getItemId()).thenReturn(ItemID.ABYSSAL_WHIP); + when(grandExchangeOffer.getTotalQuantity()).thenReturn(10); + when(grandExchangeOffer.getPrice()).thenReturn(1000); + when(grandExchangeOffer.getSpent()).thenReturn(1000); + when(grandExchangeOffer.getState()).thenReturn(GrandExchangeOfferState.SELLING); + + GrandExchangeOfferChanged grandExchangeOfferChanged = new GrandExchangeOfferChanged(); + grandExchangeOfferChanged.setSlot(i); + grandExchangeOfferChanged.setOffer(grandExchangeOffer); + grandExchangePlugin.onGrandExchangeOfferChanged(grandExchangeOfferChanged); + } + + // Now send update for one of the slots + GrandExchangeOffer grandExchangeOffer = mock(GrandExchangeOffer.class); + when(grandExchangeOffer.getQuantitySold()).thenReturn(2); + when(grandExchangeOffer.getItemId()).thenReturn(ItemID.ABYSSAL_WHIP); + when(grandExchangeOffer.getTotalQuantity()).thenReturn(10); + when(grandExchangeOffer.getPrice()).thenReturn(1000); + when(grandExchangeOffer.getSpent()).thenReturn(2000); + when(grandExchangeOffer.getState()).thenReturn(GrandExchangeOfferState.SELLING); + + GrandExchangeOfferChanged grandExchangeOfferChanged = new GrandExchangeOfferChanged(); + grandExchangeOfferChanged.setSlot(2); + grandExchangeOfferChanged.setOffer(grandExchangeOffer); + grandExchangePlugin.onGrandExchangeOfferChanged(grandExchangeOfferChanged); + + // verify trade update + ArgumentCaptor captor = ArgumentCaptor.forClass(GrandExchangeTrade.class); + verify(grandExchangeClient).submit(captor.capture()); + + GrandExchangeTrade trade = captor.getValue(); + assertFalse(trade.isBuy()); + assertEquals(ItemID.ABYSSAL_WHIP, trade.getItemId()); + assertEquals(2, trade.getQty()); + assertEquals(1, trade.getDqty()); + assertEquals(10, trade.getTotal()); + assertEquals(1000, trade.getDspent()); + assertEquals(2000, trade.getSpent()); + assertEquals(1000, trade.getOffer()); + assertEquals(2, trade.getSlot()); + assertTrue(trade.isLogin()); + } +} \ No newline at end of file diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/grounditems/GroundItemsPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/grounditems/GroundItemsPluginTest.java new file mode 100644 index 0000000000..48d6296ca5 --- /dev/null +++ b/runelite-client/src/test/java/net/runelite/client/plugins/grounditems/GroundItemsPluginTest.java @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2020, Adam + * 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.grounditems; + +import com.google.inject.Guice; +import com.google.inject.testing.fieldbinder.Bind; +import com.google.inject.testing.fieldbinder.BoundFieldModule; +import java.util.concurrent.ScheduledExecutorService; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.ItemComposition; +import net.runelite.api.ItemID; +import net.runelite.api.ItemLayer; +import net.runelite.api.Player; +import net.runelite.api.Tile; +import net.runelite.api.TileItem; +import net.runelite.api.coords.WorldPoint; +import net.runelite.api.events.ItemSpawned; +import net.runelite.client.Notifier; +import net.runelite.client.events.ConfigChanged; +import net.runelite.client.game.ItemManager; +import net.runelite.client.input.KeyManager; +import net.runelite.client.input.MouseManager; +import net.runelite.client.plugins.grounditems.config.HighlightTier; +import net.runelite.client.ui.overlay.OverlayManager; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import static org.mockito.ArgumentMatchers.any; +import org.mockito.Mock; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class GroundItemsPluginTest +{ + @Inject + private GroundItemsPlugin groundItemsPlugin; + + @Mock + @Bind + private MouseManager mouseManager; + + @Mock + @Bind + private KeyManager keyManager; + + @Mock + @Bind + private Client client; + + @Mock + @Bind + private ItemManager itemManager; + + @Mock + @Bind + private OverlayManager overlayManager; + + @Mock + @Bind + private GroundItemsConfig config; + + @Mock + @Bind + private GroundItemsOverlay overlay; + + @Mock + @Bind + private Notifier notifier; + + @Mock + @Bind + private ScheduledExecutorService executor; + + @Before + public void setUp() + { + Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); + + doAnswer(a -> + { + a.getArgument(0).run(); + return null; + }).when(executor).execute(any(Runnable.class)); + + when(client.getLocalPlayer()).thenReturn(mock(Player.class)); + when(config.getHiddenItems()).thenReturn(""); + } + + @Test + public void testNotifyHighlightedItem() + { + when(config.getHighlightItems()).thenReturn("abyssal whip"); + when(config.notifyTier()).thenReturn(HighlightTier.OFF); + when(config.notifyHighlightedDrops()).thenReturn(true); + + when(itemManager.getItemComposition(ItemID.ABYSSAL_WHIP)).thenAnswer(a -> + { + ItemComposition itemComposition = mock(ItemComposition.class); + when(itemComposition.getName()).thenReturn("Abyssal whip"); + return itemComposition; + }); + + // trigger reload of highlighted items list + ConfigChanged configChanged = new ConfigChanged(); + configChanged.setGroup("grounditems"); + groundItemsPlugin.onConfigChanged(configChanged); + + // spawn whip + Tile tile = mock(Tile.class); + when(tile.getItemLayer()).thenReturn(mock(ItemLayer.class)); + when(tile.getWorldLocation()).thenReturn(new WorldPoint(0, 0, 0)); + + TileItem tileItem = mock(TileItem.class); + when(tileItem.getId()).thenReturn(ItemID.ABYSSAL_WHIP); + when(tileItem.getQuantity()).thenReturn(1); + + groundItemsPlugin.onItemSpawned(new ItemSpawned(tile, tileItem)); + + verify(notifier).notify("You received a highlighted drop: Abyssal whip"); + } +} \ No newline at end of file diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPluginTest.java new file mode 100644 index 0000000000..bb91fffcb8 --- /dev/null +++ b/runelite-client/src/test/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPluginTest.java @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2018, Tomas Slusny + * 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.idlenotifier; + +import com.google.inject.Guice; +import com.google.inject.Inject; +import com.google.inject.testing.fieldbinder.Bind; +import com.google.inject.testing.fieldbinder.BoundFieldModule; +import net.runelite.api.Actor; +import net.runelite.api.AnimationID; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.Hitsplat; +import net.runelite.api.NPC; +import net.runelite.api.NPCComposition; +import net.runelite.api.Player; +import net.runelite.api.VarPlayer; +import net.runelite.api.coords.WorldPoint; +import net.runelite.api.events.AnimationChanged; +import net.runelite.api.events.GameStateChanged; +import net.runelite.api.events.GameTick; +import net.runelite.api.events.HitsplatApplied; +import net.runelite.api.events.InteractingChanged; +import net.runelite.client.Notifier; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import org.mockito.Mock; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class IdleNotifierPluginTest +{ + @Mock + @Bind + private Client client; + + @Mock + @Bind + private IdleNotifierConfig config; + + @Mock + @Bind + private Notifier notifier; + + @Inject + private IdleNotifierPlugin plugin; + + @Mock + private NPC monster; + + @Mock + private NPC randomEvent; + + @Mock + private NPC fishingSpot; + + @Mock + private Player player; + + @Before + public void setUp() + { + Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); + + // Mock monster + final String[] monsterActions = new String[] { "Attack", "Examine" }; + final NPCComposition monsterComp = mock(NPCComposition.class); + when(monsterComp.getActions()).thenReturn(monsterActions); + when(monster.getComposition()).thenReturn(monsterComp); + + // Mock random event + final String[] randomEventActions = new String[] { "Talk-to", "Dismiss", "Examine" }; + final NPCComposition randomEventComp = mock(NPCComposition.class); + when(randomEventComp.getActions()).thenReturn(randomEventActions); + when(randomEvent.getComposition()).thenReturn(randomEventComp); + + // Mock Fishing Spot + final String[] fishingSpotActions = new String[] { "Use-rod", "Examine" }; + final NPCComposition fishingSpotComp = mock(NPCComposition.class); + when(fishingSpotComp.getActions()).thenReturn(fishingSpotActions); + when(fishingSpot.getComposition()).thenReturn(fishingSpotComp); + when(fishingSpot.getName()).thenReturn("Fishing spot"); + + // Mock player + when(player.getAnimation()).thenReturn(AnimationID.IDLE); + when(client.getLocalPlayer()).thenReturn(player); + + // Mock config + when(config.logoutIdle()).thenReturn(true); + when(config.animationIdle()).thenReturn(true); + when(config.interactionIdle()).thenReturn(true); + when(config.getIdleNotificationDelay()).thenReturn(0); + when(config.getHitpointsThreshold()).thenReturn(42); + when(config.getPrayerThreshold()).thenReturn(42); + + // Mock client + when(client.getGameState()).thenReturn(GameState.LOGGED_IN); + when(client.getKeyboardIdleTicks()).thenReturn(42); + when(client.getMouseLastPressedMillis()).thenReturn(System.currentTimeMillis() - 100_000L); + } + + @Test + public void checkAnimationIdle() + { + when(player.getAnimation()).thenReturn(AnimationID.WOODCUTTING_BRONZE); + AnimationChanged animationChanged = new AnimationChanged(); + animationChanged.setActor(player); + plugin.onAnimationChanged(animationChanged); + plugin.onGameTick(new GameTick()); + when(player.getAnimation()).thenReturn(AnimationID.IDLE); + plugin.onAnimationChanged(animationChanged); + plugin.onGameTick(new GameTick()); + verify(notifier).notify("You are now idle!"); + } + + @Test + public void checkAnimationReset() + { + when(player.getAnimation()).thenReturn(AnimationID.WOODCUTTING_BRONZE); + AnimationChanged animationChanged = new AnimationChanged(); + animationChanged.setActor(player); + plugin.onAnimationChanged(animationChanged); + plugin.onGameTick(new GameTick()); + when(player.getAnimation()).thenReturn(AnimationID.LOOKING_INTO); + plugin.onAnimationChanged(animationChanged); + plugin.onGameTick(new GameTick()); + when(player.getAnimation()).thenReturn(AnimationID.IDLE); + plugin.onAnimationChanged(animationChanged); + plugin.onGameTick(new GameTick()); + verify(notifier, times(0)).notify(any()); + } + + @Test + public void checkAnimationLogout() + { + when(player.getAnimation()).thenReturn(AnimationID.WOODCUTTING_BRONZE); + AnimationChanged animationChanged = new AnimationChanged(); + animationChanged.setActor(player); + plugin.onAnimationChanged(animationChanged); + plugin.onGameTick(new GameTick()); + + // Logout + when(client.getGameState()).thenReturn(GameState.LOGIN_SCREEN); + GameStateChanged gameStateChanged = new GameStateChanged(); + gameStateChanged.setGameState(GameState.LOGIN_SCREEN); + plugin.onGameStateChanged(gameStateChanged); + + // Log back in + when(client.getGameState()).thenReturn(GameState.LOGGED_IN); + gameStateChanged.setGameState(GameState.LOGGED_IN); + plugin.onGameStateChanged(gameStateChanged); + + // Tick + when(player.getAnimation()).thenReturn(AnimationID.IDLE); + plugin.onAnimationChanged(animationChanged); + plugin.onGameTick(new GameTick()); + verify(notifier, times(0)).notify(any()); + } + + @Test + public void checkCombatIdle() + { + when(player.getInteracting()).thenReturn(monster); + plugin.onInteractingChanged(new InteractingChanged(player, monster)); + plugin.onGameTick(new GameTick()); + when(player.getInteracting()).thenReturn(null); + plugin.onInteractingChanged(new InteractingChanged(player, null)); + plugin.onGameTick(new GameTick()); + verify(notifier).notify("You are now out of combat!"); + } + + @Test + public void checkCombatReset() + { + when(player.getInteracting()).thenReturn(mock(Actor.class)); + plugin.onInteractingChanged(new InteractingChanged(player, monster)); + plugin.onGameTick(new GameTick()); + plugin.onInteractingChanged(new InteractingChanged(player, randomEvent)); + plugin.onGameTick(new GameTick()); + plugin.onInteractingChanged(new InteractingChanged(player, null)); + plugin.onGameTick(new GameTick()); + verify(notifier, times(0)).notify(any()); + } + + @Test + public void checkCombatLogout() + { + plugin.onInteractingChanged(new InteractingChanged(player, monster)); + when(player.getInteracting()).thenReturn(mock(Actor.class)); + plugin.onGameTick(new GameTick()); + + // Logout + when(client.getGameState()).thenReturn(GameState.LOGIN_SCREEN); + GameStateChanged gameStateChanged = new GameStateChanged(); + gameStateChanged.setGameState(GameState.LOGIN_SCREEN); + plugin.onGameStateChanged(gameStateChanged); + + // Log back in + when(client.getGameState()).thenReturn(GameState.LOGGED_IN); + gameStateChanged.setGameState(GameState.LOGGED_IN); + plugin.onGameStateChanged(gameStateChanged); + + // Tick + plugin.onInteractingChanged(new InteractingChanged(player, null)); + plugin.onGameTick(new GameTick()); + verify(notifier, times(0)).notify(any()); + } + + @Test + public void checkCombatLogoutIdle() + { + // Player is idle + when(client.getMouseIdleTicks()).thenReturn(80_000); + + // But player is being damaged (is in combat) + final HitsplatApplied hitsplatApplied = new HitsplatApplied(); + hitsplatApplied.setActor(player); + hitsplatApplied.setHitsplat(new Hitsplat(Hitsplat.HitsplatType.DAMAGE_ME, 0, 0)); + plugin.onHitsplatApplied(hitsplatApplied); + plugin.onGameTick(new GameTick()); + verify(notifier, times(0)).notify(any()); + } + + @Test + public void doubleNotifyOnMouseReset() + { + // Player is idle, but in combat so the idle packet is getting set repeatedly + // make sure we are not notifying + + when(client.getKeyboardIdleTicks()).thenReturn(80_000); + when(client.getMouseIdleTicks()).thenReturn(14_500); + + plugin.onGameTick(new GameTick()); + plugin.onGameTick(new GameTick()); + verify(notifier, times(1)).notify(any()); + } + + @Test + public void testSendOneNotificationForAnimationAndInteract() + { + when(player.getInteracting()).thenReturn(fishingSpot); + when(player.getAnimation()).thenReturn(AnimationID.FISHING_POLE_CAST); + + AnimationChanged animationChanged = new AnimationChanged(); + animationChanged.setActor(player); + + plugin.onInteractingChanged(new InteractingChanged(player, fishingSpot)); + plugin.onAnimationChanged(animationChanged); + plugin.onGameTick(new GameTick()); + + verify(notifier, never()).notify(anyString()); + + when(player.getAnimation()).thenReturn(AnimationID.IDLE); + lenient().when(player.getInteracting()).thenReturn(null); + + plugin.onAnimationChanged(animationChanged); + plugin.onInteractingChanged(new InteractingChanged(player, null)); + plugin.onGameTick(new GameTick()); + + verify(notifier).notify("You are now idle!"); + } + + @Test + public void testSpecRegen() + { + when(config.getSpecEnergyThreshold()).thenReturn(50); + + when(client.getVar(eq(VarPlayer.SPECIAL_ATTACK_PERCENT))).thenReturn(400); // 40% + plugin.onGameTick(new GameTick()); // once to set lastSpecEnergy to 400 + verify(notifier, never()).notify(any()); + + when(client.getVar(eq(VarPlayer.SPECIAL_ATTACK_PERCENT))).thenReturn(500); // 50% + plugin.onGameTick(new GameTick()); + verify(notifier).notify(eq("You have restored spec energy!")); + } + + @Test + public void testMovementIdle() + { + when(config.movementIdle()).thenReturn(true); + + when(player.getWorldLocation()).thenReturn(new WorldPoint(0, 0, 0)); + plugin.onGameTick(new GameTick()); + when(player.getWorldLocation()).thenReturn(new WorldPoint(1, 0, 0)); + plugin.onGameTick(new GameTick()); + // No movement here + plugin.onGameTick(new GameTick()); + + verify(notifier).notify(eq("You have stopped moving!")); + } +} \ No newline at end of file diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/screenshot/ScreenshotPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/screenshot/ScreenshotPluginTest.java new file mode 100644 index 0000000000..edd5101817 --- /dev/null +++ b/runelite-client/src/test/java/net/runelite/client/plugins/screenshot/ScreenshotPluginTest.java @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2018, Adam + * 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.screenshot; + +import com.google.inject.Guice; +import com.google.inject.testing.fieldbinder.Bind; +import com.google.inject.testing.fieldbinder.BoundFieldModule; +import java.util.concurrent.ScheduledExecutorService; +import java.util.function.Consumer; +import javax.inject.Inject; +import static net.runelite.api.ChatMessageType.GAMEMESSAGE; +import net.runelite.api.Client; +import net.runelite.api.events.ChatMessage; +import net.runelite.api.events.GameTick; +import net.runelite.api.events.WidgetLoaded; +import net.runelite.api.widgets.Widget; +import static net.runelite.api.widgets.WidgetID.DIALOG_SPRITE_GROUP_ID; +import static net.runelite.api.widgets.WidgetID.LEVEL_UP_GROUP_ID; +import static net.runelite.api.widgets.WidgetInfo.DIALOG_SPRITE_TEXT; +import static net.runelite.api.widgets.WidgetInfo.LEVEL_UP_LEVEL; +import net.runelite.client.Notifier; +import net.runelite.client.config.RuneLiteConfig; +import net.runelite.client.ui.ClientUI; +import net.runelite.client.ui.DrawManager; +import net.runelite.client.ui.overlay.OverlayManager; +import net.runelite.client.ui.overlay.infobox.InfoBoxManager; +import net.runelite.client.util.ImageCapture; +import static org.junit.Assert.assertEquals; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import org.mockito.Mock; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class ScreenshotPluginTest +{ + private static final String CLUE_SCROLL = "You have completed 28 medium Treasure Trails"; + private static final String BARROWS_CHEST = "Your Barrows chest count is 310"; + private static final String CHAMBERS_OF_XERIC_CHEST = "Your completed Chambers of Xeric count is: 489."; + private static final String THEATRE_OF_BLOOD_CHEST = "Your completed Theatre of Blood count is: 73."; + private static final String NOT_SO_VALUABLE_DROP = "Valuable drop: 6 x Bronze arrow (42 coins)"; + private static final String VALUABLE_DROP = "Valuable drop: Rune scimitar (25,600 coins)"; + private static final String UNTRADEABLE_DROP = "Untradeable drop: Rusty sword"; + private static final String BA_HIGH_GAMBLE_REWARD = "Raw shark (x 300)!
High level gamble count: 100"; + private static final String HUNTER_LEVEL_2_TEXT = "Congratulations, you've just advanced a Hunter level.

Your Hunter level is now 2."; + + @Mock + @Bind + private Client client; + + @Inject + private ScreenshotPlugin screenshotPlugin; + + @Mock + @Bind + private ScreenshotConfig screenshotConfig; + + @Mock + @Bind + Notifier notifier; + + @Mock + @Bind + ClientUI clientUi; + + @Mock + @Bind + DrawManager drawManager; + + @Mock + @Bind + RuneLiteConfig config; + + @Mock + @Bind + ScheduledExecutorService service; + + @Mock + @Bind + private OverlayManager overlayManager; + + @Mock + @Bind + private InfoBoxManager infoBoxManager; + + @Mock + @Bind + private ImageCapture imageCapture; + + @Before + public void before() + { + Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); + when(screenshotConfig.screenshotLevels()).thenReturn(true); + when(screenshotConfig.screenshotValuableDrop()).thenReturn(true); + when(screenshotConfig.valuableDropThreshold()).thenReturn(1000); + when(screenshotConfig.screenshotUntradeableDrop()).thenReturn(true); + } + + @Test + public void testClueScroll() + { + ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "Seth", CLUE_SCROLL, null, 0); + screenshotPlugin.onChatMessage(chatMessageEvent); + + assertEquals("medium", screenshotPlugin.getClueType()); + assertEquals(28, screenshotPlugin.getClueNumber()); + } + + @Test + public void testBarrowsChest() + { + ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "Seth", BARROWS_CHEST, null, 0); + screenshotPlugin.onChatMessage(chatMessageEvent); + + assertEquals(310, screenshotPlugin.getBarrowsNumber()); + } + + @Test + public void testChambersOfXericChest() + { + ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "Seth", CHAMBERS_OF_XERIC_CHEST, null, 0); + screenshotPlugin.onChatMessage(chatMessageEvent); + + assertEquals(489, screenshotPlugin.getChambersOfXericNumber()); + } + + @Test + public void testTheatreOfBloodChest() + { + ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "Magic fTail", THEATRE_OF_BLOOD_CHEST, null, 0); + screenshotPlugin.onChatMessage(chatMessageEvent); + + assertEquals(73, screenshotPlugin.gettheatreOfBloodNumber()); + } + + @Test + public void testNotSoValuableDrop() + { + ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", NOT_SO_VALUABLE_DROP, null, 0); + screenshotPlugin.onChatMessage(chatMessageEvent); + + verifyNoInteractions(drawManager); + + when(screenshotConfig.valuableDropThreshold()).thenReturn(0); + screenshotPlugin.onChatMessage(chatMessageEvent); + + verify(drawManager).requestNextFrameListener(any(Consumer.class)); + } + + @Test + public void testValuableDrop() + { + ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", VALUABLE_DROP, null, 0); + when(screenshotConfig.valuableDropThreshold()).thenReturn(100_000); + screenshotPlugin.onChatMessage(chatMessageEvent); + + verifyNoInteractions(drawManager); + + when(screenshotConfig.valuableDropThreshold()).thenReturn(1000); + screenshotPlugin.onChatMessage(chatMessageEvent); + + verify(drawManager).requestNextFrameListener(any(Consumer.class)); + } + + @Test + public void testUntradeableDrop() + { + ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", UNTRADEABLE_DROP, null, 0); + screenshotPlugin.onChatMessage(chatMessageEvent); + + verify(drawManager).requestNextFrameListener(any(Consumer.class)); + } + + @Test + public void testHitpointsLevel99() + { + Widget levelChild = mock(Widget.class); + when(client.getWidget(eq(LEVEL_UP_LEVEL))).thenReturn(levelChild); + + when(levelChild.getText()).thenReturn("Your Hitpoints are now 99."); + + assertEquals("Hitpoints(99)", screenshotPlugin.parseLevelUpWidget(LEVEL_UP_LEVEL)); + + WidgetLoaded event = new WidgetLoaded(); + event.setGroupId(LEVEL_UP_GROUP_ID); + screenshotPlugin.onWidgetLoaded(event); + + GameTick tick = new GameTick(); + screenshotPlugin.onGameTick(tick); + + verify(drawManager).requestNextFrameListener(any(Consumer.class)); + } + + @Test + public void testFiremakingLevel9() + { + Widget levelChild = mock(Widget.class); + when(client.getWidget(eq(LEVEL_UP_LEVEL))).thenReturn(levelChild); + + when(levelChild.getText()).thenReturn("Your Firemaking level is now 9."); + + assertEquals("Firemaking(9)", screenshotPlugin.parseLevelUpWidget(LEVEL_UP_LEVEL)); + + WidgetLoaded event = new WidgetLoaded(); + event.setGroupId(LEVEL_UP_GROUP_ID); + screenshotPlugin.onWidgetLoaded(event); + + GameTick tick = new GameTick(); + screenshotPlugin.onGameTick(tick); + + verify(drawManager).requestNextFrameListener(any(Consumer.class)); + } + + @Test + public void testAttackLevel70() + { + Widget levelChild = mock(Widget.class); + when(client.getWidget(eq(LEVEL_UP_LEVEL))).thenReturn(levelChild); + + when(levelChild.getText()).thenReturn("Your Attack level is now 70."); + + assertEquals("Attack(70)", screenshotPlugin.parseLevelUpWidget(LEVEL_UP_LEVEL)); + + WidgetLoaded event = new WidgetLoaded(); + event.setGroupId(LEVEL_UP_GROUP_ID); + screenshotPlugin.onWidgetLoaded(event); + + GameTick tick = new GameTick(); + screenshotPlugin.onGameTick(tick); + + verify(drawManager).requestNextFrameListener(any(Consumer.class)); + } + + @Test + public void testHunterLevel2() + { + Widget levelChild = mock(Widget.class); + when(client.getWidget(eq(DIALOG_SPRITE_TEXT))).thenReturn(levelChild); + + when(levelChild.getText()).thenReturn(HUNTER_LEVEL_2_TEXT); + + assertEquals("Hunter(2)", screenshotPlugin.parseLevelUpWidget(DIALOG_SPRITE_TEXT)); + + WidgetLoaded event = new WidgetLoaded(); + event.setGroupId(DIALOG_SPRITE_GROUP_ID); + screenshotPlugin.onWidgetLoaded(event); + + GameTick tick = new GameTick(); + screenshotPlugin.onGameTick(tick); + + verify(drawManager).requestNextFrameListener(any(Consumer.class)); + } + + @Test + public void testQuestParsing() + { + assertEquals("Quest(The Corsair Curse)", ScreenshotPlugin.parseQuestCompletedWidget("You have completed The Corsair Curse!")); + assertEquals("Quest(One Small Favour)", ScreenshotPlugin.parseQuestCompletedWidget("'One Small Favour' completed!")); + assertEquals("Quest(Hazeel Cult partial completion)", ScreenshotPlugin.parseQuestCompletedWidget("You have... kind of... completed the Hazeel Cult Quest!")); + assertEquals("Quest(Rag and Bone Man II)", ScreenshotPlugin.parseQuestCompletedWidget("You have completely completed Rag and Bone Man!")); + assertEquals("Quest(Recipe for Disaster - Culinaromancer)", ScreenshotPlugin.parseQuestCompletedWidget("Congratulations! You have defeated the Culinaromancer!")); + assertEquals("Quest(Recipe for Disaster - Another Cook's Quest)", ScreenshotPlugin.parseQuestCompletedWidget("You have completed Another Cook's Quest!")); + assertEquals("Quest(Doric's Quest)", ScreenshotPlugin.parseQuestCompletedWidget("You have completed Doric's Quest!")); + assertEquals("Quest(quest not found)", ScreenshotPlugin.parseQuestCompletedWidget("Sins of the Father forgiven!")); + } + + @Test + public void testBAHighGambleRewardParsing() + { + assertEquals("High Gamble(100)", ScreenshotPlugin.parseBAHighGambleWidget(BA_HIGH_GAMBLE_REWARD)); + } + + @Test + public void testLevelUpScreenshotsDisabled() + { + // Level up dialogs use the same widget interface as BA high gamble results + when(screenshotConfig.screenshotLevels()).thenReturn(false); + when(screenshotConfig.screenshotHighGamble()).thenReturn(true); + Widget dialogChild = mock(Widget.class); + when(dialogChild.getText()).thenReturn(HUNTER_LEVEL_2_TEXT); + when(client.getWidget(DIALOG_SPRITE_TEXT)).thenReturn(dialogChild); + + WidgetLoaded event = new WidgetLoaded(); + event.setGroupId(DIALOG_SPRITE_GROUP_ID); + screenshotPlugin.onWidgetLoaded(event); + + screenshotPlugin.onGameTick(new GameTick()); + + verify(drawManager, times(0)).requestNextFrameListener(any(Consumer.class)); + } + + @Test + public void testBAHighGambleScreenshotsDisabled() + { + // BA high gamble results use the same widget interface as level up dialogs + when(screenshotConfig.screenshotLevels()).thenReturn(true); + when(screenshotConfig.screenshotHighGamble()).thenReturn(false); + Widget dialogChild = mock(Widget.class); + when(dialogChild.getText()).thenReturn(BA_HIGH_GAMBLE_REWARD); + when(client.getWidget(DIALOG_SPRITE_TEXT)).thenReturn(dialogChild); + + WidgetLoaded event = new WidgetLoaded(); + event.setGroupId(DIALOG_SPRITE_GROUP_ID); + screenshotPlugin.onWidgetLoaded(event); + + screenshotPlugin.onGameTick(new GameTick()); + + verify(drawManager, times(0)).requestNextFrameListener(any(Consumer.class)); + } +} diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/slayer/SlayerPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/slayer/SlayerPluginTest.java new file mode 100644 index 0000000000..967802b2cf --- /dev/null +++ b/runelite-client/src/test/java/net/runelite/client/plugins/slayer/SlayerPluginTest.java @@ -0,0 +1,997 @@ +/* + * Copyright (c) 2017, Adam + * 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.slayer; + +import com.google.inject.Guice; +import com.google.inject.testing.fieldbinder.Bind; +import com.google.inject.testing.fieldbinder.BoundFieldModule; +import java.io.IOException; +import java.util.Arrays; +import java.util.concurrent.ScheduledExecutorService; +import javax.inject.Inject; +import net.runelite.api.ChatMessageType; +import static net.runelite.api.ChatMessageType.GAMEMESSAGE; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.Hitsplat; +import net.runelite.api.MessageNode; +import net.runelite.api.NPC; +import net.runelite.api.NPCComposition; +import net.runelite.api.Player; +import net.runelite.api.Skill; +import net.runelite.api.coords.LocalPoint; +import net.runelite.api.events.ActorDeath; +import net.runelite.api.events.ChatMessage; +import net.runelite.api.events.GameStateChanged; +import net.runelite.api.events.GameTick; +import net.runelite.api.events.HitsplatApplied; +import net.runelite.api.events.StatChanged; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.Notifier; +import net.runelite.client.chat.ChatCommandManager; +import net.runelite.client.chat.ChatMessageManager; +import net.runelite.client.game.ItemManager; +import net.runelite.client.ui.overlay.OverlayManager; +import net.runelite.client.ui.overlay.infobox.InfoBoxManager; +import net.runelite.http.api.chat.ChatClient; +import static org.junit.Assert.assertEquals; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import org.mockito.Mock; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class SlayerPluginTest +{ + private static final String TASK_NEW = "Your new task is to kill 231 Suqahs."; + private static final String TASK_NEW_KONAR = "You are to bring balance to 147 Wyrms in the Karuulm Slayer Dungeon."; + private static final String TASK_NEW_KONAR_2 = "You are to bring balance to 142 Hellhounds in Witchhaven Dungeon."; + private static final String TASK_NEW_KONAR_3 = "You are to bring balance to 135 Trolls south of Mount Quidamortem."; + private static final String TASK_NEW_FIRST = "We'll start you off hunting goblins, you'll need to kill 17 of them."; + private static final String TASK_NEW_FIRST_KONAR = "We'll start you off bringing balance to cows, you'll need to kill 44 of them."; + private static final String TASK_NEW_NPC_CONTACT = "Excellent, you're doing great. Your new task is to kill
211 Suqahs."; + private static final String TASK_NEW_FROM_PARTNER = "You have received a new Slayer assignment from breaklulz: Dust Devils (377)"; + private static final String TASK_CHECKSLAYERGEM = "You're assigned to kill Suqahs; only 211 more to go."; + private static final String TASK_CHECKSLAYERGEM_WILDERNESS = "You're assigned to kill Suqahs in the Wilderness; only 211 more to go."; + private static final String TASK_CHECKSLAYERGEM_KONAR = "You're assigned to kill Blue dragons in the Ogre Enclave; only 122 more to go."; + private static final String TASK_UPDATE_COMBAT_BRACELET = "You still need to kill 30 monsters to complete your current Slayer assignment"; + + private static final String TASK_BOSS_NEW = "Excellent. You're now assigned to kill Vet'ion 3 times.
Your reward point tally is 914."; + private static final String TASK_BOSS_NEW_THE = "Excellent. You're now assigned to kill the Chaos
Elemental 3 times. Your reward point tally is 914."; + private static final String TASK_KONAR_BOSS = "You're now assigned to bring balance to the Alchemical
Hydra 35 times. Your reward point tally is 724."; + + private static final String TASK_EXISTING = "You're still hunting suqahs; you have 222 to go. Come
back when you've finished your task."; + private static final String TASK_EXISTING_KONAR = "You're still bringing balance to adamant dragons in the Lithkren Vault, with 3 to go. Come back when you're finished."; + private static final String TASK_EXISTING_WILDERNESS = "You're still meant to be slaying bandits in the Wilderness; you have 99 to go. Come back when you've finished your task."; + + private static final String TASK_ACTIVATESLAYERGEM = "You're currently assigned to kill fossil island wyverns; only 23 more to go. Your reward point tally is 46."; + private static final String TASK_ACTIVATESLAYERGEM_KONAR = "You're currently assigned to bring balance to adamant dragons in the Lithkren Vault; you have 3 more to go. Your reward point tally is 16."; + private static final String TASK_ACTIVATESLAYERGEM_WILDERNESS = "You're currently assigned to kill bandits in the Wilderness; only 99 more to go. Your reward point tally is 34."; + + private static final String REWARD_POINTS = "Reward points: 17,566"; + + private static final String TASK_ONE = "You've completed 1 task and will need 4 more before you start receiving Slayer points; return to a Slayer master."; + private static final String TASK_COMPLETE_NO_POINTS = "You've completed 3 tasks and will need 2 more before you start receiving Slayer points; return to a Slayer master."; + private static final String TASK_POINTS = "You've completed 9 tasks and received 10 points, giving you a total of 18,000; return to a Slayer master."; + private static final String TASK_LARGE_STREAK = "You've completed 2,465 tasks and received 15 points, giving you a total of 131,071; return to a Slayer master."; + private static final String TASK_COMPETE_TURAEL = "You've completed 104 tasks . You'll be eligible to earn reward points if you complete tasks from a more advanced Slayer Master."; + private static final String TASK_MAX_STREAK = "You've completed at least 16,000 tasks and received 15 points, giving you a total of 131,071; return to a Slayer master."; + private static final String TASK_MAX_POINTS = "You've completed 9 tasks and reached the maximum amount of Slayer points (131,071); return to a Slayer master."; + private static final String TASK_WILDERNESS = "You've completed 9 Wilderness tasks and received 10 points, giving you a total of 18,000; return to a Slayer master."; + + private static final String TASK_COMPLETE = "You need something new to hunt."; + private static final String TASK_CANCELED = "Your task has been cancelled."; + + private static final String SUPERIOR_MESSAGE = "A superior foe has appeared..."; + + private static final String BRACLET_SLAUGHTER = "Your bracelet of slaughter prevents your slayer count from decreasing. It has 9 charges left."; + private static final String BRACLET_EXPEDITIOUS = "Your expeditious bracelet helps you progress your slayer task faster. It has 9 charges left."; + + private static final String BRACLET_SLAUGHTER_V2 = "Your bracelet of slaughter prevents your slayer count from decreasing. It has 1 charge left."; + private static final String BRACLET_EXPEDITIOUS_V2 = "Your expeditious bracelet helps you progress your slayer faster. It has 1 charge left."; + + private static final String BRACLET_SLAUGHTER_V3 = "Your bracelet of slaughter prevents your slayer count from decreasing. It then crumbles to dust."; + private static final String BRACLET_EXPEDITIOUS_V3 = "Your expeditious bracelet helps you progress your slayer faster. It then crumbles to dust."; + + private static final String CHAT_BRACELET_SLAUGHTER_CHARGE = "Your bracelet of slaughter has 12 charges left."; + private static final String CHAT_BRACELET_EXPEDITIOUS_CHARGE = "Your expeditious bracelet has 12 charges left."; + + private static final String CHAT_BRACELET_SLAUGHTER_CHARGE_ONE = "Your bracelet of slaughter has 1 charge left."; + private static final String CHAT_BRACELET_EXPEDITIOUS_CHARGE_ONE = "Your expeditious bracelet has 1 charge left."; + + private static final String BREAK_SLAUGHTER = "The bracelet shatters. Your next bracelet of slaughter
will start afresh from 30 charges."; + private static final String BREAK_EXPEDITIOUS = "The bracelet shatters. Your next expeditious bracelet
will start afresh from 30 charges."; + + @Mock + @Bind + Client client; + + @Mock + @Bind + SlayerConfig slayerConfig; + + @Mock + @Bind + OverlayManager overlayManager; + + @Mock + @Bind + SlayerOverlay overlay; + + @Mock + @Bind + InfoBoxManager infoBoxManager; + + @Mock + @Bind + ItemManager itemManager; + + @Mock + @Bind + Notifier notifier; + + @Mock + @Bind + ChatMessageManager chatMessageManager; + + @Mock + @Bind + ChatCommandManager chatCommandManager; + + @Mock + @Bind + ScheduledExecutorService executor; + + @Mock + @Bind + ChatClient chatClient; + + @Inject + SlayerPlugin slayerPlugin; + + @Before + public void before() + { + Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); + } + + @Test + public void testNewTask() + { + Widget npcDialog = mock(Widget.class); + when(npcDialog.getText()).thenReturn(TASK_NEW); + when(client.getWidget(WidgetInfo.DIALOG_NPC_TEXT)).thenReturn(npcDialog); + slayerPlugin.onGameTick(new GameTick()); + + assertEquals("Suqahs", slayerPlugin.getTaskName()); + assertEquals(231, slayerPlugin.getAmount()); + } + + @Test + public void testNewKonarTask() + { + Widget npcDialog = mock(Widget.class); + when(npcDialog.getText()).thenReturn(TASK_NEW_KONAR); + when(client.getWidget(WidgetInfo.DIALOG_NPC_TEXT)).thenReturn(npcDialog); + slayerPlugin.onGameTick(new GameTick()); + + assertEquals("Wyrms", slayerPlugin.getTaskName()); + assertEquals(147, slayerPlugin.getAmount()); + assertEquals("Karuulm Slayer Dungeon", slayerPlugin.getTaskLocation()); + } + + @Test + public void testNewKonarTask2() + { + Widget npcDialog = mock(Widget.class); + when(npcDialog.getText()).thenReturn(TASK_NEW_KONAR_2); + when(client.getWidget(WidgetInfo.DIALOG_NPC_TEXT)).thenReturn(npcDialog); + slayerPlugin.onGameTick(new GameTick()); + + assertEquals("Hellhounds", slayerPlugin.getTaskName()); + assertEquals(142, slayerPlugin.getAmount()); + assertEquals("Witchhaven Dungeon", slayerPlugin.getTaskLocation()); + } + + @Test + public void testNewKonarTask3() + { + Widget npcDialog = mock(Widget.class); + when(npcDialog.getText()).thenReturn(TASK_NEW_KONAR_3); + when(client.getWidget(WidgetInfo.DIALOG_NPC_TEXT)).thenReturn(npcDialog); + slayerPlugin.onGameTick(new GameTick()); + + assertEquals("Trolls", slayerPlugin.getTaskName()); + assertEquals(135, slayerPlugin.getAmount()); + assertEquals("Mount Quidamortem", slayerPlugin.getTaskLocation()); + } + + @Test + public void testFirstTask() + { + Widget npcDialog = mock(Widget.class); + when(npcDialog.getText()).thenReturn(TASK_NEW_FIRST); + when(client.getWidget(WidgetInfo.DIALOG_NPC_TEXT)).thenReturn(npcDialog); + slayerPlugin.onGameTick(new GameTick()); + + assertEquals("goblins", slayerPlugin.getTaskName()); + assertEquals(17, slayerPlugin.getAmount()); + } + + @Test + public void testFirstTaskKonar() + { + Widget npcDialog = mock(Widget.class); + when(npcDialog.getText()).thenReturn(TASK_NEW_FIRST_KONAR); + when(client.getWidget(WidgetInfo.DIALOG_NPC_TEXT)).thenReturn(npcDialog); + slayerPlugin.onGameTick(new GameTick()); + + assertEquals("cows", slayerPlugin.getTaskName()); + assertEquals(44, slayerPlugin.getAmount()); + } + + @Test + public void testNewNpcContactTask() + { + Widget npcDialog = mock(Widget.class); + when(npcDialog.getText()).thenReturn(TASK_NEW_NPC_CONTACT); + when(client.getWidget(WidgetInfo.DIALOG_NPC_TEXT)).thenReturn(npcDialog); + slayerPlugin.onGameTick(new GameTick()); + + assertEquals("Suqahs", slayerPlugin.getTaskName()); + assertEquals(211, slayerPlugin.getAmount()); + } + + @Test + public void testBossTask() + { + Widget npcDialog = mock(Widget.class); + when(npcDialog.getText()).thenReturn(TASK_BOSS_NEW); + when(client.getWidget(WidgetInfo.DIALOG_NPC_TEXT)).thenReturn(npcDialog); + slayerPlugin.onGameTick(new GameTick()); + + assertEquals("Vet'ion", slayerPlugin.getTaskName()); + assertEquals(3, slayerPlugin.getAmount()); + verify(slayerConfig).points(914); + } + + @Test + public void testBossTaskThe() + { + Widget npcDialog = mock(Widget.class); + when(npcDialog.getText()).thenReturn(TASK_BOSS_NEW_THE); + when(client.getWidget(WidgetInfo.DIALOG_NPC_TEXT)).thenReturn(npcDialog); + slayerPlugin.onGameTick(new GameTick()); + + assertEquals("Chaos Elemental", slayerPlugin.getTaskName()); + assertEquals(3, slayerPlugin.getAmount()); + verify(slayerConfig).points(914); + } + + @Test + public void testKonarBossTask() + { + Widget npcDialog = mock(Widget.class); + when(npcDialog.getText()).thenReturn(TASK_KONAR_BOSS); + when(client.getWidget(WidgetInfo.DIALOG_NPC_TEXT)).thenReturn(npcDialog); + slayerPlugin.onGameTick(new GameTick()); + + assertEquals("Alchemical Hydra", slayerPlugin.getTaskName()); + assertEquals(35, slayerPlugin.getAmount()); + verify(slayerConfig).points(724); + } + + @Test + public void testPartnerTask() + { + ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", TASK_NEW_FROM_PARTNER, null, 0); + slayerPlugin.onChatMessage(chatMessageEvent); + + assertEquals("Dust Devils", slayerPlugin.getTaskName()); + assertEquals(377, slayerPlugin.getAmount()); + } + + @Test + public void testCheckSlayerGem() + { + ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", TASK_CHECKSLAYERGEM, null, 0); + slayerPlugin.onChatMessage(chatMessageEvent); + assertEquals("Suqahs", slayerPlugin.getTaskName()); + assertEquals(211, slayerPlugin.getAmount()); + } + + @Test + public void testCheckSlayerGemWildernessTask() + { + ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", TASK_CHECKSLAYERGEM_WILDERNESS, null, 0); + slayerPlugin.onChatMessage(chatMessageEvent); + assertEquals("Suqahs", slayerPlugin.getTaskName()); + assertEquals(211, slayerPlugin.getAmount()); + assertEquals("Wilderness", slayerPlugin.getTaskLocation()); + } + + @Test + public void testCheckSlayerGemKonarTask() + { + ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", TASK_CHECKSLAYERGEM_KONAR, null, 0); + slayerPlugin.onChatMessage(chatMessageEvent); + + assertEquals("Blue dragons", slayerPlugin.getTaskName()); + assertEquals(122, slayerPlugin.getAmount()); + assertEquals("Ogre Enclave", slayerPlugin.getTaskLocation()); + } + + @Test + public void testExistingTask() + { + Widget npcDialog = mock(Widget.class); + when(npcDialog.getText()).thenReturn(TASK_EXISTING); + when(client.getWidget(WidgetInfo.DIALOG_NPC_TEXT)).thenReturn(npcDialog); + slayerPlugin.onGameTick(new GameTick()); + + assertEquals("suqahs", slayerPlugin.getTaskName()); + assertEquals(222, slayerPlugin.getAmount()); + } + + @Test + public void testExistingTaskKonar() + { + Widget npcDialog = mock(Widget.class); + when(npcDialog.getText()).thenReturn(TASK_EXISTING_KONAR); + when(client.getWidget(WidgetInfo.DIALOG_NPC_TEXT)).thenReturn(npcDialog); + slayerPlugin.onGameTick(new GameTick()); + + assertEquals("adamant dragons", slayerPlugin.getTaskName()); + assertEquals(3, slayerPlugin.getAmount()); + assertEquals("Lithkren Vault", slayerPlugin.getTaskLocation()); + } + + @Test + public void testExistingTaskWilderness() + { + Widget npcDialog = mock(Widget.class); + when(npcDialog.getText()).thenReturn(TASK_EXISTING_WILDERNESS); + when(client.getWidget(WidgetInfo.DIALOG_NPC_TEXT)).thenReturn(npcDialog); + slayerPlugin.onGameTick(new GameTick()); + + assertEquals("bandits", slayerPlugin.getTaskName()); + assertEquals(99, slayerPlugin.getAmount()); + assertEquals("Wilderness", slayerPlugin.getTaskLocation()); + } + + @Test + public void testSlayergemActivate() + { + Widget npcDialog = mock(Widget.class); + when(npcDialog.getText()).thenReturn(TASK_ACTIVATESLAYERGEM); + when(client.getWidget(WidgetInfo.DIALOG_NPC_TEXT)).thenReturn(npcDialog); + slayerPlugin.onGameTick(new GameTick()); + + assertEquals("fossil island wyverns", slayerPlugin.getTaskName()); + assertEquals(23, slayerPlugin.getAmount()); + } + + @Test + public void testSlayergemActivateKonar() + { + Widget npcDialog = mock(Widget.class); + when(npcDialog.getText()).thenReturn(TASK_ACTIVATESLAYERGEM_KONAR); + when(client.getWidget(WidgetInfo.DIALOG_NPC_TEXT)).thenReturn(npcDialog); + slayerPlugin.onGameTick(new GameTick()); + + assertEquals("adamant dragons", slayerPlugin.getTaskName()); + assertEquals(3, slayerPlugin.getAmount()); + assertEquals("Lithkren Vault", slayerPlugin.getTaskLocation()); + } + + @Test + public void testSlayergemActivateWilderness() + { + Widget npcDialog = mock(Widget.class); + when(npcDialog.getText()).thenReturn(TASK_ACTIVATESLAYERGEM_WILDERNESS); + when(client.getWidget(WidgetInfo.DIALOG_NPC_TEXT)).thenReturn(npcDialog); + slayerPlugin.onGameTick(new GameTick()); + + assertEquals("bandits", slayerPlugin.getTaskName()); + assertEquals(99, slayerPlugin.getAmount()); + assertEquals("Wilderness", slayerPlugin.getTaskLocation()); + } + + @Test + public void testRewardPointsWidget() + { + Widget rewardBar = mock(Widget.class); + Widget rewardBarText = mock(Widget.class); + Widget[] rewardBarChildren = new Widget[]{rewardBarText}; + + when(rewardBar.getDynamicChildren()).thenReturn(rewardBarChildren); + when(rewardBarText.getText()).thenReturn(REWARD_POINTS); + when(client.getWidget(WidgetInfo.SLAYER_REWARDS_TOPBAR)).thenReturn(rewardBar); + slayerPlugin.onGameTick(new GameTick()); + + verify(slayerConfig).points(17566); + } + + @Test + public void testOneTask() + { + ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "Perterter", TASK_ONE, null, 0); + slayerPlugin.onChatMessage(chatMessageEvent); + + verify(slayerConfig).streak(1); + assertEquals("", slayerPlugin.getTaskName()); + assertEquals(0, slayerPlugin.getAmount()); + } + + @Test + public void testNoPoints() + { + ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "Perterter", TASK_COMPLETE_NO_POINTS, null, 0); + slayerPlugin.onChatMessage(chatMessageEvent); + + verify(slayerConfig).streak(3); + assertEquals("", slayerPlugin.getTaskName()); + assertEquals(0, slayerPlugin.getAmount()); + } + + @Test + public void testPoints() + { + ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "Perterter", TASK_POINTS, null, 0); + slayerPlugin.onChatMessage(chatMessageEvent); + + verify(slayerConfig).streak(9); + assertEquals("", slayerPlugin.getTaskName()); + assertEquals(0, slayerPlugin.getAmount()); + verify(slayerConfig).points(18_000); + } + + @Test + public void testLargeStreak() + { + ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "Perterter", TASK_LARGE_STREAK, null, 0); + slayerPlugin.onChatMessage(chatMessageEvent); + + verify(slayerConfig).streak(2465); + assertEquals("", slayerPlugin.getTaskName()); + assertEquals(0, slayerPlugin.getAmount()); + verify(slayerConfig).points(131_071); + } + + @Test + public void testTaskCompleteTurael() + { + ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "Perterter", TASK_COMPETE_TURAEL, null, 0); + slayerPlugin.onChatMessage(chatMessageEvent); + + verify(slayerConfig).streak(104); + assertEquals("", slayerPlugin.getTaskName()); + assertEquals(0, slayerPlugin.getAmount()); + } + + @Test + public void testTaskMaxStreak() + { + ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", TASK_MAX_STREAK, null, 0); + slayerPlugin.onChatMessage(chatMessageEvent); + + verify(slayerConfig).streak(16_000); + verify(slayerConfig).points(131_071); + assertEquals("", slayerPlugin.getTaskName()); + assertEquals(0, slayerPlugin.getAmount()); + } + + @Test + public void testTaskMaxPoints() + { + ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", TASK_MAX_POINTS, null, 0); + slayerPlugin.onChatMessage(chatMessageEvent); + + verify(slayerConfig).streak(9); + verify(slayerConfig).points(131_071); + assertEquals("", slayerPlugin.getTaskName()); + assertEquals(0, slayerPlugin.getAmount()); + } + + @Test + public void testTaskWilderness() + { + ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", TASK_WILDERNESS, null, 0); + slayerPlugin.onChatMessage(chatMessageEvent); + + verify(slayerConfig).streak(9); + verify(slayerConfig).points(18_000); + assertEquals("", slayerPlugin.getTaskName()); + assertEquals(0, slayerPlugin.getAmount()); + } + + @Test + public void testComplete() + { + slayerPlugin.setTaskName("cows"); + slayerPlugin.setAmount(42); + + ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "Perterter", TASK_COMPLETE, null, 0); + slayerPlugin.onChatMessage(chatMessageEvent); + + assertEquals("", slayerPlugin.getTaskName()); + assertEquals(0, slayerPlugin.getAmount()); + } + + @Test + public void testCancelled() + { + slayerPlugin.setTaskName("cows"); + slayerPlugin.setAmount(42); + + ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "Perterter", TASK_CANCELED, null, 0); + slayerPlugin.onChatMessage(chatMessageEvent); + + assertEquals("", slayerPlugin.getTaskName()); + assertEquals(0, slayerPlugin.getAmount()); + } + + @Test + public void testSuperiorNotification() + { + ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "Superior", SUPERIOR_MESSAGE, null, 0); + + when(slayerConfig.showSuperiorNotification()).thenReturn(true); + slayerPlugin.onChatMessage(chatMessageEvent); + verify(notifier).notify(SUPERIOR_MESSAGE); + + when(slayerConfig.showSuperiorNotification()).thenReturn(false); + slayerPlugin.onChatMessage(chatMessageEvent); + verifyNoMoreInteractions(notifier); + } + + @Test + public void testCorrectlyCapturedTaskKill() + { + final Player player = mock(Player.class); + when(player.getLocalLocation()).thenReturn(new LocalPoint(0, 0)); + when(client.getLocalPlayer()).thenReturn(player); + + StatChanged statChanged = new StatChanged( + Skill.SLAYER, + 100, + 2, + 2 + ); + slayerPlugin.onStatChanged(statChanged); + + slayerPlugin.setTaskName("Dagannoth"); + slayerPlugin.setAmount(143); + + statChanged = new StatChanged( + Skill.SLAYER, + 110, + 2, + 2 + ); + slayerPlugin.onStatChanged(statChanged); + + assertEquals(142, slayerPlugin.getAmount()); + } + + @Test + public void testIncorrectlyCapturedTaskKill() + { + final Player player = mock(Player.class); + when(player.getLocalLocation()).thenReturn(new LocalPoint(0, 0)); + when(client.getLocalPlayer()).thenReturn(player); + + StatChanged statChanged = new StatChanged( + Skill.SLAYER, + 100, + 2, + 2 + ); + slayerPlugin.onStatChanged(statChanged); + + slayerPlugin.setTaskName("Monster"); + slayerPlugin.setAmount(98); + + assert Task.getTask("Monster") == null; + + statChanged = new StatChanged( + Skill.SLAYER, + 110, + 2, + 2 + ); + slayerPlugin.onStatChanged(statChanged); + + assertEquals(97, slayerPlugin.getAmount()); + } + + @Test + public void testJadTaskKill() + { + final Player player = mock(Player.class); + when(player.getLocalLocation()).thenReturn(new LocalPoint(0, 0)); + when(client.getLocalPlayer()).thenReturn(player); + + StatChanged statChanged = new StatChanged( + Skill.SLAYER, + 100, + 2, + 2 + ); + slayerPlugin.onStatChanged(statChanged); + + slayerPlugin.setTaskName("TzTok-Jad"); + slayerPlugin.setAmount(1); + + // One bat kill + statChanged = new StatChanged( + Skill.SLAYER, + 110, + 2, + 2 + ); + slayerPlugin.onStatChanged(statChanged); + + assertEquals(1, slayerPlugin.getAmount()); + + // One Jad kill + statChanged = new StatChanged( + Skill.SLAYER, + 25360, + -1, + -1 + ); + slayerPlugin.onStatChanged(statChanged); + + assertEquals(0, slayerPlugin.getAmount()); + } + + @Test + public void testZukTaskKill() + { + final Player player = mock(Player.class); + when(player.getLocalLocation()).thenReturn(new LocalPoint(0, 0)); + when(client.getLocalPlayer()).thenReturn(player); + + StatChanged statChanged = new StatChanged( + Skill.SLAYER, + 110, + 2, + 2 + ); + slayerPlugin.onStatChanged(statChanged); + + slayerPlugin.setTaskName("TzKal-Zuk"); + slayerPlugin.setAmount(1); + + // One bat kill + statChanged = new StatChanged( + Skill.SLAYER, + 125, + 2, + 2 + ); + slayerPlugin.onStatChanged(statChanged); + + assertEquals(1, slayerPlugin.getAmount()); + + // One Zuk kill + statChanged = new StatChanged( + Skill.SLAYER, + 102_015, + -1, + -1 + ); + slayerPlugin.onStatChanged(statChanged); + + assertEquals(0, slayerPlugin.getAmount()); + } + + @Test + public void testBraceletSlaughter() + { + ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", BRACLET_SLAUGHTER, null, 0); + + slayerPlugin.setAmount(42); + slayerPlugin.setSlaughterChargeCount(10); + + slayerPlugin.onChatMessage(chatMessageEvent); + + assertEquals(9, slayerPlugin.getSlaughterChargeCount()); + assertEquals(43, slayerPlugin.getAmount()); + + chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", CHAT_BRACELET_SLAUGHTER_CHARGE, null, 0); + slayerPlugin.onChatMessage(chatMessageEvent); + + assertEquals(12, slayerPlugin.getSlaughterChargeCount()); + + chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", CHAT_BRACELET_SLAUGHTER_CHARGE_ONE, null, 0); + slayerPlugin.onChatMessage(chatMessageEvent); + + assertEquals(1, slayerPlugin.getSlaughterChargeCount()); + + slayerPlugin.setSlaughterChargeCount(1); + chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", BRACLET_SLAUGHTER_V3, null, 0); + slayerPlugin.onChatMessage(chatMessageEvent); + + assertEquals(30, slayerPlugin.getSlaughterChargeCount()); + + Widget braceletBreakWidget = mock(Widget.class); + when(braceletBreakWidget.getText()).thenReturn(BREAK_SLAUGHTER); + when(client.getWidget(WidgetInfo.DIALOG_SPRITE_TEXT)).thenReturn(braceletBreakWidget); + + slayerPlugin.setSlaughterChargeCount(-1); + slayerPlugin.onGameTick(new GameTick()); + assertEquals(30, slayerPlugin.getSlaughterChargeCount()); + + chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", BRACLET_SLAUGHTER_V2, null, 0); + + slayerPlugin.setAmount(42); + slayerPlugin.setSlaughterChargeCount(2); + + slayerPlugin.onChatMessage(chatMessageEvent); + + assertEquals(1, slayerPlugin.getSlaughterChargeCount()); + assertEquals(43, slayerPlugin.getAmount()); + } + + @Test + public void testBraceletExpeditious() + { + ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", BRACLET_EXPEDITIOUS, null, 0); + + slayerPlugin.setAmount(42); + slayerPlugin.setExpeditiousChargeCount(10); + + slayerPlugin.onChatMessage(chatMessageEvent); + + assertEquals(41, slayerPlugin.getAmount()); + assertEquals(9, slayerPlugin.getExpeditiousChargeCount()); + + chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", CHAT_BRACELET_EXPEDITIOUS_CHARGE, null, 0); + slayerPlugin.onChatMessage(chatMessageEvent); + + assertEquals(12, slayerPlugin.getExpeditiousChargeCount()); + + chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", CHAT_BRACELET_EXPEDITIOUS_CHARGE_ONE, null, 0); + slayerPlugin.onChatMessage(chatMessageEvent); + + assertEquals(1, slayerPlugin.getExpeditiousChargeCount()); + + slayerPlugin.setExpeditiousChargeCount(1); + chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", BRACLET_EXPEDITIOUS_V3, null, 0); + slayerPlugin.onChatMessage(chatMessageEvent); + + assertEquals(30, slayerPlugin.getExpeditiousChargeCount()); + + Widget braceletBreakWidget = mock(Widget.class); + when(braceletBreakWidget.getText()).thenReturn(BREAK_EXPEDITIOUS); + when(client.getWidget(WidgetInfo.DIALOG_SPRITE_TEXT)).thenReturn(braceletBreakWidget); + + slayerPlugin.setExpeditiousChargeCount(-1); + slayerPlugin.onGameTick(new GameTick()); + assertEquals(30, slayerPlugin.getExpeditiousChargeCount()); + + chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", BRACLET_EXPEDITIOUS_V2, null, 0); + + slayerPlugin.setAmount(42); + slayerPlugin.setExpeditiousChargeCount(2); + + slayerPlugin.onChatMessage(chatMessageEvent); + + assertEquals(41, slayerPlugin.getAmount()); + assertEquals(1, slayerPlugin.getExpeditiousChargeCount()); + } + + @Test + public void testCombatBraceletUpdate() + { + final Player player = mock(Player.class); + when(player.getLocalLocation()).thenReturn(new LocalPoint(0, 0)); + when(client.getLocalPlayer()).thenReturn(player); + + slayerPlugin.setTaskName("Suqahs"); + slayerPlugin.setAmount(231); + + ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", TASK_UPDATE_COMBAT_BRACELET, null, 0); + slayerPlugin.onChatMessage(chatMessage); + + assertEquals("Suqahs", slayerPlugin.getTaskName()); + slayerPlugin.killed(1); + assertEquals(30, slayerPlugin.getAmount()); + } + + @Test + public void updateInitialAmount() + { + Widget npcDialog = mock(Widget.class); + when(npcDialog.getText()).thenReturn(TASK_EXISTING); + when(client.getWidget(WidgetInfo.DIALOG_NPC_TEXT)).thenReturn(npcDialog); + slayerPlugin.onGameTick(new GameTick()); + + assertEquals(222, slayerPlugin.getInitialAmount()); + } + + @Test + public void testTaskLookup() throws IOException + { + net.runelite.http.api.chat.Task task = new net.runelite.http.api.chat.Task(); + task.setTask("Abyssal demons"); + task.setLocation("Abyss"); + task.setAmount(42); + task.setInitialAmount(42); + + when(slayerConfig.taskCommand()).thenReturn(true); + when(chatClient.getTask(anyString())).thenReturn(task); + + ChatMessage setMessage = new ChatMessage(); + setMessage.setType(ChatMessageType.PUBLICCHAT); + setMessage.setName("Adam"); + setMessage.setMessageNode(mock(MessageNode.class)); + + slayerPlugin.taskLookup(setMessage, "!task"); + + verify(chatMessageManager).update(any(MessageNode.class)); + } + + @Test + public void testTaskLookupInvalid() throws IOException + { + net.runelite.http.api.chat.Task task = new net.runelite.http.api.chat.Task(); + task.setTask("task<"); + task.setLocation("loc"); + task.setAmount(42); + task.setInitialAmount(42); + + when(slayerConfig.taskCommand()).thenReturn(true); + when(chatClient.getTask(anyString())).thenReturn(task); + + ChatMessage chatMessage = new ChatMessage(); + chatMessage.setType(ChatMessageType.PUBLICCHAT); + chatMessage.setName("Adam"); + chatMessage.setMessageNode(mock(MessageNode.class)); + + slayerPlugin.taskLookup(chatMessage, "!task"); + + verify(chatMessageManager, never()).update(any(MessageNode.class)); + } + + @Test + public void testNewAccountSlayerKill() + { + final Player player = mock(Player.class); + when(player.getLocalLocation()).thenReturn(new LocalPoint(0, 0)); + when(client.getLocalPlayer()).thenReturn(player); + + slayerPlugin.setTaskName("Bears"); + slayerPlugin.setAmount(35); + + StatChanged statChanged = new StatChanged( + Skill.SLAYER, + 0, + 1, + 1 + ); + slayerPlugin.onStatChanged(statChanged); + + statChanged = new StatChanged( + Skill.SLAYER, + 27, + 1, + 1 + ); + slayerPlugin.onStatChanged(statChanged); + + assertEquals(34, slayerPlugin.getAmount()); + } + + @Test + public void infoboxNotAddedOnLogin() + { + when(slayerConfig.taskName()).thenReturn(Task.BLOODVELD.getName()); + + GameStateChanged loggingIn = new GameStateChanged(); + loggingIn.setGameState(GameState.LOGGING_IN); + slayerPlugin.onGameStateChanged(loggingIn); + + GameStateChanged loggedIn = new GameStateChanged(); + loggedIn.setGameState(GameState.LOGGED_IN); + slayerPlugin.onGameStateChanged(loggedIn); + + verify(infoBoxManager, never()).addInfoBox(any()); + } + + @Test + public void testMultikill() + { + final Player player = mock(Player.class); + when(player.getLocalLocation()).thenReturn(new LocalPoint(0, 0)); + when(client.getLocalPlayer()).thenReturn(player); + + // Setup xp cache + StatChanged statChanged = new StatChanged( + Skill.SLAYER, + 0, + 1, + 1 + ); + slayerPlugin.onStatChanged(statChanged); + + NPCComposition npcComposition = mock(NPCComposition.class); + when(npcComposition.getActions()).thenReturn(new String[]{"Attack"}); + + NPC npc1 = mock(NPC.class); + when(npc1.getName()).thenReturn("Suqah"); + when(npc1.getTransformedComposition()).thenReturn(npcComposition); + + NPC npc2 = mock(NPC.class); + when(npc2.getName()).thenReturn("Suqah"); + when(npc2.getTransformedComposition()).thenReturn(npcComposition); + + when(client.getNpcs()).thenReturn(Arrays.asList(npc1, npc2)); + + // Set task + Widget npcDialog = mock(Widget.class); + when(npcDialog.getText()).thenReturn(TASK_NEW); + when(client.getWidget(WidgetInfo.DIALOG_NPC_TEXT)).thenReturn(npcDialog); + slayerPlugin.onGameTick(new GameTick()); + + // Damage both npcs + Hitsplat hitsplat = new Hitsplat(Hitsplat.HitsplatType.DAMAGE_ME, 1, 1); + HitsplatApplied hitsplatApplied = new HitsplatApplied(); + hitsplatApplied.setHitsplat(hitsplat); + hitsplatApplied.setActor(npc1); + slayerPlugin.onHitsplatApplied(hitsplatApplied); + + hitsplatApplied.setActor(npc2); + slayerPlugin.onHitsplatApplied(hitsplatApplied); + + // Kill both npcs + slayerPlugin.onActorDeath(new ActorDeath(npc1)); + slayerPlugin.onActorDeath(new ActorDeath(npc2)); + + slayerPlugin.onGameTick(new GameTick()); + + statChanged = new StatChanged( + Skill.SLAYER, + 105, + 2, + 2 + ); + slayerPlugin.onStatChanged(statChanged); + + assertEquals("Suqahs", slayerPlugin.getTaskName()); + assertEquals(229, slayerPlugin.getAmount()); // 2 kills + } +} diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/specialcounter/SpecialCounterPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/specialcounter/SpecialCounterPluginTest.java new file mode 100644 index 0000000000..e865688cd4 --- /dev/null +++ b/runelite-client/src/test/java/net/runelite/client/plugins/specialcounter/SpecialCounterPluginTest.java @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2020, Adam + * 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.specialcounter; + +import com.google.inject.Guice; +import com.google.inject.Inject; +import com.google.inject.testing.fieldbinder.Bind; +import com.google.inject.testing.fieldbinder.BoundFieldModule; +import net.runelite.api.Actor; +import net.runelite.api.Client; +import net.runelite.api.EquipmentInventorySlot; +import net.runelite.api.Hitsplat; +import net.runelite.api.InventoryID; +import net.runelite.api.Item; +import net.runelite.api.ItemContainer; +import net.runelite.api.ItemID; +import net.runelite.api.NPC; +import net.runelite.api.Player; +import net.runelite.api.VarPlayer; +import net.runelite.api.events.HitsplatApplied; +import net.runelite.api.events.InteractingChanged; +import net.runelite.api.events.VarbitChanged; +import net.runelite.client.Notifier; +import net.runelite.client.game.ItemManager; +import net.runelite.client.ui.overlay.infobox.InfoBoxManager; +import net.runelite.client.ws.PartyService; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import static org.mockito.ArgumentMatchers.any; +import org.mockito.Mock; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class SpecialCounterPluginTest +{ + @Mock + @Bind + private Client client; + + @Mock + @Bind + private InfoBoxManager infoBoxManager; + + @Mock + @Bind + private PartyService partyService; + + @Mock + @Bind + private ItemManager itemManager; + + @Mock + @Bind + private Notifier notifier; + + @Mock + @Bind + private SpecialCounterConfig specialCounterConfig; + + @Inject + private SpecialCounterPlugin specialCounterPlugin; + + @Before + public void before() + { + Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); + + // Set up spec weapon + ItemContainer equipment = mock(ItemContainer.class); + when(equipment.getItem(EquipmentInventorySlot.WEAPON.getSlotIdx())).thenReturn(new Item(ItemID.BANDOS_GODSWORD, 1)); + when(client.getItemContainer(InventoryID.EQUIPMENT)).thenReturn(equipment); + + // Set up special attack energy + when(client.getVar(VarPlayer.SPECIAL_ATTACK_PERCENT)).thenReturn(100); + specialCounterPlugin.onVarbitChanged(new VarbitChanged()); + + } + + private static HitsplatApplied hitsplat(Actor target, Hitsplat.HitsplatType type) + { + Hitsplat hitsplat = new Hitsplat(type, type == Hitsplat.HitsplatType.DAMAGE_ME ? 1 : 0, 42); + HitsplatApplied hitsplatApplied = new HitsplatApplied(); + hitsplatApplied.setActor(target); + hitsplatApplied.setHitsplat(hitsplat); + return hitsplatApplied; + } + + @Test + public void testSpecDamage() + { + NPC target = mock(NPC.class); + + Player player = mock(Player.class); + when(client.getLocalPlayer()).thenReturn(player); + + // spec npc + when(client.getVar(VarPlayer.SPECIAL_ATTACK_PERCENT)).thenReturn(50); + specialCounterPlugin.onVarbitChanged(new VarbitChanged()); + lenient().when(player.getInteracting()).thenReturn(target); + specialCounterPlugin.onInteractingChanged(new InteractingChanged(player, target)); + + // hit 1 + specialCounterPlugin.onHitsplatApplied(hitsplat(target, Hitsplat.HitsplatType.DAMAGE_ME)); + + verify(infoBoxManager).addInfoBox(any(SpecialCounter.class)); + } + + @Test + public void testSpecBlock() + { + NPC target = mock(NPC.class); + + Player player = mock(Player.class); + when(client.getLocalPlayer()).thenReturn(player); + + // spec npc + when(client.getVar(VarPlayer.SPECIAL_ATTACK_PERCENT)).thenReturn(50); + specialCounterPlugin.onVarbitChanged(new VarbitChanged()); + lenient().when(player.getInteracting()).thenReturn(target); + specialCounterPlugin.onInteractingChanged(new InteractingChanged(player, target)); + + // block 0 + specialCounterPlugin.onHitsplatApplied(hitsplat(target, Hitsplat.HitsplatType.BLOCK_ME)); + + // hit 1 + specialCounterPlugin.onHitsplatApplied(hitsplat(target, Hitsplat.HitsplatType.DAMAGE_ME)); + + verify(infoBoxManager, never()).addInfoBox(any(SpecialCounter.class)); + } + + @Test + public void testUnaggro() + { + NPC target = mock(NPC.class); + + Player player = mock(Player.class); + when(client.getLocalPlayer()).thenReturn(player); + + // tick 1: attack npc + when(player.getInteracting()).thenReturn(target); + specialCounterPlugin.onInteractingChanged(new InteractingChanged(player, target)); + + // tick 2: spec fires and un-interact npc + when(client.getVar(VarPlayer.SPECIAL_ATTACK_PERCENT)).thenReturn(50); + specialCounterPlugin.onVarbitChanged(new VarbitChanged()); + lenient().when(player.getInteracting()).thenReturn(null); + specialCounterPlugin.onInteractingChanged(new InteractingChanged(player, null)); + + // tick 3: hit 1 + specialCounterPlugin.onHitsplatApplied(hitsplat(target, Hitsplat.HitsplatType.DAMAGE_ME)); + + verify(infoBoxManager).addInfoBox(any(SpecialCounter.class)); + } + + @Test + public void testSameTick() + { + NPC targetA = mock(NPC.class); + NPC targetB = mock(NPC.class); + + Player player = mock(Player.class); + when(client.getLocalPlayer()).thenReturn(player); + + // tick 1: attack npc A + when(player.getInteracting()).thenReturn(targetA); + specialCounterPlugin.onInteractingChanged(new InteractingChanged(player, targetA)); + + // tick 2: spec npc B + when(client.getVar(VarPlayer.SPECIAL_ATTACK_PERCENT)).thenReturn(50); + specialCounterPlugin.onVarbitChanged(new VarbitChanged()); + lenient().when(player.getInteracting()).thenReturn(targetB); + specialCounterPlugin.onInteractingChanged(new InteractingChanged(player, targetB)); + + // tick 3: hitsplat A, hitsplat B + specialCounterPlugin.onHitsplatApplied(hitsplat(targetA, Hitsplat.HitsplatType.DAMAGE_ME)); + verify(infoBoxManager, never()).addInfoBox(any(SpecialCounter.class)); + + specialCounterPlugin.onHitsplatApplied(hitsplat(targetB, Hitsplat.HitsplatType.DAMAGE_ME)); + verify(infoBoxManager).addInfoBox(any(SpecialCounter.class)); + } + + @Test + public void testReset() + { + NPC targetA = mock(NPC.class); + NPC targetB = mock(NPC.class); + when(targetB.getId()).thenReturn(1); // a different npc type + + Player player = mock(Player.class); + when(client.getLocalPlayer()).thenReturn(player); + + // spec npc + when(client.getVar(VarPlayer.SPECIAL_ATTACK_PERCENT)).thenReturn(50); + specialCounterPlugin.onVarbitChanged(new VarbitChanged()); + lenient().when(player.getInteracting()).thenReturn(targetA); + specialCounterPlugin.onInteractingChanged(new InteractingChanged(player, targetA)); + + // hit 1 + specialCounterPlugin.onHitsplatApplied(hitsplat(targetA, Hitsplat.HitsplatType.DAMAGE_ME)); + + verify(infoBoxManager).addInfoBox(any(SpecialCounter.class)); + + // attack npc 2 + specialCounterPlugin.onInteractingChanged(new InteractingChanged(player, targetB)); + + // hit 1 + specialCounterPlugin.onHitsplatApplied(hitsplat(targetB, Hitsplat.HitsplatType.DAMAGE_ME)); + + verify(infoBoxManager).removeInfoBox(any(SpecialCounter.class)); + } + + @Test + public void testNotification() + { + // Create an enemy + NPC target = mock(NPC.class); + + // Create player + Player player = mock(Player.class); + when(client.getLocalPlayer()).thenReturn(player); + when(specialCounterConfig.bandosGodswordThreshold()).thenReturn(2); + when(specialCounterConfig.thresholdNotification()).thenReturn(true); + + // Attack enemy + when(player.getInteracting()).thenReturn(target); + specialCounterPlugin.onInteractingChanged(new InteractingChanged(player, target)); + + // First special attack + when(client.getVar(VarPlayer.SPECIAL_ATTACK_PERCENT)).thenReturn(50); + specialCounterPlugin.onVarbitChanged(new VarbitChanged()); + specialCounterPlugin.onHitsplatApplied(hitsplat(target, Hitsplat.HitsplatType.DAMAGE_ME)); + + // Second special attack + when(client.getVar(VarPlayer.SPECIAL_ATTACK_PERCENT)).thenReturn(0); + specialCounterPlugin.onVarbitChanged(new VarbitChanged()); + specialCounterPlugin.onHitsplatApplied(hitsplat(target, Hitsplat.HitsplatType.DAMAGE_ME)); + + verify(notifier).notify("Bandos Godsword special attack threshold reached!"); + } + + @Test + public void testNotificationNotThreshold() + { + // Create an enemy + NPC target = mock(NPC.class); + + // Create player + Player player = mock(Player.class); + when(client.getLocalPlayer()).thenReturn(player); + when(specialCounterConfig.bandosGodswordThreshold()).thenReturn(3); + lenient().when(specialCounterConfig.thresholdNotification()).thenReturn(true); + + // Attack enemy + when(player.getInteracting()).thenReturn(target); + specialCounterPlugin.onInteractingChanged(new InteractingChanged(player, target)); + + // First special attack + when(client.getVar(VarPlayer.SPECIAL_ATTACK_PERCENT)).thenReturn(50); + specialCounterPlugin.onVarbitChanged(new VarbitChanged()); + specialCounterPlugin.onHitsplatApplied(hitsplat(target, Hitsplat.HitsplatType.DAMAGE_ME)); + + // Second special attack + when(client.getVar(VarPlayer.SPECIAL_ATTACK_PERCENT)).thenReturn(0); + specialCounterPlugin.onVarbitChanged(new VarbitChanged()); + specialCounterPlugin.onHitsplatApplied(hitsplat(target, Hitsplat.HitsplatType.DAMAGE_ME)); + + verify(notifier, never()).notify(any()); + } +} diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/timers/TimersPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/timers/TimersPluginTest.java new file mode 100644 index 0000000000..ab7a254c6d --- /dev/null +++ b/runelite-client/src/test/java/net/runelite/client/plugins/timers/TimersPluginTest.java @@ -0,0 +1,372 @@ +/* + * Copyright (c) 2019, Adam + * 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.timers; + +import com.google.inject.Guice; +import com.google.inject.Inject; +import com.google.inject.testing.fieldbinder.Bind; +import com.google.inject.testing.fieldbinder.BoundFieldModule; +import java.time.Duration; +import java.time.Instant; +import net.runelite.api.ChatMessageType; +import net.runelite.api.Client; +import net.runelite.api.InventoryID; +import net.runelite.api.ItemContainer; +import net.runelite.api.events.ChatMessage; +import net.runelite.api.events.ItemContainerChanged; +import net.runelite.client.game.ItemManager; +import net.runelite.client.game.SpriteManager; +import net.runelite.client.ui.overlay.infobox.InfoBox; +import net.runelite.client.ui.overlay.infobox.InfoBoxManager; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.nullable; +import org.mockito.Mock; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.stubbing.Answer; + +@RunWith(MockitoJUnitRunner.class) +public class TimersPluginTest +{ + @Inject + private TimersPlugin timersPlugin; + + @Mock + @Bind + private TimersConfig timersConfig; + + @Mock + @Bind + private Client client; + + @Mock + @Bind + private ItemManager itemManager; + + @Mock + @Bind + private SpriteManager spriteManager; + + @Mock + @Bind + private InfoBoxManager infoBoxManager; + + @Before + public void before() + { + Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); + } + + @Test + public void testHalfTeleblock() + { + when(timersConfig.showTeleblock()).thenReturn(true); + ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "A Tele Block spell has been cast on you by Runelite. It will expire in 2 minutes, 30 seconds.", "", 0); + timersPlugin.onChatMessage(chatMessage); + + ArgumentCaptor captor = ArgumentCaptor.forClass(InfoBox.class); + verify(infoBoxManager).addInfoBox(captor.capture()); + TimerTimer infoBox = (TimerTimer) captor.getValue(); + assertEquals(GameTimer.TELEBLOCK, infoBox.getTimer()); + assertEquals(Duration.ofSeconds(2 * 60 + 30), infoBox.getDuration()); + } + + @Test + public void testFullTeleblock() + { + when(timersConfig.showTeleblock()).thenReturn(true); + ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "A Tele Block spell has been cast on you by Runelite. It will expire in 5 minutes.", "", 0); + timersPlugin.onChatMessage(chatMessage); + + ArgumentCaptor captor = ArgumentCaptor.forClass(InfoBox.class); + verify(infoBoxManager).addInfoBox(captor.capture()); + TimerTimer infoBox = (TimerTimer) captor.getValue(); + assertEquals(GameTimer.TELEBLOCK, infoBox.getTimer()); + assertEquals(Duration.ofMinutes(5), infoBox.getDuration()); + } + + @Test + public void testDmmHalfTb() + { + when(timersConfig.showTeleblock()).thenReturn(true); + ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "A Tele Block spell has been cast on you by Runelite. It will expire in 1 minute, 15 seconds.", "", 0); + timersPlugin.onChatMessage(chatMessage); + + ArgumentCaptor captor = ArgumentCaptor.forClass(InfoBox.class); + verify(infoBoxManager).addInfoBox(captor.capture()); + TimerTimer infoBox = (TimerTimer) captor.getValue(); + assertEquals(GameTimer.TELEBLOCK, infoBox.getTimer()); + assertEquals(Duration.ofSeconds(60 + 15), infoBox.getDuration()); + } + + @Test + public void testDmmFullTb() + { + when(timersConfig.showTeleblock()).thenReturn(true); + ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "A Tele Block spell has been cast on you by Runelite. It will expire in 2 minutes, 30 seconds.", "", 0); + timersPlugin.onChatMessage(chatMessage); + + ArgumentCaptor captor = ArgumentCaptor.forClass(InfoBox.class); + verify(infoBoxManager).addInfoBox(captor.capture()); + TimerTimer infoBox = (TimerTimer) captor.getValue(); + assertEquals(GameTimer.TELEBLOCK, infoBox.getTimer()); + assertEquals(Duration.ofSeconds(60 * 2 + 30), infoBox.getDuration()); + } + + @Test + public void testDivineBastion() + { + when(timersConfig.showDivine()).thenReturn(true); + ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "You drink some of your divine bastion potion.", "", 0); + timersPlugin.onChatMessage(chatMessage); + + ArgumentCaptor captor = ArgumentCaptor.forClass(InfoBox.class); + verify(infoBoxManager).addInfoBox(captor.capture()); + TimerTimer infoBox = (TimerTimer) captor.getValue(); + assertEquals(GameTimer.DIVINE_BASTION, infoBox.getTimer()); + } + + @Test + public void testDivineBattlemage() + { + when(timersConfig.showDivine()).thenReturn(true); + ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "You drink some of your divine battlemage potion.", "", 0); + timersPlugin.onChatMessage(chatMessage); + + ArgumentCaptor captor = ArgumentCaptor.forClass(InfoBox.class); + verify(infoBoxManager).addInfoBox(captor.capture()); + TimerTimer infoBox = (TimerTimer) captor.getValue(); + assertEquals(GameTimer.DIVINE_BATTLEMAGE, infoBox.getTimer()); + } + + @Test + public void testTransparentChatboxTb() + { + when(timersConfig.showTeleblock()).thenReturn(true); + ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "A Tele Block spell has been cast on you by Alexsuperfly. It will expire in 5 minutes.", "", 0); + timersPlugin.onChatMessage(chatMessage); + + ArgumentCaptor captor = ArgumentCaptor.forClass(InfoBox.class); + verify(infoBoxManager).addInfoBox(captor.capture()); + TimerTimer infoBox = (TimerTimer) captor.getValue(); + assertEquals(GameTimer.TELEBLOCK, infoBox.getTimer()); + assertEquals(Duration.ofMinutes(5), infoBox.getDuration()); + } + + @Test + public void testTransparentChatboxTbRemoved() + { + when(timersConfig.showTeleblock()).thenReturn(true); + ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "Your Tele Block has been removed because you killed Alexsuperfly.", "", 0); + timersPlugin.onChatMessage(chatMessage); + + verify(infoBoxManager, atLeastOnce()).removeIf(any()); + } + + @Test + public void testMageArena2TbFull() + { + when(timersConfig.showTeleblock()).thenReturn(true); + ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "A Tele Block spell has been cast on you. It will expire in 2 minutes.", "", 0); + timersPlugin.onChatMessage(chatMessage); + + ArgumentCaptor captor = ArgumentCaptor.forClass(InfoBox.class); + verify(infoBoxManager).addInfoBox(captor.capture()); + TimerTimer infoBox = (TimerTimer) captor.getValue(); + assertEquals(GameTimer.TELEBLOCK, infoBox.getTimer()); + assertEquals(Duration.ofMinutes(2), infoBox.getDuration()); + } + + @Test + public void testMageArena2TbHalf() + { + when(timersConfig.showTeleblock()).thenReturn(true); + ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "A Tele Block spell has been cast on you. It will expire in 1 minute.", "", 0); + timersPlugin.onChatMessage(chatMessage); + + ArgumentCaptor captor = ArgumentCaptor.forClass(InfoBox.class); + verify(infoBoxManager).addInfoBox(captor.capture()); + TimerTimer infoBox = (TimerTimer) captor.getValue(); + assertEquals(GameTimer.TELEBLOCK, infoBox.getTimer()); + assertEquals(Duration.ofMinutes(1), infoBox.getDuration()); + } + + @Test + public void testStamina() + { + when(timersConfig.showStamina()).thenReturn(true); + ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "You drink some of your stamina potion.", "", 0); + timersPlugin.onChatMessage(chatMessage); + + ArgumentCaptor captor = ArgumentCaptor.forClass(InfoBox.class); + verify(infoBoxManager).addInfoBox(captor.capture()); + TimerTimer infoBox = (TimerTimer) captor.getValue(); + assertEquals(GameTimer.STAMINA, infoBox.getTimer()); + assertEquals(Duration.ofMinutes(2), infoBox.getDuration()); + } + + @Test + public void testSireStunTimer() + { + when(timersConfig.showAbyssalSireStun()).thenReturn(true); + ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", "The Sire has been disorientated temporarily.", "", 0); + timersPlugin.onChatMessage(chatMessage); + + ArgumentCaptor captor = ArgumentCaptor.forClass(InfoBox.class); + verify(infoBoxManager).addInfoBox(captor.capture()); + TimerTimer infoBox = (TimerTimer) captor.getValue(); + assertEquals(GameTimer.ABYSSAL_SIRE_STUN, infoBox.getTimer()); + assertEquals(Duration.ofSeconds(30), infoBox.getDuration()); + } + + @Test + public void testEndurance() + { + when(timersConfig.showStamina()).thenReturn(true); + + ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "Your Ring of endurance doubles the duration of your stamina potion's effect.", "", 0); + timersPlugin.onChatMessage(chatMessage); + + chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "You drink some of your stamina potion.", "", 0); + timersPlugin.onChatMessage(chatMessage); + + ArgumentCaptor captor = ArgumentCaptor.forClass(InfoBox.class); + verify(infoBoxManager).addInfoBox(captor.capture()); + TimerTimer infoBox = (TimerTimer) captor.getValue(); + assertEquals(GameTimer.STAMINA, infoBox.getTimer()); + assertEquals(Duration.ofMinutes(4), infoBox.getDuration()); + + // unwield ring + timersPlugin.onItemContainerChanged(new ItemContainerChanged(InventoryID.EQUIPMENT.getId(), mock(ItemContainer.class))); + // some time has elapsed in the test; this should be just under 2 mins + int mins = (int) infoBox.getDuration().toMinutes(); + assertTrue(mins == 1 || mins == 2); + } + + @Test + public void testTzhaarTimer() + { + when(timersConfig.showTzhaarTimers()).thenReturn(true); + when(client.getMapRegions()).thenReturn(new int[]{TimersPlugin.FIGHT_CAVES_REGION_ID}); + + class InstantRef + { + Instant i; + } + + InstantRef startTime = new InstantRef(); + when(timersConfig.tzhaarStartTime()).then(a -> startTime.i); + doAnswer((Answer) invocationOnMock -> + { + Object argument = invocationOnMock.getArguments()[0]; + startTime.i = (Instant) argument; + return null; + }).when(timersConfig).tzhaarStartTime(nullable(Instant.class)); + + InstantRef lastTime = new InstantRef(); + when(timersConfig.tzhaarLastTime()).then(a -> lastTime.i); + doAnswer((Answer) invocationOnMock -> + { + Object argument = invocationOnMock.getArguments()[0]; + lastTime.i = (Instant) argument; + return null; + }).when(timersConfig).tzhaarLastTime(nullable(Instant.class)); + + // test timer creation: verify the infobox was added and that it is an ElapsedTimer + ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", "Wave: 1", "", 0); + timersPlugin.onChatMessage(chatMessage); + ArgumentCaptor captor = ArgumentCaptor.forClass(InfoBox.class); + verify(infoBoxManager, times(1)).addInfoBox(captor.capture()); + assertTrue(captor.getValue() instanceof ElapsedTimer); + + // test timer pause: verify the added ElapsedTimer has a non-null lastTime + chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", "The Inferno has been paused. You may now log out.", "", 0); + timersPlugin.onChatMessage(chatMessage); + verify(infoBoxManager, times(1)).removeInfoBox(captor.capture()); + verify(infoBoxManager, times(2)).addInfoBox(captor.capture()); + assertTrue(captor.getValue() instanceof ElapsedTimer); + ElapsedTimer timer = (ElapsedTimer) captor.getValue(); + assertNotEquals(timer.getLastTime(), null); + Instant oldTime = ((ElapsedTimer) captor.getValue()).getStartTime(); + + // test timer unpause: verify the last time is null after being unpaused + chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", "Wave: 2", "", 0); + timersPlugin.onChatMessage(chatMessage); + verify(infoBoxManager, times(2)).removeInfoBox(captor.capture()); + verify(infoBoxManager, times(3)).addInfoBox(captor.capture()); + assertTrue(captor.getValue() instanceof ElapsedTimer); + timer = (ElapsedTimer) captor.getValue(); + assertNull(timer.getLastTime()); + + // test timer remove: verify the infobox was removed (and no more were added) + chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", "You have been defeated!", "", 0); + timersPlugin.onChatMessage(chatMessage); + verify(infoBoxManager, times(3)).removeInfoBox(captor.capture()); + verify(infoBoxManager, times(3)).addInfoBox(captor.capture()); + } + + @Test + public void testInfernoTimerStartOffset() + { + when(timersConfig.showTzhaarTimers()).thenReturn(true); + when(client.getMapRegions()).thenReturn(new int[]{TimersPlugin.INFERNO_REGION_ID}); + + class InstantRef + { + Instant i; + } + + InstantRef startTime = new InstantRef(); + when(timersConfig.tzhaarStartTime()).then(a -> startTime.i); + doAnswer((Answer) invocationOnMock -> + { + Object argument = invocationOnMock.getArguments()[0]; + startTime.i = (Instant) argument; + return null; + }).when(timersConfig).tzhaarStartTime(nullable(Instant.class)); + + ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", "Wave: 1", "", 0); + timersPlugin.onChatMessage(chatMessage); + + ArgumentCaptor captor = ArgumentCaptor.forClass(InfoBox.class); + verify(infoBoxManager, times(1)).addInfoBox(captor.capture()); + assertTrue(captor.getValue() instanceof ElapsedTimer); + ElapsedTimer timer = (ElapsedTimer) captor.getValue(); + assertEquals("00:06", timer.getText()); + } +} \ No newline at end of file diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/timetracking/farming/FarmingTrackerTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/timetracking/farming/FarmingTrackerTest.java new file mode 100644 index 0000000000..f407fd0a34 --- /dev/null +++ b/runelite-client/src/test/java/net/runelite/client/plugins/timetracking/farming/FarmingTrackerTest.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2021, Adam + * 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.timetracking.farming; + +import com.google.inject.Guice; +import com.google.inject.Inject; +import com.google.inject.testing.fieldbinder.Bind; +import com.google.inject.testing.fieldbinder.BoundFieldModule; +import java.util.EnumSet; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.Player; +import net.runelite.api.Varbits; +import net.runelite.api.WorldType; +import net.runelite.client.Notifier; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.config.RuneScapeProfile; +import net.runelite.client.config.RuneScapeProfileType; +import net.runelite.client.game.ItemManager; +import net.runelite.client.plugins.timetracking.TimeTrackingConfig; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class FarmingTrackerTest +{ + @Inject + private FarmingTracker farmingTracker; + + @Mock + @Bind + private Client client; + + @Mock + @Bind + private ItemManager itemManager; + + @Mock + @Bind + private ConfigManager configManager; + + @Mock + @Bind + private TimeTrackingConfig config; + + @Mock + @Bind + private FarmingWorld farmingWorld; + + @Mock + @Bind + private Notifier notifier; + + @Before + public void before() + { + Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); + + when(client.getGameState()).thenReturn(GameState.LOGGED_IN); + when(client.getWorldType()).thenReturn(EnumSet.noneOf(WorldType.class)); + + Player player = mock(Player.class); + when(player.getName()).thenReturn("Adam"); + when(client.getLocalPlayer()).thenReturn(player); + } + + @Test(expected = IllegalStateException.class) + public void testEmptyNotification() + { + RuneScapeProfile runeScapeProfile = new RuneScapeProfile("Adam", RuneScapeProfileType.STANDARD, null, null); + + PatchPrediction patchPrediction = new PatchPrediction(Produce.EMPTY_COMPOST_BIN, CropState.EMPTY, 0L, 0, 0); + FarmingRegion region = new FarmingRegion("Ardougne", 10548, false, + new FarmingPatch("North", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT), + new FarmingPatch("South", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT), + new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER), + new FarmingPatch("", Varbits.FARMING_4774, PatchImplementation.HERB), + new FarmingPatch("", Varbits.FARMING_4775, PatchImplementation.COMPOST) + ); + FarmingPatch patch = region.getPatches()[4]; + patch.setRegion(region); + farmingTracker.sendNotification(runeScapeProfile, patchPrediction, patch); + } + + @Test + public void testHarvestableNotification() + { + RuneScapeProfile runeScapeProfile = new RuneScapeProfile("Adam", RuneScapeProfileType.STANDARD, null, null); + + PatchPrediction patchPrediction = new PatchPrediction(Produce.RANARR, CropState.HARVESTABLE, 0L, 0, 0); + FarmingRegion region = new FarmingRegion("Ardougne", 10548, false, + new FarmingPatch("North", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT), + new FarmingPatch("South", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT), + new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER), + new FarmingPatch("", Varbits.FARMING_4774, PatchImplementation.HERB), + new FarmingPatch("", Varbits.FARMING_4775, PatchImplementation.COMPOST) + ); + FarmingPatch patch = region.getPatches()[3]; + patch.setRegion(region); + farmingTracker.sendNotification(runeScapeProfile, patchPrediction, patch); + + verify(notifier).notify("Your Ranarr is ready to harvest in Ardougne."); + } +} \ No newline at end of file diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/xpglobes/XpGlobesPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/xpglobes/XpGlobesPluginTest.java new file mode 100644 index 0000000000..bfc5de4b0d --- /dev/null +++ b/runelite-client/src/test/java/net/runelite/client/plugins/xpglobes/XpGlobesPluginTest.java @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2021, Wright + * 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.xpglobes; + +import com.google.inject.Guice; +import com.google.inject.testing.fieldbinder.Bind; +import com.google.inject.testing.fieldbinder.BoundFieldModule; +import javax.inject.Inject; +import net.runelite.api.Experience; +import net.runelite.api.Skill; +import net.runelite.api.events.StatChanged; +import net.runelite.client.plugins.xptracker.XpTrackerService; +import net.runelite.client.ui.overlay.OverlayManager; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.when; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class XpGlobesPluginTest +{ + private static final int VIRTUAL_LEVEL_TOTAL_XP = Experience.getXpForLevel(Experience.MAX_REAL_LEVEL + 1); + + @Inject + private XpGlobesPlugin xpGlobesPlugin; + + @Mock + @Bind + private OverlayManager overlayManager; + + @Mock + @Bind + private XpGlobesOverlay xpGlobesOverlay; + + @Mock + @Bind + private XpTrackerService xpTrackerService; + + @Mock + @Bind + private XpGlobesConfig xpGlobesConfig; + + @Before + public void before() + { + Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); + + statChanged(VIRTUAL_LEVEL_TOTAL_XP, Skill.AGILITY); + assertTrue(xpGlobesPlugin.getXpGlobes().isEmpty()); + } + + @Test + public void testVirtualLevelInGlobeIsNotShownByDefault() + { + when(xpGlobesConfig.showVirtualLevel()).thenReturn(false); + + statChanged(VIRTUAL_LEVEL_TOTAL_XP + 1, Skill.AGILITY); + + assertEquals(Experience.MAX_REAL_LEVEL, xpGlobesPlugin.getXpGlobes().get(0).getCurrentLevel()); + } + + @Test + public void testVirtualLevelInGlobeIsShownWhenConfigured() + { + when(xpGlobesConfig.showVirtualLevel()).thenReturn(true); + + statChanged(VIRTUAL_LEVEL_TOTAL_XP + 1, Skill.AGILITY); + + assertEquals(Experience.getLevelForXp(VIRTUAL_LEVEL_TOTAL_XP + 1), xpGlobesPlugin.getXpGlobes().get(0).getCurrentLevel()); + } + + @Test + public void testGlobeIsNotShownWhenHideMaxAndShowVirtualLevelConfigured() + { + when(xpGlobesConfig.hideMaxed()).thenReturn(true); + lenient().when(xpGlobesConfig.showVirtualLevel()).thenReturn(true); + + statChanged(VIRTUAL_LEVEL_TOTAL_XP + 1, Skill.AGILITY); + + assertTrue(xpGlobesPlugin.getXpGlobes().isEmpty()); + } + + @Test + public void testGlobeIsNotShownWhenHideMaxConfigured() + { + when(xpGlobesConfig.hideMaxed()).thenReturn(true); + + statChanged(VIRTUAL_LEVEL_TOTAL_XP + 1, Skill.AGILITY); + + assertTrue(xpGlobesPlugin.getXpGlobes().isEmpty()); + } + + @Test + public void testGlobeIsShownOnXpGainBelowMaxWhenHideMaxConfigured() + { + lenient().when(xpGlobesConfig.hideMaxed()).thenReturn(true); + + int totalXp = 1; + statChanged(totalXp, Skill.FARMING); + assertTrue(xpGlobesPlugin.getXpGlobes().isEmpty()); + + statChanged(totalXp + 150, Skill.FARMING); + + assertEquals(Experience.getLevelForXp(totalXp + 150), xpGlobesPlugin.getXpGlobes().get(0).getCurrentLevel()); + } + + @Test + public void testStatChangesFromBoostDoNotAffectXpGlobes() + { + statChanged(VIRTUAL_LEVEL_TOTAL_XP, Skill.AGILITY, 5); + + assertTrue(xpGlobesPlugin.getXpGlobes().isEmpty()); + } + + private void statChanged(int totalXp, Skill skill) + { + statChanged(totalXp, skill, 0); + } + + private void statChanged(int totalXp, Skill skill, int boostedLevel) + { + // A statChanged event uses the max real level + int statChangedLevel = Math.min(Experience.getLevelForXp(totalXp), Experience.MAX_REAL_LEVEL); + + StatChanged firstStatChangedEvent = new StatChanged( + skill, + totalXp, + statChangedLevel, + boostedLevel + ); + + // The first xp change is cached + xpGlobesPlugin.onStatChanged(firstStatChangedEvent); + } +} diff --git a/runelite-client/src/test/java/net/runelite/client/util/ColorUtilTest.java b/runelite-client/src/test/java/net/runelite/client/util/ColorUtilTest.java new file mode 100644 index 0000000000..8a531b18bc --- /dev/null +++ b/runelite-client/src/test/java/net/runelite/client/util/ColorUtilTest.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2018, Jordan Atwood + * 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.util; + +import com.google.common.collect.ImmutableMap; +import java.awt.Color; +import java.util.Map; +import static org.junit.Assert.assertEquals; +import org.junit.Test; + +public class ColorUtilTest +{ + private static final Map COLOR_HEXSTRING_MAP = new ImmutableMap.Builder(). + put(Color.BLACK, "000000"). + put(new Color(0x1), "000001"). + put(new Color(0x100000), "100000"). + put(Color.RED, "ff0000"). + put(Color.GREEN, "00ff00"). + put(Color.BLUE, "0000ff"). + put(new Color(0xA1B2C3), "a1b2c3"). + put(Color.WHITE, "ffffff").build(); + + private static final Map COLOR_ALPHA_HEXSTRING_MAP = ImmutableMap.of( + new Color(0x00000000, true), "00000000", + new Color(0xA1B2C3D4, true), "a1b2c3d4" + ); + + @Test + public void colorTag() + { + COLOR_HEXSTRING_MAP.forEach((color, hex) -> + { + assertEquals("", ColorUtil.colorTag(color)); + }); + } + + @Test + public void prependColorTag() + { + COLOR_HEXSTRING_MAP.forEach((color, hex) -> + { + assertEquals("test", ColorUtil.prependColorTag("test", color)); + assertEquals("", ColorUtil.prependColorTag("", color)); + }); + + assertEquals("94/99", ColorUtil.prependColorTag("94" + ColorUtil.prependColorTag("/99", Color.WHITE), Color.RED)); + } + + @Test + public void wrapWithColorTag() + { + COLOR_HEXSTRING_MAP.forEach((color, hex) -> + { + assertEquals("test", ColorUtil.wrapWithColorTag("test", color)); + assertEquals("", ColorUtil.wrapWithColorTag("", color)); + }); + } + + @Test + public void toHexColor() + { + COLOR_HEXSTRING_MAP.forEach((color, hex) -> + { + assertEquals("#" + hex, ColorUtil.toHexColor(color)); + }); + } + + @Test + public void colorWithAlpha() + { + int[] alpha = {73}; + + COLOR_HEXSTRING_MAP.forEach((color, hex) -> + { + assertEquals(new Color(color.getRed(), color.getGreen(), color.getBlue(), alpha[0]), + ColorUtil.colorWithAlpha(color, alpha[0])); + alpha[0] += 73; + alpha[0] %= 255; + }); + + COLOR_ALPHA_HEXSTRING_MAP.forEach((color, hex) -> + { + assertEquals(new Color(color.getRed(), color.getGreen(), color.getBlue(), alpha[0]), + ColorUtil.colorWithAlpha(color, alpha[0])); + alpha[0] += 73; + alpha[0] %= 255; + }); + } + + @Test + public void colorLerp() + { + assertEquals(Color.WHITE, ColorUtil.colorLerp(Color.WHITE, Color.WHITE, 0.9)); + assertEquals(new Color(128, 128, 128), ColorUtil.colorLerp(Color.BLACK, Color.WHITE, 0.5)); + assertEquals(Color.BLACK, ColorUtil.colorLerp(Color.BLACK, Color.CYAN, 0)); + assertEquals(Color.CYAN, ColorUtil.colorLerp(Color.BLACK, Color.CYAN, 1)); + } + + @Test + public void colorToHexCode() + { + COLOR_HEXSTRING_MAP.forEach((color, hex) -> + { + assertEquals(hex, ColorUtil.colorToHexCode(color)); + }); + } +} diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/EntityHiderBridgeMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/EntityHiderBridgeMixin.java index 23097e1a80..0327b9473e 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/EntityHiderBridgeMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/EntityHiderBridgeMixin.java @@ -41,10 +41,10 @@ public abstract class EntityHiderBridgeMixin implements RSClient public static boolean isHidingEntities; @Inject - public static boolean hidePlayers; + public static boolean hideOthers; @Inject - public static boolean hidePlayers2D; + public static boolean hideOthers2D; @Inject public static boolean hideFriends; @@ -52,6 +52,9 @@ public abstract class EntityHiderBridgeMixin implements RSClient @Inject public static boolean hideClanMates; + @Inject + public static boolean hideIgnores; + @Inject public static boolean hideLocalPlayer; @@ -76,18 +79,9 @@ public abstract class EntityHiderBridgeMixin implements RSClient @Inject public static boolean hideDeadNPCs; - @Inject - public static HashMap hiddenNpcsName = new HashMap<>(); - - @Inject - public static HashMap hiddenNpcsDeath = new HashMap<>(); - @Inject public static List hideSpecificPlayers = new ArrayList<>(); - @Inject - public static Set blacklistDeadNpcs = new HashSet<>(); - @Inject @Override public void setIsHidingEntities(boolean state) @@ -97,16 +91,16 @@ public abstract class EntityHiderBridgeMixin implements RSClient @Inject @Override - public void setPlayersHidden(boolean state) + public void setOthersHidden(boolean state) { - hidePlayers = state; + hideOthers = state; } @Inject @Override - public void setPlayersHidden2D(boolean state) + public void setOthersHidden2D(boolean state) { - hidePlayers2D = state; + hideOthers2D = state; } @Inject @@ -123,6 +117,13 @@ public abstract class EntityHiderBridgeMixin implements RSClient hideClanMates = state; } + @Inject + @Override + public void setIgnoresHidden(boolean state) + { + hideIgnores = state; + } + @Inject @Override public void setLocalPlayerHidden(boolean state) @@ -151,78 +152,6 @@ public abstract class EntityHiderBridgeMixin implements RSClient hideNPCs2D = state; } - @Inject - @Override - public void addHiddenNpcName(String npc) - { - npc = npc.toLowerCase(); - int i = hiddenNpcsName.getOrDefault(npc, 0); - if (i == Integer.MAX_VALUE) - { - throw new RuntimeException("NPC name " + npc + " has been hidden Integer.MAX_VALUE times, is something wrong?"); - } - - hiddenNpcsName.put(npc, ++i); - } - - @Inject - @Override - public void removeHiddenNpcName(String npc) - { - npc = npc.toLowerCase(); - int i = hiddenNpcsName.getOrDefault(npc, 0); - if (i == 0) - { - return; - } - - hiddenNpcsName.put(npc, --i); - } - - @Inject - @Override - public void forciblyUnhideNpcName(String npc) - { - npc = npc.toLowerCase(); - hiddenNpcsName.put(npc, 0); - } - - @Inject - @Override - public void addHiddenNpcDeath(String npc) - { - npc = npc.toLowerCase(); - int i = hiddenNpcsDeath.getOrDefault(npc, 0); - if (i == Integer.MAX_VALUE) - { - throw new RuntimeException("NPC death " + npc + " has been hidden Integer.MAX_VALUE times, is something wrong?"); - } - - hiddenNpcsDeath.put(npc, ++i); - } - - @Inject - @Override - public void removeHiddenNpcDeath(String npc) - { - npc = npc.toLowerCase(); - int i = hiddenNpcsDeath.getOrDefault(npc, 0); - if (i == 0) - { - return; - } - - hiddenNpcsDeath.put(npc, --i); - } - - @Inject - @Override - public void forciblyUnhideNpcDeath(String npc) - { - npc = npc.toLowerCase(); - hiddenNpcsDeath.put(npc, 0); - } - @Inject @Override public void setHideSpecificPlayers(List players) @@ -230,13 +159,6 @@ public abstract class EntityHiderBridgeMixin implements RSClient hideSpecificPlayers = players; } - @Inject - @Override - public void setBlacklistDeadNpcs(Set blacklist) - { - blacklistDeadNpcs = blacklist; - } - @Inject @Override public void setPetsHidden(boolean state) diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/EntityHiderMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/EntityHiderMixin.java index 4734e790b4..e99e8f9659 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/EntityHiderMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/EntityHiderMixin.java @@ -36,10 +36,10 @@ import net.runelite.api.mixins.Shadow; import net.runelite.api.util.Text; import net.runelite.rs.api.RSActor; import net.runelite.rs.api.RSClient; -import net.runelite.rs.api.RSRenderable; import net.runelite.rs.api.RSNPC; import net.runelite.rs.api.RSPlayer; import net.runelite.rs.api.RSProjectile; +import net.runelite.rs.api.RSRenderable; import net.runelite.rs.api.RSScene; @Mixin(RSScene.class) @@ -51,11 +51,11 @@ public abstract class EntityHiderMixin implements RSScene @Shadow("isHidingEntities") private static boolean isHidingEntities; - @Shadow("hidePlayers") - private static boolean hidePlayers; + @Shadow("hideOthers") + private static boolean hideOthers; - @Shadow("hidePlayers2D") - private static boolean hidePlayers2D; + @Shadow("hideOthers2D") + private static boolean hideOthers2D; @Shadow("hideFriends") private static boolean hideFriends; @@ -69,21 +69,15 @@ public abstract class EntityHiderMixin implements RSScene @Shadow("hideLocalPlayer2D") private static boolean hideLocalPlayer2D; + @Shadow("hideIgnores") + private static boolean hideIgnores; + @Shadow("hideNPCs") private static boolean hideNPCs; - @Shadow("hiddenNpcsName") - private static HashMap hiddenNpcsName; - - @Shadow("hiddenNpcsDeath") - private static HashMap hiddenNpcsDeath; - @Shadow("hideSpecificPlayers") private static List hideSpecificPlayers; - @Shadow("blacklistDeadNpcs") - private static Set blacklistDeadNpcs; - @Shadow("hideNPCs2D") private static boolean hideNPCs2D; @@ -140,10 +134,17 @@ public abstract class EntityHiderMixin implements RSScene if (entity instanceof RSPlayer) { - boolean local = drawingUI ? hideLocalPlayer2D : hideLocalPlayer; - boolean other = drawingUI ? hidePlayers2D : hidePlayers; - boolean isLocalPlayer = entity == client.getLocalPlayer(); RSPlayer player = (RSPlayer) entity; + RSPlayer local = client.getLocalPlayer(); + if (player.getName() == null) + { + return true; + } + + if (player == local) + { + return drawingUI ? !hideLocalPlayer2D : !hideLocalPlayer; + } for (String name : hideSpecificPlayers) { @@ -156,59 +157,43 @@ public abstract class EntityHiderMixin implements RSScene } } - if (isLocalPlayer ? local : other) + if (hideAttackers && player.getInteracting() == local) { - if (!hideAttackers) - { - if (player.getInteracting() == client.getLocalPlayer()) - { - return true; - } - } - - if (player.getName() == null) - { - // player.isFriend() and player.isClanMember() npe when the player has a null name - return false; - } - - return (!hideFriends && player.isFriend()) || - (!isLocalPlayer && !hideClanMates && player.isFriendsChatMember()); + return false; } + + if (player.isFriend()) + { + return !hideFriends; + } + + if (player.isFriendsChatMember()) + { + return !hideClanMates; + } + + if (client.getFriendManager().isIgnored(player.getRsName())) + { + return !hideIgnores; + } + + return drawingUI ? !hideOthers2D : !hideOthers; } else if (entity instanceof RSNPC) { RSNPC npc = (RSNPC) entity; - if (!hideAttackers) - { - if (npc.getInteracting() == client.getLocalPlayer()) - { - return true; - } - } - - if (hidePets) - { - if (npc.getComposition().isFollower()) - { - return false; - } - } - - if (hideDeadNPCs && npc.getHealthRatio() == 0 && !blacklistDeadNpcs.contains(npc.getId())) + if (npc.isDead() && hideDeadNPCs) { return false; } - if (npc.getName() != null && - hiddenNpcsName.getOrDefault(Text.standardize(npc.getName().toLowerCase()), 0) > 0) + if (npc.getComposition().isFollower() && npc.getIndex() != client.getFollowerIndex() && hidePets) { return false; } - if (npc.getName() != null && npc.getHealthRatio() == 0 && - hiddenNpcsDeath.getOrDefault(Text.standardize(npc.getName().toLowerCase()), 0) > 0) + if (npc.getInteracting() == client.getLocalPlayer() && hideAttackers) { return false; } diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java index 644a1346d3..9fb793edef 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java @@ -536,17 +536,36 @@ public abstract class RSClientMixin implements RSClient } @Inject - public void addChatMessage(int type, String name, String message, String sender) + public MessageNode addChatMessage(ChatMessageType type, String name, String message, String sender, boolean postEvent) { assert this.isClientThread() : "addChatMessage must be called on client thread"; - addRSChatMessage(type, name, message, sender); + copy$addChatMessage(type.getType(), name, message, sender); + + Logger logger = client.getLogger(); + if (logger.isDebugEnabled()) + { + logger.debug("Chat message type {}: {}", type.name(), message); + } + + // Get the message node which was added + @SuppressWarnings("unchecked") Map chatLineMap = client.getChatLineMap(); + RSChatChannel chatLineBuffer = chatLineMap.get(type.getType()); + MessageNode messageNode = chatLineBuffer.getLines()[0]; + + if (postEvent) + { + final ChatMessage chatMessage = new ChatMessage(messageNode, type, name, message, sender, messageNode.getTimestamp()); + client.getCallbacks().post(chatMessage); + } + + return messageNode; } @Inject @Override - public void addChatMessage(ChatMessageType type, String name, String message, String sender) + public MessageNode addChatMessage(ChatMessageType type, String name, String message, String sender) { - addChatMessage(type.getType(), name, message, sender); + return addChatMessage(type, name, message, sender, true); } @Inject @@ -1388,13 +1407,6 @@ public abstract class RSClientMixin implements RSClient @Replace("menuAction") static void copy$menuAction(int param0, int param1, int opcode, int id, String option, String target, int canvasX, int canvasY) { - boolean authentic = true; - if (target != null && target.startsWith("!AUTHENTIC")) - { - authentic = false; - target = target.substring(10); - } - /* Along the way, the RuneScape client may change a menuAction by incrementing it with 2000. * I have no idea why, but it does. Their code contains the same conditional statement. */ @@ -1403,17 +1415,13 @@ public abstract class RSClientMixin implements RSClient opcode -= 2000; } - final MenuOptionClicked menuOptionClicked = new MenuOptionClicked( - option, - target, - id, - opcode, - param0, - param1, - false, - authentic, - client.getMouseCurrentButton() - ); + final MenuOptionClicked menuOptionClicked = new MenuOptionClicked(); + menuOptionClicked.setActionParam(param0); + menuOptionClicked.setMenuOption(option); + menuOptionClicked.setMenuTarget(target); + menuOptionClicked.setMenuAction(MenuAction.of(opcode)); + menuOptionClicked.setId(id); + menuOptionClicked.setWidgetId(param1); client.getCallbacks().post(menuOptionClicked); @@ -1425,15 +1433,15 @@ public abstract class RSClientMixin implements RSClient if (printMenuActions) { client.getLogger().info( - "|MenuAction|: MenuOption={} MenuTarget={} Id={} Opcode={} Param0={} Param1={} CanvasX={} CanvasY={} Authentic={}", - menuOptionClicked.getOption(), menuOptionClicked.getTarget(), menuOptionClicked.getIdentifier(), - menuOptionClicked.getOpcode(), menuOptionClicked.getActionParam(), menuOptionClicked.getActionParam1(), - canvasX, canvasY, authentic + "|MenuAction|: MenuOption={} MenuTarget={} Id={} Opcode={} Param0={} Param1={} CanvasX={} CanvasY={}", + menuOptionClicked.getMenuOption(), menuOptionClicked.getMenuTarget(), menuOptionClicked.getId(), + menuOptionClicked.getMenuAction(), menuOptionClicked.getActionParam(), menuOptionClicked.getWidgetId(), + canvasX, canvasY ); } - copy$menuAction(menuOptionClicked.getActionParam(), menuOptionClicked.getActionParam1(), menuOptionClicked.getOpcode(), - menuOptionClicked.getIdentifier(), menuOptionClicked.getOption(), menuOptionClicked.getTarget(), canvasX, canvasY); + copy$menuAction(menuOptionClicked.getActionParam(), menuOptionClicked.getWidgetId(), menuOptionClicked.getMenuAction().getId(), + menuOptionClicked.getId(), menuOptionClicked.getMenuOption(), menuOptionClicked.getMenuTarget(), canvasX, canvasY); } @Override @@ -1442,7 +1450,7 @@ public abstract class RSClientMixin implements RSClient { assert isClientThread(); - client.sendMenuAction(param0, param1, opcode, identifier, option, "!AUTHENTIC" + target, 658, 384); + client.sendMenuAction(param0, param1, opcode, identifier, option, target, 658, 384); } @FieldHook("Login_username") @@ -1495,14 +1503,18 @@ public abstract class RSClientMixin implements RSClient client.getCallbacks().updateNpcs(); } - @Inject - @MethodHook(value = "addChatMessage", end = true) - public static void onAddChatMessage(int type, String name, String message, String sender) + @SuppressWarnings("InfiniteRecursion") + @Copy("addChatMessage") + @Replace("addChatMessage") + public static void copy$addChatMessage(int type, String name, String message, String sender) { + copy$addChatMessage(type, name, message, sender); + Logger logger = client.getLogger(); if (logger.isDebugEnabled()) { - logger.debug("Chat message type {}: {}", ChatMessageType.of(type), message); + ChatMessageType msgType = ChatMessageType.of(type); + logger.debug("Chat message type {}: {}", msgType == ChatMessageType.UNKNOWN ? String.valueOf(type) : msgType.name(), message); } // Get the message node which was added diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSDynamicObjectMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSDynamicObjectMixin.java index e819d6a8cf..2b36064e99 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSDynamicObjectMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSDynamicObjectMixin.java @@ -24,6 +24,8 @@ */ package net.runelite.mixins; +import net.runelite.api.DialogOption; +import net.runelite.api.events.DialogProcessed; import net.runelite.api.events.DynamicObjectAnimationChanged; import net.runelite.api.mixins.Copy; import net.runelite.api.mixins.FieldHook; @@ -100,4 +102,23 @@ public abstract class RSDynamicObjectMixin implements RSDynamicObject { return (int) (getSequenceDefinition() == null ? -1 : getSequenceDefinition().getHash()); } + + @Inject + @MethodHook("resumePauseWidget") + public static void onDialogProcessed(int widgetUid, int menuIndex) + { + DialogOption dialogOption = DialogOption.of(widgetUid, menuIndex); + if (dialogOption != null) + { + client.getCallbacks().post(new DialogProcessed(dialogOption)); + } + else + { + client.getLogger().debug( + "Unknown or unmapped dialog option for widgetUid: {} and menuIndex {}", + widgetUid, + menuIndex + ); + } + } } diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSGameShellMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSGameEngineMixin.java similarity index 96% rename from runelite-mixins/src/main/java/net/runelite/mixins/RSGameShellMixin.java rename to runelite-mixins/src/main/java/net/runelite/mixins/RSGameEngineMixin.java index 221063ce75..2573152106 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSGameShellMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSGameEngineMixin.java @@ -35,10 +35,10 @@ import net.runelite.api.mixins.Mixin; import net.runelite.api.mixins.Replace; import net.runelite.api.mixins.Shadow; import net.runelite.rs.api.RSClient; -import net.runelite.rs.api.RSGameShell; +import net.runelite.rs.api.RSGameEngine; -@Mixin(RSGameShell.class) -public abstract class RSGameShellMixin implements RSGameShell +@Mixin(RSGameEngine.class) +public abstract class RSGameEngineMixin implements RSGameEngine { @Shadow("client") private static RSClient client; diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSNPCMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSNPCMixin.java index 5d29390a45..c90105f7e4 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSNPCMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSNPCMixin.java @@ -111,7 +111,18 @@ public abstract class RSNPCMixin implements RSNPC } else if (this.getId() != -1) { - client.getCallbacks().post(new NpcChanged(this, composition)); + RSNPCComposition oldComposition = getComposition(); + if (oldComposition == null) + { + return; + } + + if (composition.getId() == oldComposition.getId()) + { + return; + } + + client.getCallbacks().postDeferred(new NpcChanged(this, oldComposition)); } } diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSPlayerMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSPlayerMixin.java index 2200710ada..80c4f3fcfd 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSPlayerMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSPlayerMixin.java @@ -28,26 +28,14 @@ import java.awt.Polygon; import java.awt.Shape; import java.util.ArrayList; import net.runelite.api.HeadIcon; -import static net.runelite.api.HeadIcon.MAGIC; -import static net.runelite.api.HeadIcon.MELEE; -import static net.runelite.api.HeadIcon.RANGED; -import static net.runelite.api.HeadIcon.REDEMPTION; -import static net.runelite.api.HeadIcon.RETRIBUTION; -import static net.runelite.api.HeadIcon.SMITE; import net.runelite.api.Model; import net.runelite.api.Perspective; import net.runelite.api.SkullIcon; -import static net.runelite.api.SkullIcon.DEAD_MAN_FIVE; -import static net.runelite.api.SkullIcon.DEAD_MAN_FOUR; -import static net.runelite.api.SkullIcon.DEAD_MAN_ONE; -import static net.runelite.api.SkullIcon.DEAD_MAN_THREE; -import static net.runelite.api.SkullIcon.DEAD_MAN_TWO; -import static net.runelite.api.SkullIcon.SKULL; -import static net.runelite.api.SkullIcon.SKULL_FIGHT_PIT; +import static net.runelite.api.SkullIcon.*; import net.runelite.api.coords.LocalPoint; +import net.runelite.api.events.OverheadPrayerChanged; import net.runelite.api.events.PlayerChanged; -import net.runelite.api.events.player.headicon.OverheadPrayerChanged; -import net.runelite.api.events.player.headicon.PlayerSkullChanged; +import net.runelite.api.events.PlayerSkullChanged; import net.runelite.api.mixins.Copy; import net.runelite.api.mixins.FieldHook; import net.runelite.api.mixins.Inject; @@ -71,10 +59,10 @@ public abstract class RSPlayerMixin implements RSPlayer private boolean friended; @Inject - private int oldHeadIcon = -1; + private int oldHeadIcon = -2; @Inject - private int oldSkullIcon = -1; + private int oldSkullIcon = -2; @Inject @Override @@ -101,14 +89,11 @@ public abstract class RSPlayerMixin implements RSPlayer @FieldHook("headIconPrayer") public void prayerChanged(int idx) { - if (!(getRsOverheadIcon() == -1 && oldHeadIcon == -1)) + if (getRsOverheadIcon() != oldHeadIcon) { final HeadIcon headIcon = getHeadIcon(getRsOverheadIcon()); - if (getRsOverheadIcon() != oldHeadIcon) - { - client.getCallbacks().post( - new OverheadPrayerChanged(this, getHeadIcon(oldHeadIcon), headIcon)); - } + client.getCallbacks().post( + new OverheadPrayerChanged(this, getHeadIcon(oldHeadIcon), headIcon)); } oldHeadIcon = getRsOverheadIcon(); } @@ -143,23 +128,12 @@ public abstract class RSPlayerMixin implements RSPlayer @Inject private HeadIcon getHeadIcon(int overheadIcon) { - switch (overheadIcon) + if (overheadIcon == -1) { - case 0: - return MELEE; - case 1: - return RANGED; - case 2: - return MAGIC; - case 3: - return RETRIBUTION; - case 4: - return SMITE; - case 5: - return REDEMPTION; - default: - return null; + return null; } + + return HeadIcon.values()[overheadIcon]; } @Inject diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSWidgetMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSWidgetMixin.java index c940376ba4..3bc5fb52ef 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSWidgetMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSWidgetMixin.java @@ -28,6 +28,7 @@ import net.runelite.api.HashTable; import net.runelite.api.Node; import net.runelite.api.Point; import net.runelite.api.WidgetNode; +import net.runelite.api.events.WidgetHiddenChanged; import net.runelite.api.events.WidgetPositioned; import net.runelite.api.mixins.Copy; import net.runelite.api.mixins.FieldHook; @@ -74,6 +75,48 @@ public abstract class RSWidgetMixin implements RSWidget rl$y = -1; } + @Inject + @Override + public void broadcastHidden(boolean hidden) + { + WidgetHiddenChanged event = new WidgetHiddenChanged(); + event.setWidget(this); + event.setHidden(hidden); + + client.getCallbacks().post(event); + + RSWidget[] children = getChildren(); + + if (children != null) + { + // recursive through children + for (RSWidget child : children) + { + // if the widget is hidden it will not magically unhide from its parent changing + if (child == null || child.isSelfHidden()) + { + continue; + } + + child.broadcastHidden(hidden); + } + } + + // make sure we iterate nested children as well + // cannot be null + Widget[] nestedChildren = getNestedChildren(); + + for (Widget nestedChild : nestedChildren) + { + if (nestedChild == null || nestedChild.isSelfHidden()) + { + continue; + } + + ((RSWidget) nestedChild).broadcastHidden(hidden); + } + } + @Inject @Override public void setRenderParentId(int parentId) diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/StretchedModeMaxSizeMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/StretchedModeMaxSizeMixin.java index da1a9e6fc0..de0638e6bd 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/StretchedModeMaxSizeMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/StretchedModeMaxSizeMixin.java @@ -6,10 +6,10 @@ import net.runelite.api.mixins.Mixin; import net.runelite.api.mixins.Replace; import net.runelite.api.mixins.Shadow; import net.runelite.rs.api.RSClient; -import net.runelite.rs.api.RSGameShell; +import net.runelite.rs.api.RSGameEngine; -@Mixin(RSGameShell.class) -public abstract class StretchedModeMaxSizeMixin implements RSGameShell +@Mixin(RSGameEngine.class) +public abstract class StretchedModeMaxSizeMixin implements RSGameEngine { @Shadow("client") private static RSClient client; diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSAbstractArchive.java b/runescape-api/src/main/java/net/runelite/rs/api/RSAbstractArchive.java index fe3f6c7003..bddfbe6f71 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSAbstractArchive.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSAbstractArchive.java @@ -1,14 +1,36 @@ package net.runelite.rs.api; +import net.runelite.api.AbstractArchive; import net.runelite.api.IndexDataBase; import net.runelite.mapping.Import; -public interface RSAbstractArchive extends IndexDataBase +public interface RSAbstractArchive extends IndexDataBase, AbstractArchive { @Import("takeFile") + @Override byte[] getConfigData(int archiveId, int fileId); @Import("getGroupFileIds") @Override - int[] getFileIds(int group); + int[] getFileIds(int groupId); + + @Import("groupCount") + @Override + int getGroupCount(); + + @Import("fileIds") + @Override + int[][] getFileIds(); + + @Import("getFile") + @Override + byte[] getFile(int groupId, int fileId); + + @Import("getGroupFileCount") + @Override + int getGroupFileCount(int groupId); + + @Import("fileCounts") + @Override + int[] getFileCounts(); } diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSBuffer.java b/runescape-api/src/main/java/net/runelite/rs/api/RSBuffer.java index b43e772f62..3772548707 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSBuffer.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSBuffer.java @@ -1,12 +1,37 @@ package net.runelite.rs.api; +import net.runelite.api.Buffer; import net.runelite.mapping.Import; -public interface RSBuffer extends RSNode +public interface RSBuffer extends Buffer, RSNode { @Import("array") byte[] getPayload(); @Import("offset") int getOffset(); + + @Import("writeByte") + @Override + void writeByte(int var1); + + @Import("writeShort") + @Override + void writeShort(int var1); + + @Import("writeMedium") + @Override + void writeMedium(int var1); + + @Import("writeInt") + @Override + void writeInt(int var1); + + @Import("writeLong") + @Override + void writeLong(long var1); + + @Import("writeStringCp1252NullTerminated") + @Override + void writeStringCp1252NullTerminated(String string); } \ No newline at end of file diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java b/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java index 90d9cb0779..66318eef50 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java @@ -26,6 +26,7 @@ package net.runelite.rs.api; import java.math.BigInteger; import java.util.Map; +import net.runelite.api.AbstractArchive; import net.runelite.api.Client; import net.runelite.api.SpritePixels; import net.runelite.api.World; @@ -33,7 +34,7 @@ import net.runelite.api.widgets.Widget; import net.runelite.mapping.Construct; import net.runelite.mapping.Import; -public interface RSClient extends RSGameShell, Client +public interface RSClient extends RSGameEngine, Client { @Import("cameraX") @Override @@ -1350,4 +1351,51 @@ public interface RSClient extends RSGameShell, Client RSIterableNodeHashTable newIterableNodeHashTable(int size); RSVarbitComposition getVarbitComposition(int id); + + @Override + @Import("SequenceDefinition_skeletonsArchive") + RSAbstractArchive getSequenceDefinition_skeletonsArchive(); + + @Override + @Import("SequenceDefinition_archive") + RSAbstractArchive getSequenceDefinition_archive(); + + @Override + @Import("SequenceDefinition_animationsArchive") + RSAbstractArchive getSequenceDefinition_animationsArchive(); + + @Override + @Import("NpcDefinition_archive") + AbstractArchive getNpcDefinition_archive(); + + @Override + @Import("ObjectDefinition_modelsArchive") + AbstractArchive getObjectDefinition_modelsArchive(); + + @Override + @Import("ObjectDefinition_archive") + RSAbstractArchive getObjectDefinition_archive(); + + @Override + @Import("ItemDefinition_archive") + RSAbstractArchive getItemDefinition_archive(); + + @Override + @Import("KitDefinition_archive") + AbstractArchive getKitDefinition_archive(); + + @Override + @Import("KitDefinition_modelsArchive") + AbstractArchive getKitDefinition_modelsArchive(); + + @Override + @Import("SpotAnimationDefinition_archive") + AbstractArchive getSpotAnimationDefinition_archive(); + + @Override + @Import("SpotAnimationDefinition_modelArchive") + AbstractArchive getSpotAnimationDefinition_modelArchive(); + + @Construct + RSBuffer createBuffer(byte[] bytes); } diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSFriendSystem.java b/runescape-api/src/main/java/net/runelite/rs/api/RSFriendSystem.java index 283ce53c09..87bd7ed14e 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSFriendSystem.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSFriendSystem.java @@ -13,6 +13,9 @@ public interface RSFriendSystem @Import("isFriended") boolean isFriended(RSUsername var1, boolean var2); + @Import("isIgnored") + boolean isIgnored(RSUsername var1); + @Import("addFriend") void addFriend(String username); diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSGameShell.java b/runescape-api/src/main/java/net/runelite/rs/api/RSGameEngine.java similarity index 96% rename from runescape-api/src/main/java/net/runelite/rs/api/RSGameShell.java rename to runescape-api/src/main/java/net/runelite/rs/api/RSGameEngine.java index fe27edcd9a..345845d9ee 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSGameShell.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSGameEngine.java @@ -24,11 +24,11 @@ */ package net.runelite.rs.api; -import net.runelite.api.GameShell; +import net.runelite.api.GameEngine; import java.awt.Canvas; import net.runelite.mapping.Import; -public interface RSGameShell extends GameShell +public interface RSGameEngine extends GameEngine { @Import("canvas") Canvas getCanvas(); diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSTile.java b/runescape-api/src/main/java/net/runelite/rs/api/RSTile.java index 7dc5bee2f3..19182c5fb2 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSTile.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSTile.java @@ -28,6 +28,10 @@ public interface RSTile extends Tile @Override GroundObject getGroundObject(); + @Import("floorDecoration") + @Override + void setGroundObject(GroundObject object); + @Import("boundaryObject") @Override WallObject getWallObject(); diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSWidget.java b/runescape-api/src/main/java/net/runelite/rs/api/RSWidget.java index ace10f8461..57546ccfe4 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSWidget.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSWidget.java @@ -588,4 +588,6 @@ public interface RSWidget extends Widget @Import("onVarTransmit") @Override void setOnVarTransmitListener(Object[] o); + + void broadcastHidden(boolean hidden); } \ No newline at end of file diff --git a/runescape-client/src/main/java/ArchiveLoader.java b/runescape-client/src/main/java/ArchiveLoader.java index d5a24dbe3a..347f638dcb 100644 --- a/runescape-client/src/main/java/ArchiveLoader.java +++ b/runescape-client/src/main/java/ArchiveLoader.java @@ -526,7 +526,7 @@ public class ArchiveLoader { class22.field107 = "Can't login? Click here."; // L: 1256 } - GameShell.field481 = new Bounds(Login.loginBoxCenter, var31, var1.stringWidth(class22.field107), 11); // L: 1259 + GameEngine.field481 = new Bounds(Login.loginBoxCenter, var31, var1.stringWidth(class22.field107), 11); // L: 1259 GrandExchangeOfferOwnWorldComparator.field643 = new Bounds(Login.loginBoxCenter, var31, var1.stringWidth("Still having trouble logging in?"), 11); // L: 1260 var1.drawCentered(class22.field107, Login.loginBoxCenter, var31, 16777215, 0); // L: 1261 } else if (Login.loginIndex == 3) { // L: 1263 diff --git a/runescape-client/src/main/java/Canvas.java b/runescape-client/src/main/java/Canvas.java index 5d60bc2c12..26d20936c1 100644 --- a/runescape-client/src/main/java/Canvas.java +++ b/runescape-client/src/main/java/Canvas.java @@ -78,7 +78,7 @@ public final class Canvas extends java.awt.Canvas { DynamicObject.archive2 = WorldMapCacheName.newArchive(2, true, false, true); // L: 1744 class330.archive3 = WorldMapCacheName.newArchive(3, false, true, true); // L: 1745 class227.archive4 = WorldMapCacheName.newArchive(4, false, true, true); // L: 1746 - GameShell.archive5 = WorldMapCacheName.newArchive(5, true, true, true); // L: 1747 + GameEngine.archive5 = WorldMapCacheName.newArchive(5, true, true, true); // L: 1747 class217.archive6 = WorldMapCacheName.newArchive(6, true, true, true); // L: 1748 BuddyRankComparator.archive7 = WorldMapCacheName.newArchive(7, false, true, true); // L: 1749 Messages.archive8 = WorldMapCacheName.newArchive(8, false, true, true); // L: 1750 @@ -103,7 +103,7 @@ public final class Canvas extends java.awt.Canvas { var12 += DynamicObject.archive2.percentage() * 2 / 100; // L: 1771 var12 += class330.archive3.percentage() * 2 / 100; // L: 1772 var12 += class227.archive4.percentage() * 6 / 100; // L: 1773 - var12 += GameShell.archive5.percentage() * 4 / 100; // L: 1774 + var12 += GameEngine.archive5.percentage() * 4 / 100; // L: 1774 var12 += class217.archive6.percentage() * 2 / 100; // L: 1775 var12 += BuddyRankComparator.archive7.percentage() * 56 / 100; // L: 1776 var12 += Messages.archive8.percentage() * 2 / 100; // L: 1777 @@ -128,7 +128,7 @@ public final class Canvas extends java.awt.Canvas { UserComparator4.method3469(SceneTilePaint.archive0, "Animations"); // L: 1794 UserComparator4.method3469(WorldMapSprite.archive1, "Skeletons"); // L: 1795 UserComparator4.method3469(class227.archive4, "Sound FX"); // L: 1796 - UserComparator4.method3469(GameShell.archive5, "Maps"); // L: 1797 + UserComparator4.method3469(GameEngine.archive5, "Maps"); // L: 1797 UserComparator4.method3469(class217.archive6, "Music Tracks"); // L: 1798 UserComparator4.method3469(BuddyRankComparator.archive7, "Models"); // L: 1799 UserComparator4.method3469(Messages.archive8, "Sprites"); // L: 1800 @@ -152,7 +152,7 @@ public final class Canvas extends java.awt.Canvas { WorldMapIcon_0.method270(22050, !Client.isLowDetail, 2); // L: 1815 MidiPcmStream var20 = new MidiPcmStream(); // L: 1816 var20.method3759(9, 128); // L: 1817 - AbstractWorldMapData.pcmPlayer0 = UserComparator6.method3526(GameShell.taskHandler, 0, 22050); // L: 1818 + AbstractWorldMapData.pcmPlayer0 = UserComparator6.method3526(GameEngine.taskHandler, 0, 22050); // L: 1818 AbstractWorldMapData.pcmPlayer0.setStream(var20); // L: 1819 var21 = Client.archive15; // L: 1820 var2 = FontName.archive14; // L: 1821 @@ -161,7 +161,7 @@ public final class Canvas extends java.awt.Canvas { class206.musicSamplesArchive = var2; // L: 1825 class206.soundEffectsArchive = var16; // L: 1826 class206.midiPcmStream = var20; // L: 1827 - FriendLoginUpdate.pcmPlayer1 = UserComparator6.method3526(GameShell.taskHandler, 1, 2048); // L: 1829 + FriendLoginUpdate.pcmPlayer1 = UserComparator6.method3526(GameEngine.taskHandler, 1, 2048); // L: 1829 WorldMapManager.pcmStreamMixer = new PcmStreamMixer(); // L: 1830 FriendLoginUpdate.pcmPlayer1.setStream(WorldMapManager.pcmStreamMixer); // L: 1831 ItemLayer.decimator = new Decimator(22050, PcmPlayer.field1443); // L: 1832 @@ -498,7 +498,7 @@ public final class Canvas extends java.awt.Canvas { } } else if (Client.titleLoadingStage == 110) { // L: 2132 SoundCache.mouseRecorder = new MouseRecorder(); // L: 2133 - GameShell.taskHandler.newThreadTask(SoundCache.mouseRecorder, 10); // L: 2134 + GameEngine.taskHandler.newThreadTask(SoundCache.mouseRecorder, 10); // L: 2134 Login.Login_loadingText = "Loaded input handler"; // L: 2135 Login.Login_loadingPercent = 92; // L: 2136 Client.titleLoadingStage = 120; // L: 2137 diff --git a/runescape-client/src/main/java/Client.java b/runescape-client/src/main/java/Client.java index 69fafe983f..3190819024 100644 --- a/runescape-client/src/main/java/Client.java +++ b/runescape-client/src/main/java/Client.java @@ -15,7 +15,7 @@ import netscape.javascript.JSObject; @Implements("Client") @ObfuscatedName("client") -public final class Client extends GameShell implements Usernamed { +public final class Client extends GameEngine implements Usernamed { @ObfuscatedName("ns") @ObfuscatedSignature( descriptor = "Lhe;" @@ -1691,7 +1691,7 @@ public final class Client extends GameShell implements Usernamed { int var2; for (var2 = 0; var2 < WorldMapIcon_0.regionLandArchives.length; ++var2) { // L: 947 if (class41.regionMapArchiveIds[var2] != -1 && WorldMapIcon_0.regionLandArchives[var2] == null) { // L: 948 949 - WorldMapIcon_0.regionLandArchives[var2] = GameShell.archive5.takeFile(class41.regionMapArchiveIds[var2], 0); // L: 950 + WorldMapIcon_0.regionLandArchives[var2] = GameEngine.archive5.takeFile(class41.regionMapArchiveIds[var2], 0); // L: 950 if (WorldMapIcon_0.regionLandArchives[var2] == null) { // L: 951 var43 = false; // L: 952 ++field700; // L: 953 @@ -1699,7 +1699,7 @@ public final class Client extends GameShell implements Usernamed { } if (GrandExchangeOfferTotalQuantityComparator.regionLandArchiveIds[var2] != -1 && MouseRecorder.regionMapArchives[var2] == null) { // L: 957 958 - MouseRecorder.regionMapArchives[var2] = GameShell.archive5.takeFileEncrypted(GrandExchangeOfferTotalQuantityComparator.regionLandArchiveIds[var2], 0, class227.xteaKeys[var2]); // L: 959 + MouseRecorder.regionMapArchives[var2] = GameEngine.archive5.takeFileEncrypted(GrandExchangeOfferTotalQuantityComparator.regionLandArchiveIds[var2], 0, class227.xteaKeys[var2]); // L: 959 if (MouseRecorder.regionMapArchives[var2] == null) { // L: 960 var43 = false; // L: 961 ++field700; // L: 962 @@ -2050,8 +2050,8 @@ public final class Client extends GameShell implements Usernamed { for (var46 = var4 - 1; var46 <= var5 + 1; ++var46) { // L: 1223 for (var9 = var6 - 1; var9 <= var7 + 1; ++var9) { // L: 1224 if (var46 < var4 || var46 > var5 || var9 < var6 || var9 > var7) { // L: 1225 - GameShell.archive5.loadRegionFromName("m" + var46 + "_" + var9); // L: 1226 - GameShell.archive5.loadRegionFromName("l" + var46 + "_" + var9); // L: 1227 + GameEngine.archive5.loadRegionFromName("m" + var46 + "_" + var9); // L: 1226 + GameEngine.archive5.loadRegionFromName("l" + var46 + "_" + var9); // L: 1227 } } } @@ -2076,11 +2076,11 @@ public final class Client extends GameShell implements Usernamed { class225.clock.mark(); // L: 1250 for (var5 = 0; var5 < 32; ++var5) { // L: 1251 - GameShell.graphicsTickTimes[var5] = 0L; + GameEngine.graphicsTickTimes[var5] = 0L; } for (var5 = 0; var5 < 32; ++var5) { // L: 1252 - GameShell.clientTickTimes[var5] = 0L; + GameEngine.clientTickTimes[var5] = 0L; } class8.gameCyclesToDo = 0; // L: 1253 @@ -2687,7 +2687,7 @@ public final class Client extends GameShell implements Usernamed { if (--field864 + 1 <= 0) { // L: 1561 try { if (js5ConnectState == 0) { // L: 1563 - WorldMapManager.js5SocketTask = GameShell.taskHandler.newSocketTask(WorldMapSprite.worldHost, ArchiveDiskAction.port3); // L: 1564 + WorldMapManager.js5SocketTask = GameEngine.taskHandler.newSocketTask(WorldMapSprite.worldHost, ArchiveDiskAction.port3); // L: 1564 ++js5ConnectState; // L: 1565 } @@ -2706,7 +2706,7 @@ public final class Client extends GameShell implements Usernamed { if (useBufferedSocket) { // L: 1575 TaskHandler.js5Socket = class219.method4011((Socket)WorldMapManager.js5SocketTask.result, 40000, 5000); // L: 1576 } else { - TaskHandler.js5Socket = new NetSocket((Socket)WorldMapManager.js5SocketTask.result, GameShell.taskHandler, 5000); // L: 1579 + TaskHandler.js5Socket = new NetSocket((Socket)WorldMapManager.js5SocketTask.result, GameEngine.taskHandler, 5000); // L: 1579 } Buffer var1 = new Buffer(5); // L: 1581 @@ -2875,7 +2875,7 @@ public final class Client extends GameShell implements Usernamed { if (loginState == 1) { // L: 2221 if (WorldMapID.socketTask == null) { // L: 2222 - WorldMapID.socketTask = GameShell.taskHandler.newSocketTask(WorldMapSprite.worldHost, ArchiveDiskAction.port3); // L: 2223 + WorldMapID.socketTask = GameEngine.taskHandler.newSocketTask(WorldMapSprite.worldHost, ArchiveDiskAction.port3); // L: 2223 } if (WorldMapID.socketTask.status == 2) { // L: 2225 @@ -2886,7 +2886,7 @@ public final class Client extends GameShell implements Usernamed { if (useBufferedSocket) { // L: 2227 var1 = class219.method4011((Socket)WorldMapID.socketTask.result, 40000, 5000); // L: 2228 } else { - var1 = new NetSocket((Socket)WorldMapID.socketTask.result, GameShell.taskHandler, 5000); // L: 2231 + var1 = new NetSocket((Socket)WorldMapID.socketTask.result, GameEngine.taskHandler, 5000); // L: 2231 } packetWriter.setSocket((AbstractSocket)var1); // L: 2233 @@ -3042,7 +3042,7 @@ public final class Client extends GameShell implements Usernamed { var5.packetBuffer.writeBytes(var29.array, 0, var29.array.length); // L: 2364 var5.packetBuffer.writeByte(clientType); // L: 2365 var5.packetBuffer.writeInt(0); // L: 2366 - var5.packetBuffer.method5718(GameShell.archive5.hash); // L: 2367 + var5.packetBuffer.method5718(GameEngine.archive5.hash); // L: 2367 var5.packetBuffer.method5718(GrandExchangeOfferUnitPriceComparator.archive13.hash); // L: 2368 var5.packetBuffer.method5718(PacketBufferNode.archive12.hash); // L: 2369 var5.packetBuffer.method5587(ItemContainer.archive11.hash); // L: 2370 @@ -3164,7 +3164,7 @@ public final class Client extends GameShell implements Usernamed { if (loginState == 13) { // L: 2493 field892 = 0; // L: 2494 - GameShell.setLoginResponseString("You have only just left another world.", "Your profile will be transferred in:", field682 / 60 + " seconds."); // L: 2495 + GameEngine.setLoginResponseString("You have only just left another world.", "Your profile will be transferred in:", field682 / 60 + " seconds."); // L: 2495 if (--field682 <= 0) { // L: 2496 loginState = 0; } @@ -3270,7 +3270,7 @@ public final class Client extends GameShell implements Usernamed { String var25 = var2.readStringCp1252NullTerminated(); // L: 2591 String var33 = var2.readStringCp1252NullTerminated(); // L: 2592 String var27 = var2.readStringCp1252NullTerminated(); // L: 2593 - GameShell.setLoginResponseString(var25, var33, var27); // L: 2594 + GameEngine.setLoginResponseString(var25, var33, var27); // L: 2594 WorldMapCacheName.updateGameState(10); // L: 2595 } @@ -5333,7 +5333,7 @@ public final class Client extends GameShell implements Usernamed { var57.packetBuffer.method5569(var18); // L: 6401 var57.packetBuffer.method5718(var16); // L: 6402 var57.packetBuffer.method5587(var5); // L: 6403 - var57.packetBuffer.method5568(GameShell.fps); // L: 6404 + var57.packetBuffer.method5568(GameEngine.fps); // L: 6404 packetWriter.addNode(var57); // L: 6405 var1.serverPacket = null; // L: 6406 return true; // L: 6407 diff --git a/runescape-client/src/main/java/FontName.java b/runescape-client/src/main/java/FontName.java index a4562658d8..e65da8c031 100644 --- a/runescape-client/src/main/java/FontName.java +++ b/runescape-client/src/main/java/FontName.java @@ -237,7 +237,7 @@ public class FontName { if (var10.contentType == 1336) { // L: 9016 if (Client.displayFps) { // L: 9017 var13 += 15; // L: 9018 - WorldMapLabelSize.fontPlain12.drawRightAligned("Fps:" + GameShell.fps, var12 + var10.width, var13, 16776960, -1); // L: 9019 + WorldMapLabelSize.fontPlain12.drawRightAligned("Fps:" + GameEngine.fps, var12 + var10.width, var13, 16776960, -1); // L: 9019 var13 += 15; // L: 9020 Runtime var42 = Runtime.getRuntime(); // L: 9021 var20 = (int)((var42.totalMemory() - var42.freeMemory()) / 1024L); // L: 9022 diff --git a/runescape-client/src/main/java/GameShell.java b/runescape-client/src/main/java/GameEngine.java similarity index 97% rename from runescape-client/src/main/java/GameShell.java rename to runescape-client/src/main/java/GameEngine.java index b61fe0534e..5cab90a2d5 100644 --- a/runescape-client/src/main/java/GameShell.java +++ b/runescape-client/src/main/java/GameEngine.java @@ -25,8 +25,8 @@ import net.runelite.mapping.ObfuscatedName; import net.runelite.mapping.ObfuscatedSignature; @ObfuscatedName("bd") -@Implements("GameShell") -public abstract class GameShell extends Applet implements Runnable, FocusListener, WindowListener { +@Implements("GameEngine") +public abstract class GameEngine extends Applet implements Runnable, FocusListener, WindowListener { @ObfuscatedName("h") @ObfuscatedSignature( descriptor = "Lfa;" @@ -37,14 +37,14 @@ public abstract class GameShell extends Applet implements Runnable, FocusListene @ObfuscatedSignature( descriptor = "Lbd;" ) - @Export("gameShell") - static GameShell gameShell; + @Export("gameEngine") + static GameEngine gameEngine; @ObfuscatedName("t") @ObfuscatedGetter( intValue = 548418733 ) - @Export("GameShell_redundantStartThreadCount") - static int GameShell_redundantStartThreadCount; + @Export("GameEngine_redundantStartThreadCount") + static int GameEngine_redundantStartThreadCount; @ObfuscatedName("j") @ObfuscatedGetter( longValue = -299301004563523829L @@ -192,8 +192,8 @@ public abstract class GameShell extends Applet implements Runnable, FocusListene final EventQueue eventQueue; static { - gameShell = null; // L: 41 - GameShell_redundantStartThreadCount = 0; // L: 43 + gameEngine = null; // L: 41 + GameEngine_redundantStartThreadCount = 0; // L: 43 stopTimeMs = 0L; // L: 44 isKilled = false; // L: 45 cycleDurationMillis = 20; // L: 48 @@ -207,7 +207,7 @@ public abstract class GameShell extends Applet implements Runnable, FocusListene garbageCollectorLastCheckTimeMs = -1L; // L: 86 } - protected GameShell() { + protected GameEngine() { this.hasErrored = false; // L: 46 this.canvasX = 0; // L: 59 this.canvasY = 0; // L: 60 @@ -451,9 +451,9 @@ public abstract class GameShell extends Applet implements Runnable, FocusListene @Export("startThread") protected final void startThread(int var1, int var2, int var3) { try { - if (gameShell != null) { // L: 220 - ++GameShell_redundantStartThreadCount; // L: 221 - if (GameShell_redundantStartThreadCount >= 3) { // L: 222 + if (gameEngine != null) { // L: 220 + ++GameEngine_redundantStartThreadCount; // L: 221 + if (GameEngine_redundantStartThreadCount >= 3) { // L: 222 this.error("alreadyloaded"); // L: 223 return; // L: 224 } @@ -462,7 +462,7 @@ public abstract class GameShell extends Applet implements Runnable, FocusListene return; // L: 227 } - gameShell = this; // L: 229 + gameEngine = this; // L: 229 IgnoreList.canvasWidth = var1; // L: 230 ModelData0.canvasHeight = var2; // L: 231 RunException.RunException_revision = var3; // L: 232 @@ -851,7 +851,7 @@ public abstract class GameShell extends Applet implements Runnable, FocusListene protected abstract void vmethod1777(); public final synchronized void paint(Graphics var1) { - if (this == gameShell && !isKilled) { // L: 449 + if (this == gameEngine && !isKilled) { // L: 449 this.fullRedraw = true; // L: 450 if (class298.currentTimeMillis() - this.field472 > 1000L) { // L: 451 Rectangle var2 = var1.getClipBounds(); // L: 452 @@ -864,7 +864,7 @@ public abstract class GameShell extends Applet implements Runnable, FocusListene } // L: 455 public final void destroy() { - if (this == gameShell && !isKilled) { // L: 438 + if (this == gameEngine && !isKilled) { // L: 438 stopTimeMs = class298.currentTimeMillis(); // L: 439 class236.sleepExact(5000L); // L: 440 this.kill(); // L: 441 @@ -899,13 +899,13 @@ public abstract class GameShell extends Applet implements Runnable, FocusListene public abstract void init(); public final void stop() { - if (this == gameShell && !isKilled) { // L: 433 + if (this == gameEngine && !isKilled) { // L: 433 stopTimeMs = class298.currentTimeMillis() + 4000L; // L: 434 } } // L: 435 public final void start() { - if (this == gameShell && !isKilled) { // L: 428 + if (this == gameEngine && !isKilled) { // L: 428 stopTimeMs = 0L; // L: 429 } } // L: 430 diff --git a/runescape-client/src/main/java/GrandExchangeEvent.java b/runescape-client/src/main/java/GrandExchangeEvent.java index d0566d1427..86a473496b 100644 --- a/runescape-client/src/main/java/GrandExchangeEvent.java +++ b/runescape-client/src/main/java/GrandExchangeEvent.java @@ -132,11 +132,11 @@ public class GrandExchangeEvent { int var0; for (var0 = 0; var0 < 32; ++var0) { // L: 422 - GameShell.graphicsTickTimes[var0] = 0L; + GameEngine.graphicsTickTimes[var0] = 0L; } for (var0 = 0; var0 < 32; ++var0) { // L: 423 - GameShell.clientTickTimes[var0] = 0L; + GameEngine.clientTickTimes[var0] = 0L; } class8.gameCyclesToDo = 0; // L: 424 diff --git a/runescape-client/src/main/java/GrandExchangeOfferNameComparator.java b/runescape-client/src/main/java/GrandExchangeOfferNameComparator.java index 26a884fba0..92f6c97873 100644 --- a/runescape-client/src/main/java/GrandExchangeOfferNameComparator.java +++ b/runescape-client/src/main/java/GrandExchangeOfferNameComparator.java @@ -108,8 +108,8 @@ final class GrandExchangeOfferNameComparator implements Comparator { GarbageCollectorMXBean var2 = (GarbageCollectorMXBean)var1.next(); // L: 570 if (var2.isValid()) { // L: 572 class25.garbageCollector = var2; // L: 573 - GameShell.garbageCollectorLastCheckTimeMs = -1L; // L: 574 - GameShell.garbageCollectorLastCollectionTime = -1L; // L: 575 + GameEngine.garbageCollectorLastCheckTimeMs = -1L; // L: 574 + GameEngine.garbageCollectorLastCollectionTime = -1L; // L: 575 } } } catch (Throwable var11) { // L: 580 @@ -119,16 +119,16 @@ final class GrandExchangeOfferNameComparator implements Comparator { if (class25.garbageCollector != null) { // L: 582 long var9 = class298.currentTimeMillis(); // L: 583 long var3 = class25.garbageCollector.getCollectionTime(); // L: 584 - if (-1L != GameShell.garbageCollectorLastCollectionTime) { // L: 585 - long var5 = var3 - GameShell.garbageCollectorLastCollectionTime; // L: 586 - long var7 = var9 - GameShell.garbageCollectorLastCheckTimeMs; // L: 587 + if (-1L != GameEngine.garbageCollectorLastCollectionTime) { // L: 585 + long var5 = var3 - GameEngine.garbageCollectorLastCollectionTime; // L: 586 + long var7 = var9 - GameEngine.garbageCollectorLastCheckTimeMs; // L: 587 if (var7 != 0L) { // L: 588 var0 = (int)(100L * var5 / var7); } } - GameShell.garbageCollectorLastCollectionTime = var3; // L: 590 - GameShell.garbageCollectorLastCheckTimeMs = var9; // L: 591 + GameEngine.garbageCollectorLastCollectionTime = var3; // L: 590 + GameEngine.garbageCollectorLastCheckTimeMs = var9; // L: 591 } return var0; // L: 593 diff --git a/runescape-client/src/main/java/ItemContainer.java b/runescape-client/src/main/java/ItemContainer.java index 27b759e733..c5a3f4bafb 100644 --- a/runescape-client/src/main/java/ItemContainer.java +++ b/runescape-client/src/main/java/ItemContainer.java @@ -170,8 +170,8 @@ public class ItemContainer extends Node { var8 = var7 + (var6 << 8); // L: 5317 if (!var16 || var7 != 49 && var7 != 149 && var7 != 147 && var6 != 50 && (var6 != 49 || var7 != 47)) { // L: 5318 FileSystem.regions[var4] = var8; // L: 5319 - class41.regionMapArchiveIds[var4] = GameShell.archive5.getGroupId("m" + var6 + "_" + var7); // L: 5320 - GrandExchangeOfferTotalQuantityComparator.regionLandArchiveIds[var4] = GameShell.archive5.getGroupId("l" + var6 + "_" + var7); // L: 5321 + class41.regionMapArchiveIds[var4] = GameEngine.archive5.getGroupId("m" + var6 + "_" + var7); // L: 5320 + GrandExchangeOfferTotalQuantityComparator.regionLandArchiveIds[var4] = GameEngine.archive5.getGroupId("l" + var6 + "_" + var7); // L: 5321 ++var4; // L: 5322 } } @@ -236,8 +236,8 @@ public class ItemContainer extends Node { FileSystem.regions[var5] = var12; // L: 5368 var13 = var12 >> 8 & 255; // L: 5369 int var14 = var12 & 255; // L: 5370 - class41.regionMapArchiveIds[var5] = GameShell.archive5.getGroupId("m" + var13 + "_" + var14); // L: 5371 - GrandExchangeOfferTotalQuantityComparator.regionLandArchiveIds[var5] = GameShell.archive5.getGroupId("l" + var13 + "_" + var14); // L: 5372 + class41.regionMapArchiveIds[var5] = GameEngine.archive5.getGroupId("m" + var13 + "_" + var14); // L: 5371 + GrandExchangeOfferTotalQuantityComparator.regionLandArchiveIds[var5] = GameEngine.archive5.getGroupId("l" + var13 + "_" + var14); // L: 5372 ++var5; // L: 5373 } } diff --git a/runescape-client/src/main/java/Messages.java b/runescape-client/src/main/java/Messages.java index 9ef82f2c62..b8cb8a37df 100644 --- a/runescape-client/src/main/java/Messages.java +++ b/runescape-client/src/main/java/Messages.java @@ -94,6 +94,6 @@ public class Messages { ) static void method2285() { Login.loginIndex = 24; // L: 1517 - GameShell.setLoginResponseString("The game servers are currently being updated.", "Please wait a few minutes and try again.", ""); // L: 1518 + GameEngine.setLoginResponseString("The game servers are currently being updated.", "Please wait a few minutes and try again.", ""); // L: 1518 } // L: 1519 } diff --git a/runescape-client/src/main/java/SequenceDefinition.java b/runescape-client/src/main/java/SequenceDefinition.java index 5e7a03606e..561e3fb410 100644 --- a/runescape-client/src/main/java/SequenceDefinition.java +++ b/runescape-client/src/main/java/SequenceDefinition.java @@ -381,7 +381,7 @@ public class SequenceDefinition extends DualNode { garbageValue = "1" ) @Export("doCycleTitle") - static void doCycleTitle(GameShell var0) { + static void doCycleTitle(GameEngine var0) { int var2; int var3; int var4; @@ -662,12 +662,12 @@ public class SequenceDefinition extends DualNode { var35 += 15; // L: 496 var36 = 361; // L: 497 - if (GameShell.field481 != null) { // L: 498 - var38 = GameShell.field481.highX / 2; // L: 499 - if (var4 == 1 && var44 >= GameShell.field481.lowX - var38 && var44 <= var38 + GameShell.field481.lowX && var34 >= var36 - 15 && var34 < var36) { // L: 500 + if (GameEngine.field481 != null) { // L: 498 + var38 = GameEngine.field481.highX / 2; // L: 499 + if (var4 == 1 && var44 >= GameEngine.field481.lowX - var38 && var44 <= var38 + GameEngine.field481.lowX && var34 >= var36 - 15 && var34 < var36) { // L: 500 switch(Login.field1190) { // L: 501 case 1: - GameShell.setLoginResponseString("Please enter your username.", "If you created your account after November", "2010, this will be the creation email address."); // L: 504 + GameEngine.setLoginResponseString("Please enter your username.", "If you created your account after November", "2010, this will be the creation email address."); // L: 504 Login.loginIndex = 5; // L: 505 return; // L: 506 case 2: @@ -681,16 +681,16 @@ public class SequenceDefinition extends DualNode { if (var4 == 1 && var44 >= var38 - 75 && var44 <= var38 + 75 && var34 >= var37 - 20 && var34 <= var37 + 20) { // L: 518 Login.Login_username = Login.Login_username.trim(); // L: 519 if (Login.Login_username.length() == 0) { // L: 520 - GameShell.setLoginResponseString("", "Please enter your username/email address.", ""); // L: 521 + GameEngine.setLoginResponseString("", "Please enter your username/email address.", ""); // L: 521 return; // L: 522 } if (Login.Login_password.length() == 0) { // L: 524 - GameShell.setLoginResponseString("", "Please enter your password.", ""); // L: 525 + GameEngine.setLoginResponseString("", "Please enter your password.", ""); // L: 525 return; // L: 526 } - GameShell.setLoginResponseString("", "Connecting to server...", ""); // L: 528 + GameEngine.setLoginResponseString("", "Connecting to server...", ""); // L: 528 WorldMapDecoration.method380(false); // L: 529 WorldMapCacheName.updateGameState(20); // L: 530 return; // L: 531 @@ -782,16 +782,16 @@ public class SequenceDefinition extends DualNode { if (StudioGame.field3135 == 84) { // L: 591 Login.Login_username = Login.Login_username.trim(); // L: 592 if (Login.Login_username.length() == 0) { // L: 593 - GameShell.setLoginResponseString("", "Please enter your username/email address.", ""); // L: 594 + GameEngine.setLoginResponseString("", "Please enter your username/email address.", ""); // L: 594 return; // L: 595 } if (Login.Login_password.length() == 0) { // L: 597 - GameShell.setLoginResponseString("", "Please enter your password.", ""); // L: 598 + GameEngine.setLoginResponseString("", "Please enter your password.", ""); // L: 598 return; // L: 599 } - GameShell.setLoginResponseString("", "Connecting to server...", ""); // L: 601 + GameEngine.setLoginResponseString("", "Connecting to server...", ""); // L: 601 WorldMapDecoration.method380(false); // L: 602 WorldMapCacheName.updateGameState(20); // L: 603 return; // L: 604 @@ -880,7 +880,7 @@ public class SequenceDefinition extends DualNode { var35 = Login.loginBoxX + 180; // L: 688 var8 = 326; // L: 689 if (var4 == 1 && var44 >= var35 - 75 && var44 <= var35 + 75 && var34 >= var8 - 20 && var34 <= var8 + 20) { // L: 690 - GameShell.setLoginResponseString("Please enter your username.", "If you created your account after November", "2010, this will be the creation email address."); // L: 691 + GameEngine.setLoginResponseString("Please enter your username.", "If you created your account after November", "2010, this will be the creation email address."); // L: 691 Login.loginIndex = 5; // L: 692 return; // L: 693 } @@ -892,14 +892,14 @@ public class SequenceDefinition extends DualNode { if (var4 == 1 && var44 >= var35 - 75 && var44 <= var35 + 75 && var34 >= var8 - 20 && var34 <= var8 + 20) { // L: 699 SecureRandomCallable.otp.trim(); // L: 700 if (SecureRandomCallable.otp.length() != 6) { // L: 701 - GameShell.setLoginResponseString("", "Please enter a 6-digit PIN.", ""); // L: 702 + GameEngine.setLoginResponseString("", "Please enter a 6-digit PIN.", ""); // L: 702 return; // L: 703 } WorldMapSection1.field313 = Integer.parseInt(SecureRandomCallable.otp); // L: 705 SecureRandomCallable.otp = ""; // L: 706 WorldMapDecoration.method380(true); // L: 707 - GameShell.setLoginResponseString("", "Connecting to server...", ""); // L: 708 + GameEngine.setLoginResponseString("", "Connecting to server...", ""); // L: 708 WorldMapCacheName.updateGameState(20); // L: 709 return; // L: 710 } @@ -945,14 +945,14 @@ public class SequenceDefinition extends DualNode { if (StudioGame.field3135 == 84) { // L: 743 SecureRandomCallable.otp.trim(); // L: 744 if (SecureRandomCallable.otp.length() != 6) { // L: 745 - GameShell.setLoginResponseString("", "Please enter a 6-digit PIN.", ""); // L: 746 + GameEngine.setLoginResponseString("", "Please enter a 6-digit PIN.", ""); // L: 746 return; // L: 747 } WorldMapSection1.field313 = Integer.parseInt(SecureRandomCallable.otp); // L: 749 SecureRandomCallable.otp = ""; // L: 750 WorldMapDecoration.method380(true); // L: 751 - GameShell.setLoginResponseString("", "Connecting to server...", ""); // L: 752 + GameEngine.setLoginResponseString("", "Connecting to server...", ""); // L: 752 WorldMapCacheName.updateGameState(20); // L: 753 return; // L: 754 } @@ -1016,7 +1016,7 @@ public class SequenceDefinition extends DualNode { var8 = 321; // L: 812 if (var4 == 1 && var44 >= var35 - 75 && var44 <= var35 + 75 && var34 >= var8 - 20 && var34 <= var8 + 20) { // L: 813 AttackOption.openURL(AbstractWorldMapIcon.method632("secure", true) + "m=dob/set_dob.ws", true, false); // L: 814 - GameShell.setLoginResponseString("", "Page has opened in a new window.", "(Please check your popup blocker.)"); // L: 815 + GameEngine.setLoginResponseString("", "Page has opened in a new window.", "(Please check your popup blocker.)"); // L: 815 Login.loginIndex = 6; // L: 816 return; // L: 817 } @@ -1030,7 +1030,7 @@ public class SequenceDefinition extends DualNode { var8 = 321; // L: 826 if (var4 == 1 && var44 >= var35 - 75 && var44 <= var35 + 75 && var34 >= var8 - 20 && var34 <= var8 + 20) { // L: 827 AttackOption.openURL("https://www.jagex.com/terms/privacy", true, false); // L: 828 - GameShell.setLoginResponseString("", "Page has opened in a new window.", "(Please check your popup blocker.)"); // L: 829 + GameEngine.setLoginResponseString("", "Page has opened in a new window.", "(Please check your popup blocker.)"); // L: 829 Login.loginIndex = 6; // L: 830 return; // L: 831 } @@ -1056,7 +1056,7 @@ public class SequenceDefinition extends DualNode { var37 = 276; // L: 852 if (var4 == 1 && var44 >= var38 - 75 && var44 <= var38 + 75 && var34 >= var37 - 20 && var34 <= var37 + 20) { // L: 853 AttackOption.openURL(var30, true, false); // L: 854 - GameShell.setLoginResponseString("", "Page has opened in a new window.", "(Please check your popup blocker.)"); // L: 855 + GameEngine.setLoginResponseString("", "Page has opened in a new window.", "(Please check your popup blocker.)"); // L: 855 Login.loginIndex = 6; // L: 856 return; // L: 857 } diff --git a/runescape-client/src/main/java/UserComparator8.java b/runescape-client/src/main/java/UserComparator8.java index e6da9b50b7..b36ec51570 100644 --- a/runescape-client/src/main/java/UserComparator8.java +++ b/runescape-client/src/main/java/UserComparator8.java @@ -44,11 +44,11 @@ public class UserComparator8 extends AbstractUserComparator { @Export("getLoginError") static void getLoginError(int var0) { if (var0 == -3) { // L: 2791 - GameShell.setLoginResponseString("Connection timed out.", "Please try using a different world.", ""); + GameEngine.setLoginResponseString("Connection timed out.", "Please try using a different world.", ""); } else if (var0 == -2) { // L: 2792 - GameShell.setLoginResponseString("Error connecting to server.", "Please try using a different world.", ""); + GameEngine.setLoginResponseString("Error connecting to server.", "Please try using a different world.", ""); } else if (var0 == -1) { // L: 2793 - GameShell.setLoginResponseString("No response from server.", "Please try using a different world.", ""); + GameEngine.setLoginResponseString("No response from server.", "Please try using a different world.", ""); } else if (var0 == 3) { // L: 2794 Login.loginIndex = 3; // L: 2795 Login.field1190 = 1; // L: 2796 @@ -57,66 +57,66 @@ public class UserComparator8 extends AbstractUserComparator { Login.field1199 = 0; // L: 2801 } else if (var0 == 5) { // L: 2804 Login.field1190 = 2; // L: 2805 - GameShell.setLoginResponseString("Your account has not logged out from its last", "session or the server is too busy right now.", "Please try again in a few minutes."); // L: 2806 + GameEngine.setLoginResponseString("Your account has not logged out from its last", "session or the server is too busy right now.", "Please try again in a few minutes."); // L: 2806 } else if (var0 != 68 && (Client.onMobile || var0 != 6)) { // L: 2808 if (var0 == 7) { // L: 2811 - GameShell.setLoginResponseString("This world is full.", "Please use a different world.", ""); + GameEngine.setLoginResponseString("This world is full.", "Please use a different world.", ""); } else if (var0 == 8) { // L: 2812 - GameShell.setLoginResponseString("Unable to connect.", "Login server offline.", ""); + GameEngine.setLoginResponseString("Unable to connect.", "Login server offline.", ""); } else if (var0 == 9) { // L: 2813 - GameShell.setLoginResponseString("Login limit exceeded.", "Too many connections from your address.", ""); + GameEngine.setLoginResponseString("Login limit exceeded.", "Too many connections from your address.", ""); } else if (var0 == 10) { // L: 2814 - GameShell.setLoginResponseString("Unable to connect.", "Bad session id.", ""); + GameEngine.setLoginResponseString("Unable to connect.", "Bad session id.", ""); } else if (var0 == 11) { // L: 2815 - GameShell.setLoginResponseString("We suspect someone knows your password.", "Press 'change your password' on front page.", ""); + GameEngine.setLoginResponseString("We suspect someone knows your password.", "Press 'change your password' on front page.", ""); } else if (var0 == 12) { // L: 2816 - GameShell.setLoginResponseString("You need a members account to login to this world.", "Please subscribe, or use a different world.", ""); + GameEngine.setLoginResponseString("You need a members account to login to this world.", "Please subscribe, or use a different world.", ""); } else if (var0 == 13) { // L: 2817 - GameShell.setLoginResponseString("Could not complete login.", "Please try using a different world.", ""); + GameEngine.setLoginResponseString("Could not complete login.", "Please try using a different world.", ""); } else if (var0 == 14) { // L: 2818 - GameShell.setLoginResponseString("The server is being updated.", "Please wait 1 minute and try again.", ""); + GameEngine.setLoginResponseString("The server is being updated.", "Please wait 1 minute and try again.", ""); } else if (var0 == 16) { // L: 2819 - GameShell.setLoginResponseString("Too many login attempts.", "Please wait a few minutes before trying again.", ""); + GameEngine.setLoginResponseString("Too many login attempts.", "Please wait a few minutes before trying again.", ""); } else if (var0 == 17) { // L: 2820 - GameShell.setLoginResponseString("You are standing in a members-only area.", "To play on this world move to a free area first", ""); + GameEngine.setLoginResponseString("You are standing in a members-only area.", "To play on this world move to a free area first", ""); } else if (var0 == 18) { // L: 2821 Login.loginIndex = 12; // L: 2823 Login.field1199 = 1; // L: 2824 } else if (var0 == 19) { // L: 2827 - GameShell.setLoginResponseString("This world is running a closed Beta.", "Sorry invited players only.", "Please use a different world."); + GameEngine.setLoginResponseString("This world is running a closed Beta.", "Sorry invited players only.", "Please use a different world."); } else if (var0 == 20) { // L: 2828 - GameShell.setLoginResponseString("Invalid loginserver requested.", "Please try using a different world.", ""); + GameEngine.setLoginResponseString("Invalid loginserver requested.", "Please try using a different world.", ""); } else if (var0 == 22) { // L: 2829 - GameShell.setLoginResponseString("Malformed login packet.", "Please try again.", ""); + GameEngine.setLoginResponseString("Malformed login packet.", "Please try again.", ""); } else if (var0 == 23) { // L: 2830 - GameShell.setLoginResponseString("No reply from loginserver.", "Please wait 1 minute and try again.", ""); + GameEngine.setLoginResponseString("No reply from loginserver.", "Please wait 1 minute and try again.", ""); } else if (var0 == 24) { // L: 2831 - GameShell.setLoginResponseString("Error loading your profile.", "Please contact customer support.", ""); + GameEngine.setLoginResponseString("Error loading your profile.", "Please contact customer support.", ""); } else if (var0 == 25) { // L: 2832 - GameShell.setLoginResponseString("Unexpected loginserver response.", "Please try using a different world.", ""); + GameEngine.setLoginResponseString("Unexpected loginserver response.", "Please try using a different world.", ""); } else if (var0 == 26) { // L: 2833 - GameShell.setLoginResponseString("This computers address has been blocked", "as it was used to break our rules.", ""); + GameEngine.setLoginResponseString("This computers address has been blocked", "as it was used to break our rules.", ""); } else if (var0 == 27) { // L: 2834 - GameShell.setLoginResponseString("", "Service unavailable.", ""); + GameEngine.setLoginResponseString("", "Service unavailable.", ""); } else if (var0 == 31) { // L: 2835 - GameShell.setLoginResponseString("Your account must have a displayname set", "in order to play the game. Please set it", "via the website, or the main game."); + GameEngine.setLoginResponseString("Your account must have a displayname set", "in order to play the game. Please set it", "via the website, or the main game."); } else if (var0 == 32) { - GameShell.setLoginResponseString("Your attempt to log into your account was", "unsuccessful. Don't worry, you can sort", "this out by visiting the billing system."); // L: 2836 + GameEngine.setLoginResponseString("Your attempt to log into your account was", "unsuccessful. Don't worry, you can sort", "this out by visiting the billing system."); // L: 2836 } else if (var0 == 37) { // L: 2837 - GameShell.setLoginResponseString("Your account is currently inaccessible.", "Please try again in a few minutes.", ""); + GameEngine.setLoginResponseString("Your account is currently inaccessible.", "Please try again in a few minutes.", ""); } else if (var0 == 38) { // L: 2838 - GameShell.setLoginResponseString("You need to vote to play!", "Visit runescape.com and vote,", "and then come back here!"); + GameEngine.setLoginResponseString("You need to vote to play!", "Visit runescape.com and vote,", "and then come back here!"); } else if (var0 == 55) { // L: 2839 Login.loginIndex = 8; // L: 2840 } else { if (var0 == 56) { // L: 2842 - GameShell.setLoginResponseString("Enter the 6-digit code generated by your", "authenticator app.", ""); // L: 2843 + GameEngine.setLoginResponseString("Enter the 6-digit code generated by your", "authenticator app.", ""); // L: 2843 WorldMapCacheName.updateGameState(11); // L: 2844 return; // L: 2845 } if (var0 == 57) { // L: 2847 - GameShell.setLoginResponseString("The code you entered was incorrect.", "Please try again.", ""); // L: 2848 + GameEngine.setLoginResponseString("The code you entered was incorrect.", "Please try again.", ""); // L: 2848 WorldMapCacheName.updateGameState(11); // L: 2849 return; // L: 2850 } @@ -124,11 +124,11 @@ public class UserComparator8 extends AbstractUserComparator { if (var0 == 61) { // L: 2852 Login.loginIndex = 7; // L: 2853 } else { - GameShell.setLoginResponseString("Unexpected server response", "Please try using a different world.", ""); // L: 2855 + GameEngine.setLoginResponseString("Unexpected server response", "Please try using a different world.", ""); // L: 2855 } } } else { - GameShell.setLoginResponseString("RuneScape has been updated!", "Please reload this page.", ""); // L: 2809 + GameEngine.setLoginResponseString("RuneScape has been updated!", "Please reload this page.", ""); // L: 2809 } WorldMapCacheName.updateGameState(10); // L: 2856 diff --git a/runescape-client/src/main/java/WorldMapRectangle.java b/runescape-client/src/main/java/WorldMapRectangle.java index 2a05e24647..cb925cfab9 100644 --- a/runescape-client/src/main/java/WorldMapRectangle.java +++ b/runescape-client/src/main/java/WorldMapRectangle.java @@ -140,7 +140,7 @@ public final class WorldMapRectangle { WorldMapSprite.archive1.clearFiles(); // L: 2905 class330.archive3.clearFiles(); // L: 2906 class227.archive4.clearFiles(); // L: 2907 - GameShell.archive5.clearFiles(); // L: 2908 + GameEngine.archive5.clearFiles(); // L: 2908 class217.archive6.clearFiles(); // L: 2909 BuddyRankComparator.archive7.clearFiles(); // L: 2910 Messages.archive8.clearFiles(); // L: 2911 diff --git a/runescape-client/src/main/java/WorldMapSection1.java b/runescape-client/src/main/java/WorldMapSection1.java index e383cd225e..0b7208b2f0 100644 --- a/runescape-client/src/main/java/WorldMapSection1.java +++ b/runescape-client/src/main/java/WorldMapSection1.java @@ -182,7 +182,7 @@ public class WorldMapSection1 implements WorldMapSection { switch(var0) { // L: 2941 case 1: Login.loginIndex = 24; // L: 2950 - GameShell.setLoginResponseString("", "You were disconnected from the server.", ""); // L: 2951 + GameEngine.setLoginResponseString("", "You were disconnected from the server.", ""); // L: 2951 break; case 2: Messages.method2285(); // L: 2944 diff --git a/runescape-client/src/main/java/class7.java b/runescape-client/src/main/java/class7.java index 5ebfdf7f0c..187c84a75f 100644 --- a/runescape-client/src/main/java/class7.java +++ b/runescape-client/src/main/java/class7.java @@ -444,7 +444,7 @@ public enum class7 implements Enumerated { static void method83() { Login.Login_username = Login.Login_username.trim(); // L: 896 if (Login.Login_username.length() == 0) { // L: 897 - GameShell.setLoginResponseString("Please enter your username.", "If you created your account after November", "2010, this will be the creation email address."); // L: 898 + GameEngine.setLoginResponseString("Please enter your username.", "If you created your account after November", "2010, this will be the creation email address."); // L: 898 } else { long var1; try { @@ -488,23 +488,23 @@ public enum class7 implements Enumerated { switch(var0) { // L: 936 case 2: - GameShell.setLoginResponseString(Strings.field3053, Strings.field3054, Strings.field3055); // L: 941 + GameEngine.setLoginResponseString(Strings.field3053, Strings.field3054, Strings.field3055); // L: 941 Login.loginIndex = 6; // L: 942 break; // L: 943 case 3: - GameShell.setLoginResponseString("", "Error connecting to server.", ""); // L: 954 + GameEngine.setLoginResponseString("", "Error connecting to server.", ""); // L: 954 break; case 4: - GameShell.setLoginResponseString("The part of the website you are trying", "to connect to is offline at the moment.", "Please try again later."); // L: 951 + GameEngine.setLoginResponseString("The part of the website you are trying", "to connect to is offline at the moment.", "Please try again later."); // L: 951 break; // L: 952 case 5: - GameShell.setLoginResponseString("Sorry, there was an error trying to", "log you in to this part of the website.", "Please try again later."); // L: 938 + GameEngine.setLoginResponseString("Sorry, there was an error trying to", "log you in to this part of the website.", "Please try again later."); // L: 938 break; // L: 939 case 6: - GameShell.setLoginResponseString("", "Error connecting to server.", ""); // L: 948 + GameEngine.setLoginResponseString("", "Error connecting to server.", ""); // L: 948 break; // L: 949 case 7: - GameShell.setLoginResponseString("You must enter a valid login to proceed. For accounts", "created after 24th November 2010, please use your", "email address. Otherwise please use your username."); // L: 945 + GameEngine.setLoginResponseString("You must enter a valid login to proceed. For accounts", "created after 24th November 2010, please use your", "email address. Otherwise please use your username."); // L: 945 } }