diff --git a/client/build.gradle b/client/build.gradle
index 394d215..b559543 100644
--- a/client/build.gradle
+++ b/client/build.gradle
@@ -1,6 +1,7 @@
plugins {
id 'java'
id 'application'
+ id 'org.jetbrains.kotlin.jvm' version '1.4.10'
}
mainClassName = 'rt4.client'
@@ -35,6 +36,8 @@ dependencies {
implementation 'lib:jogl-all-natives-linux-i586'
implementation 'lib:jogl-all-natives-macosx-universal'
implementation 'lib:jogl-all-natives-android-aarch64'
+
+ runtime 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.10'
}
jar {
@@ -42,4 +45,5 @@ jar {
attributes 'Main-Class': "$mainClassName"
}
from { configurations.compileClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
+ duplicatesStrategy = DuplicatesStrategy.INCLUDE
}
diff --git a/client/src/main/java/plugin/Plugin.java b/client/src/main/java/plugin/Plugin.java
index c9fc977..fd09102 100644
--- a/client/src/main/java/plugin/Plugin.java
+++ b/client/src/main/java/plugin/Plugin.java
@@ -37,8 +37,10 @@ public abstract class Plugin {
/**
* OnXPUpdate() is called when the client receives an XP update packet. This includes at login.
+ * @param skill - the skill ID being updated
+ * @param xp - the new total XP for the skill.
*/
- public void OnXPUpdate() {}
+ public void OnXPUpdate(int skill, int xp) {}
/**
* Update() is called once per tick, aka once every 600ms.
@@ -81,4 +83,9 @@ public abstract class Plugin {
* @param value the value the varp is being set to.
*/
public void OnVarpUpdate(int id, int value) {}
+
+ /**
+ * OnLogout is called when the client logs out. This should be used to clear player-relevant plugin state.
+ */
+ public void OnLogout() {}
}
diff --git a/client/src/main/java/plugin/PluginRepository.java b/client/src/main/java/plugin/PluginRepository.java
index 4f2e7d5..89fa1e3 100644
--- a/client/src/main/java/plugin/PluginRepository.java
+++ b/client/src/main/java/plugin/PluginRepository.java
@@ -103,4 +103,12 @@ public class PluginRepository {
public static void OnVarpUpdate(int id, int value) {
loadedPlugins.values().forEach((plugin) -> plugin.OnVarpUpdate(id, value));
}
+
+ public static void OnXPUpdate(int skill, int xp) {
+ loadedPlugins.values().forEach((plugin) -> plugin.OnXPUpdate(skill, xp));
+ }
+
+ public static void OnLogout() {
+ loadedPlugins.values().forEach(Plugin::OnLogout);
+ }
}
diff --git a/client/src/main/java/plugin/api/API.java b/client/src/main/java/plugin/api/API.java
index 157ddb1..2db5ca8 100644
--- a/client/src/main/java/plugin/api/API.java
+++ b/client/src/main/java/plugin/api/API.java
@@ -1,6 +1,10 @@
package plugin.api;
import rt4.*;
+import rt4.DisplayMode;
+import rt4.Font;
+
+import java.awt.*;
/**
* API used for writing plugins, so dozens of plugins don't break when we rename shit :)
@@ -8,7 +12,7 @@ import rt4.*;
*/
public class API {
public static void DrawText(FontType fontType, FontColor color, TextModifier mod, String text, int screenX, int screenY) {
- JagString js = JagString.parse(text);
+ JagString js = JagString.of(text);
Font font;
switch (fontType) {
@@ -51,4 +55,60 @@ public class API {
public static boolean IsHD() {
return GlRenderer.enabled;
}
+
+ public static Sprite GetSprite(int spriteId) {
+ Sprite rawSprite = null;
+
+ if (client.js5Archive8.isFileReady(spriteId)) {
+ rawSprite = SpriteLoader.loadSprites(spriteId, client.js5Archive8);
+ }
+
+ return rawSprite;
+ }
+
+ public static WindowMode GetWindowMode() {
+ int mode = DisplayMode.getWindowMode();
+ switch(mode) {
+ case 2:
+ return WindowMode.RESIZABLE;
+ case 3:
+ return WindowMode.FULLSCREEN;
+ default:
+ return WindowMode.FIXED;
+ }
+ }
+
+ public static Dimension GetWindowDimensions() {
+ return new Dimension(GameShell.canvasWidth, GameShell.canvasHeight);
+ }
+
+ public static void FillRect(int x, int y, int width, int height, int color, int alpha) {
+ if (IsHD()) {
+ if (alpha != 0)
+ GlRaster.fillRectAlpha(x,y,width,height,color,alpha);
+ else
+ GlRaster.fillRect(x,y,width,height,color);
+ } else {
+ if (alpha != 0)
+ SoftwareRaster.fillRectAlpha(x,y,width,height,color,alpha);
+ else
+ SoftwareRaster.fillRect(x,y,width,height,color);
+ }
+ }
+
+ public static void DrawRect(int x, int y, int width, int height, int color) {
+ if (IsHD()) {
+ GlRaster.drawRect(x, y, width, height, color);
+ } else {
+ SoftwareRaster.drawRect(x, y, width, height, color);
+ }
+ }
+
+ public static void ClipRect(int x, int y, int width, int height) {
+ if (IsHD()) {
+ GlRaster.setClip(x,y,width,height);
+ } else {
+ SoftwareRaster.setClip(x,y,width,height);
+ }
+ }
}
diff --git a/client/src/main/java/plugin/api/FontColor.java b/client/src/main/java/plugin/api/FontColor.java
index 8b6a772..a7e43e7 100644
--- a/client/src/main/java/plugin/api/FontColor.java
+++ b/client/src/main/java/plugin/api/FontColor.java
@@ -12,6 +12,6 @@ public class FontColor {
}
public static FontColor fromColor(Color color) {
- return new FontColor(color.getRed() << 16 + color.getGreen() << 8 + color.getBlue());
+ return new FontColor((color.getRed() << 16) + (color.getGreen() << 8) + color.getBlue());
}
}
diff --git a/client/src/main/java/plugin/api/WindowMode.java b/client/src/main/java/plugin/api/WindowMode.java
new file mode 100644
index 0000000..f4b2a1b
--- /dev/null
+++ b/client/src/main/java/plugin/api/WindowMode.java
@@ -0,0 +1,7 @@
+package plugin.api;
+
+public enum WindowMode {
+ FIXED,
+ RESIZABLE,
+ FULLSCREEN
+}
diff --git a/client/src/main/java/rt4/Cheat.java b/client/src/main/java/rt4/Cheat.java
index 9f046f2..8a42f14 100644
--- a/client/src/main/java/rt4/Cheat.java
+++ b/client/src/main/java/rt4/Cheat.java
@@ -102,7 +102,7 @@ public class Cheat {
@OriginalMember(owner = "client!en", name = "a", descriptor = "(IIIB)V")
public static void teleport(@OriginalArg(0) int arg0, @OriginalArg(1) int arg1, @OriginalArg(2) int arg2) {
- @Pc(66) JagString local66 = JagString.concatenate(new JagString[]{aClass100_521, JagString.parseInt(arg2), Cs1ScriptRunner.aClass100_760, JagString.parseInt(arg0 >> 6), Cs1ScriptRunner.aClass100_760, JagString.parseInt(arg1 >> 6), Cs1ScriptRunner.aClass100_760, JagString.parseInt(arg0 & 0x3F), Cs1ScriptRunner.aClass100_760, JagString.parseInt(arg1 & 0x3F)});
+ @Pc(66) JagString local66 = JagString.concatenate(new JagString[]{aClass100_521, JagString.parseInt(arg2), JagString.aClass100_760, JagString.parseInt(arg0 >> 6), JagString.aClass100_760, JagString.parseInt(arg1 >> 6), JagString.aClass100_760, JagString.parseInt(arg0 & 0x3F), JagString.aClass100_760, JagString.parseInt(arg1 & 0x3F)});
local66.print();
execute(local66);
}
diff --git a/client/src/main/java/rt4/Cs1ScriptRunner.java b/client/src/main/java/rt4/Cs1ScriptRunner.java
index 8639838..0bf1897 100644
--- a/client/src/main/java/rt4/Cs1ScriptRunner.java
+++ b/client/src/main/java/rt4/Cs1ScriptRunner.java
@@ -34,22 +34,6 @@ public class Cs1ScriptRunner {
public static final int anInt671 = 0x332d25;
@OriginalMember(owner = "client!pg", name = "V", descriptor = "I")
public static final int anInt4504 = 50;
- @OriginalMember(owner = "client!wa", name = "pb", descriptor = "Lclient!na;")
- public static final JagString aClass100_556 = JagString.parse("
");
- @OriginalMember(owner = "client!ed", name = "H", descriptor = "Lclient!na;")
- public static final JagString aClass100_375 = JagString.parse("<)4col> x");
- @OriginalMember(owner = "client!je", name = "db", descriptor = "Lclient!na;")
- public static final JagString aClass100_589 = JagString.parse("
");
- @OriginalMember(owner = "client!uf", name = "s", descriptor = "Lclient!na;")
- public static final JagString aClass100_1043 = JagString.parse(" ");
- @OriginalMember(owner = "client!wj", name = "b", descriptor = "Lclient!na;")
- public static final JagString aClass100_1101 = JagString.parse(" ");
- @OriginalMember(owner = "client!mi", name = "R", descriptor = "Lclient!na;")
- public static final JagString aClass100_760 = JagString.parse(")1");
- @OriginalMember(owner = "client!sj", name = "w", descriptor = "Lclient!na;")
- public static final JagString aClass100_978 = JagString.parse("<)4col>");
- @OriginalMember(owner = "client!jb", name = "c", descriptor = "Lclient!na;")
- public static final JagString aClass100_583 = JagString.parse("(Y<)4col>");
@OriginalMember(owner = "client!th", name = "m", descriptor = "[Lclient!be;")
public static Component[] aClass13Array13;
@OriginalMember(owner = "client!k", name = "j", descriptor = "I")
@@ -776,7 +760,7 @@ public class Cs1ScriptRunner {
local1934 = MiniMenu.NULL;
}
if ((local1989.stackable == 1 || component.objCount != 1) && component.objCount != -1) {
- local1934 = JagString.concatenate(new JagString[]{MiniMenu.aClass100_32, local1934, aClass100_375, method1548(component.objCount)});
+ local1934 = JagString.concatenate(new JagString[]{MiniMenu.aClass100_32, local1934, JagString.aClass100_375, method1548(component.objCount)});
}
}
if (aClass13_10 == component) {
@@ -1018,9 +1002,9 @@ public class Cs1ScriptRunner {
local2611 = ObjTypeList.get(component.objTypes[local276] - 1);
@Pc(3159) JagString local3159;
if (local2611.stackable != 1 && component.objCounts[local276] == 1) {
- local3159 = JagString.concatenate(new JagString[]{MiniMenu.aClass100_32, local2611.name, aClass100_978});
+ local3159 = JagString.concatenate(new JagString[]{MiniMenu.aClass100_32, local2611.name, JagString.aClass100_978});
} else {
- local3159 = JagString.concatenate(new JagString[]{MiniMenu.aClass100_32, local2611.name, aClass100_375, method1548(component.objCounts[local276])});
+ local3159 = JagString.concatenate(new JagString[]{MiniMenu.aClass100_32, local2611.name, JagString.aClass100_375, method1548(component.objCounts[local276])});
}
local556 = local123 + memory * (component.invMarginX + 115);
objId = (component.invMarginY + 12) * local468 + local114;
@@ -1045,7 +1029,7 @@ public class Cs1ScriptRunner {
local3297 = interpolate(component, local3297);
@Pc(3325) JagString local3325;
while (local3297.length() > 0) {
- cardMemory = local3297.indexOf(aClass100_556);
+ cardMemory = local3297.indexOf(JagString.aClass100_556);
if (cardMemory == -1) {
local3325 = local3297;
local3297 = JagString.EMPTY;
@@ -1083,7 +1067,7 @@ public class Cs1ScriptRunner {
objId = local556 + local3299.lineHeight + 2;
local3297 = interpolate(component, local3297);
while (local3297.length() > 0) {
- local563 = local3297.indexOf(aClass100_556);
+ local563 = local3297.indexOf(JagString.aClass100_556);
if (local563 == -1) {
local3325 = local3297;
local3297 = JagString.EMPTY;
@@ -1257,14 +1241,14 @@ public class Cs1ScriptRunner {
public static JagString method1548(@OriginalArg(1) int arg0) {
@Pc(9) JagString local9 = JagString.parseInt(arg0);
for (@Pc(21) int local21 = local9.length() - 3; local21 > 0; local21 -= 3) {
- local9 = JagString.concatenate(new JagString[]{local9.substring(local21, 0), aClass100_760, local9.substring(local21)});
+ local9 = JagString.concatenate(new JagString[]{local9.substring(local21, 0), JagString.aClass100_760, local9.substring(local21)});
}
if (local9.length() > 9) {
- return JagString.concatenate(new JagString[]{aClass100_1043, local9.substring(local9.length() - 8, 0), LocalizedText.MILLION_SHORT, MiniMenu.OPEN_PARENTHESIS, local9, aClass100_583});
+ return JagString.concatenate(new JagString[]{JagString.aClass100_1043, local9.substring(local9.length() - 8, 0), LocalizedText.MILLION_SHORT, MiniMenu.OPEN_PARENTHESIS, local9, JagString.aClass100_583});
} else if (local9.length() > 6) {
- return JagString.concatenate(new JagString[]{aClass100_589, local9.substring(local9.length() - 4, 0), LocalizedText.THOUSAND_SHORT, MiniMenu.OPEN_PARENTHESIS, local9, aClass100_583});
+ return JagString.concatenate(new JagString[]{JagString.aClass100_589, local9.substring(local9.length() - 4, 0), LocalizedText.THOUSAND_SHORT, MiniMenu.OPEN_PARENTHESIS, local9, JagString.aClass100_583});
} else {
- return JagString.concatenate(new JagString[]{aClass100_1101, local9, aClass100_978});
+ return JagString.concatenate(new JagString[]{JagString.aClass100_1101, local9, JagString.aClass100_978});
}
}
diff --git a/client/src/main/java/rt4/DateUtil.java b/client/src/main/java/rt4/DateUtil.java
index 8933053..6def766 100644
--- a/client/src/main/java/rt4/DateUtil.java
+++ b/client/src/main/java/rt4/DateUtil.java
@@ -12,16 +12,6 @@ public final class DateUtil {
@OriginalMember(owner = "client!cl", name = "K", descriptor = "Ljava/util/Calendar;")
public static final Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
- @OriginalMember(owner = "client!fn", name = "Z", descriptor = "Lclient!na;")
- public static final JagString aClass100_461 = JagString.parse(")1 ");
- @OriginalMember(owner = "client!wb", name = "a", descriptor = "Lclient!na;")
- public static final JagString aClass100_1089 = JagString.parse(")2");
- @OriginalMember(owner = "client!dm", name = "j", descriptor = "Lclient!na;")
- public static final JagString SPACE = JagString.parse(" ");
- @OriginalMember(owner = "client!vh", name = "c", descriptor = "Lclient!na;")
- public static final JagString COLON = JagString.parse(":");
- @OriginalMember(owner = "client!ee", name = "a", descriptor = "Lclient!na;")
- public static final JagString TIMEZONE = JagString.parse(" GMT");
@OriginalMember(owner = "client!km", name = "tc", descriptor = "Lclient!na;")
private static final JagString DEC = JagString.parse("Dec");
@@ -104,6 +94,6 @@ public final class DateUtil {
@Pc(36) int local36 = calendar.get(Calendar.HOUR_OF_DAY);
@Pc(40) int local40 = calendar.get(Calendar.MINUTE);
@Pc(44) int local44 = calendar.get(Calendar.SECOND);
- return JagString.concatenate(new JagString[]{DAYS[local13 - 1], aClass100_461, JagString.parseInt(local17 / 10), JagString.parseInt(local17 % 10), aClass100_1089, MONTHS[local21], aClass100_1089, JagString.parseInt(local32), SPACE, JagString.parseInt(local36 / 10), JagString.parseInt(local36 % 10), COLON, JagString.parseInt(local40 / 10), JagString.parseInt(local40 % 10), COLON, JagString.parseInt(local44 / 10), JagString.parseInt(local44 % 10), TIMEZONE});
+ return JagString.concatenate(new JagString[]{DAYS[local13 - 1], JagString.aClass100_461, JagString.parseInt(local17 / 10), JagString.parseInt(local17 % 10), JagString.aClass100_1089, MONTHS[local21], JagString.aClass100_1089, JagString.parseInt(local32), JagString.SPACE, JagString.parseInt(local36 / 10), JagString.parseInt(local36 % 10), JagString.COLON, JagString.parseInt(local40 / 10), JagString.parseInt(local40 % 10), JagString.COLON, JagString.parseInt(local44 / 10), JagString.parseInt(local44 % 10), JagString.TIMEZONE});
}
}
diff --git a/client/src/main/java/rt4/DisplayMode.java b/client/src/main/java/rt4/DisplayMode.java
index e892fde..06cfcb9 100644
--- a/client/src/main/java/rt4/DisplayMode.java
+++ b/client/src/main/java/rt4/DisplayMode.java
@@ -75,7 +75,7 @@ public final class DisplayMode {
}
@OriginalMember(owner = "client!pm", name = "a", descriptor = "(ZIZIZII)V")
- public static void setWindowMode(@OriginalArg(0) boolean arg0, @OriginalArg(1) int arg1, @OriginalArg(2) boolean arg2, @OriginalArg(3) int arg3, @OriginalArg(5) int arg4, @OriginalArg(6) int arg5) {
+ public static void setWindowMode(@OriginalArg(0) boolean arg0, @OriginalArg(1) int arg1, @OriginalArg(2) boolean arg2, @OriginalArg(3) int mode, @OriginalArg(5) int arg4, @OriginalArg(6) int arg5) {
if (arg2) {
GlRenderer.quit();
}
@@ -92,7 +92,7 @@ public final class DisplayMode {
}
}
if (arg1 == 3 && GameShell.fullScreenFrame == null) {
- setWindowMode(true, Preferences.favoriteWorlds, true, arg3, -1, -1);
+ setWindowMode(true, Preferences.favoriteWorlds, true, mode, -1, -1);
return;
}
@Pc(85) Container local85;
@@ -146,7 +146,7 @@ public final class DisplayMode {
GameShell.canvas.setLocation(GameShell.leftMargin, GameShell.topMargin);
}
}
- if (arg1 == 0 && arg3 > 0) {
+ if (arg1 == 0 && mode > 0) {
GlRenderer.createAndDestroyContext(GameShell.canvas);
}
if (arg2 && arg1 > 0) {
@@ -167,7 +167,7 @@ public final class DisplayMode {
} catch (@Pc(277) Exception local277) {
}
GameShell.method2704();
- if (arg3 == 0) {
+ if (mode == 0) {
SoftwareRaster.frameBuffer = FrameBuffer.create(503, 765, GameShell.canvas);
} else {
SoftwareRaster.frameBuffer = null;
@@ -185,10 +185,10 @@ public final class DisplayMode {
}
}
if (!GlRenderer.enabled && arg1 > 0) {
- setWindowMode(true, 0, true, arg3, -1, -1);
+ setWindowMode(true, 0, true, mode, -1, -1);
return;
}
- if (arg1 > 0 && arg3 == 0) {
+ if (arg1 > 0 && mode == 0) {
GameShell.thread.setPriority(5);
SoftwareRaster.frameBuffer = null;
SoftwareModel.method4580();
@@ -197,7 +197,7 @@ public final class DisplayMode {
Rasteriser.setBrightness(0.7F);
}
LoginManager.method4637();
- } else if (arg1 == 0 && arg3 > 0) {
+ } else if (arg1 == 0 && mode > 0) {
GameShell.thread.setPriority(1);
SoftwareRaster.frameBuffer = FrameBuffer.create(503, 765, GameShell.canvas);
SoftwareModel.method4583();
diff --git a/client/src/main/java/rt4/JagString.java b/client/src/main/java/rt4/JagString.java
index fb8be2d..449090e 100644
--- a/client/src/main/java/rt4/JagString.java
+++ b/client/src/main/java/rt4/JagString.java
@@ -19,13 +19,39 @@ public final class JagString implements StringInterface {
@OriginalMember(owner = "client!pi", name = "Q", descriptor = "Lclient!na;")
public static final JagString aClass100_853 = parse("null");
@OriginalMember(owner = "client!t", name = "C", descriptor = "Lclient!na;")
- public static final JagString aClass100_994 = parse(")3");
+ public static final JagString PERIOD = parse(")3");
@OriginalMember(owner = "client!vk", name = "a", descriptor = "[I")
public static final int[] anIntArray471 = new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 73, 74, 76, 78, 83, 84, 85, 86, 91, 92, 93, 94, 95, 97, 103, 104, 105, 106, 107, 108, 113, 114, 115, 116, 118, 119, 120, 121, 122, 123, 124, 125, 133, 134, 136, 138, 143, 144, 145, 146, 151, 152, 153, 154, 155, 157, 163, 164, 165, 166, 168, 169, 174, 175, 176, 177, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 97, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 157, 215, 216, 117, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 66, 66, 66, 66, 66, 66, 65, 75, 79, 79, 79, 79, 87, 87, 87, 87, 77, 96, 98, 98, 98, 98, 98, 250, 251, 109, 109, 109, 109, 117, 252, 167, 126, 126, 126, 126, 126, 126, 125, 135, 139, 139, 139, 139, 147, 147, 147, 147, 137, 156, 158, 158, 158, 158, 158, 253, 254, 170, 170, 170, 170, 178, 255, 178};
@OriginalMember(owner = "client!sh", name = "e", descriptor = "Lclient!na;")
public static final JagString aClass100_967 = parse("");
@OriginalMember(owner = "client!dm", name = "n", descriptor = "Lclient!na;")
public static final JagString PERCENT_SIGN = parse("(U");
+ @OriginalMember(owner = "client!wa", name = "pb", descriptor = "Lclient!na;")
+ public static final JagString aClass100_556 = parse("
");
+ @OriginalMember(owner = "client!ed", name = "H", descriptor = "Lclient!na;")
+ public static final JagString aClass100_375 = parse("<)4col> x");
+ @OriginalMember(owner = "client!je", name = "db", descriptor = "Lclient!na;")
+ public static final JagString aClass100_589 = parse(" ");
+ @OriginalMember(owner = "client!uf", name = "s", descriptor = "Lclient!na;")
+ public static final JagString aClass100_1043 = parse(" ");
+ @OriginalMember(owner = "client!wj", name = "b", descriptor = "Lclient!na;")
+ public static final JagString aClass100_1101 = parse(" ");
+ @OriginalMember(owner = "client!mi", name = "R", descriptor = "Lclient!na;")
+ public static final JagString aClass100_760 = parse(")1");
+ @OriginalMember(owner = "client!sj", name = "w", descriptor = "Lclient!na;")
+ public static final JagString aClass100_978 = parse("<)4col>");
+ @OriginalMember(owner = "client!jb", name = "c", descriptor = "Lclient!na;")
+ public static final JagString aClass100_583 = parse("(Y<)4col>");
+ @OriginalMember(owner = "client!fn", name = "Z", descriptor = "Lclient!na;")
+ public static final JagString aClass100_461 = parse(")1 ");
+ @OriginalMember(owner = "client!wb", name = "a", descriptor = "Lclient!na;")
+ public static final JagString aClass100_1089 = parse(")2");
+ @OriginalMember(owner = "client!dm", name = "j", descriptor = "Lclient!na;")
+ public static final JagString SPACE = parse(" ");
+ @OriginalMember(owner = "client!vh", name = "c", descriptor = "Lclient!na;")
+ public static final JagString COLON = parse(":");
+ @OriginalMember(owner = "client!ee", name = "a", descriptor = "Lclient!na;")
+ public static final JagString TIMEZONE = parse(" GMT");
@OriginalMember(owner = "client!li", name = "w", descriptor = "Lclient!sc;")
public static HashTable aClass133_13;
@OriginalMember(owner = "client!na", name = "T", descriptor = "[B")
@@ -203,7 +229,7 @@ public final class JagString implements StringInterface {
@OriginalMember(owner = "client!oi", name = "a", descriptor = "(II)Lclient!na;")
public static JagString formatIp(@OriginalArg(0) int arg0) {
- return concatenate(new JagString[]{parseInt(arg0 >> 24 & 0xFF), aClass100_994, parseInt(arg0 >> 16 & 0xFF), aClass100_994, parseInt(arg0 >> 8 & 0xFF), aClass100_994, parseInt(arg0 & 0xFF)});
+ return concatenate(new JagString[]{parseInt(arg0 >> 24 & 0xFF), PERIOD, parseInt(arg0 >> 16 & 0xFF), PERIOD, parseInt(arg0 >> 8 & 0xFF), PERIOD, parseInt(arg0 & 0xFF)});
}
@OriginalMember(owner = "client!nb", name = "a", descriptor = "(II)Lclient!na;")
@@ -215,18 +241,21 @@ public final class JagString implements StringInterface {
return str;
}
+ /**
+ * @return A JagString consisting of the actual bytes in the provided string.
+ */
@OriginalMember(owner = "client!sj", name = "a", descriptor = "(Ljava/lang/String;I)Lclient!na;")
- public static JagString method3952(@OriginalArg(0) String arg0) {
- @Pc(14) byte[] local14 = arg0.getBytes(StandardCharsets.ISO_8859_1);
- @Pc(23) JagString local23 = new JagString();
- local23.chars = local14;
- local23.length = 0;
- for (@Pc(31) int local31 = 0; local31 < local14.length; local31++) {
- if (local14[local31] != 0) {
- local14[local23.length++] = local14[local31];
+ public static JagString of(@OriginalArg(0) String string) {
+ @Pc(14) byte[] bytes = string.getBytes(StandardCharsets.ISO_8859_1);
+ @Pc(23) JagString js = new JagString();
+ js.chars = bytes;
+ js.length = 0;
+ for (@Pc(31) int i = 0; i < bytes.length; i++) {
+ if (bytes[i] != 0) {
+ bytes[js.length++] = bytes[i];
}
}
- return local23;
+ return js;
}
@OriginalMember(owner = "client!gn", name = "a", descriptor = "(BI)Lclient!na;")
@@ -983,7 +1012,7 @@ public final class JagString implements StringInterface {
public final JagString fromParameters(@OriginalArg(1) Applet arg0) {
@Pc(19) String local19 = new String(this.chars, 0, this.length);
@Pc(23) String local23 = arg0.getParameter(local19);
- return local23 == null ? null : method3952(local23);
+ return local23 == null ? null : of(local23);
}
@OriginalMember(owner = "client!na", name = "d", descriptor = "(Z)I")
diff --git a/client/src/main/java/rt4/LoginManager.java b/client/src/main/java/rt4/LoginManager.java
index 58dbba3..dc7eff6 100644
--- a/client/src/main/java/rt4/LoginManager.java
+++ b/client/src/main/java/rt4/LoginManager.java
@@ -3,6 +3,7 @@ package rt4;
import org.openrs2.deob.annotation.OriginalArg;
import org.openrs2.deob.annotation.OriginalMember;
import org.openrs2.deob.annotation.Pc;
+import plugin.PluginRepository;
import java.io.IOException;
import java.net.Socket;
@@ -690,6 +691,7 @@ public class LoginManager {
Protocol.verifyId = 0;
VarpDomain.reset();
InterfaceList.method1596(true);
+ PluginRepository.OnLogout();
}
@OriginalMember(owner = "client!k", name = "a", descriptor = "(IIIIZIZ)V")
diff --git a/client/src/main/java/rt4/Protocol.java b/client/src/main/java/rt4/Protocol.java
index 0c3aef4..ebd2de3 100644
--- a/client/src/main/java/rt4/Protocol.java
+++ b/client/src/main/java/rt4/Protocol.java
@@ -3,6 +3,7 @@ package rt4;
import org.openrs2.deob.annotation.OriginalArg;
import org.openrs2.deob.annotation.OriginalMember;
import org.openrs2.deob.annotation.Pc;
+import plugin.PluginRepository;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
@@ -967,7 +968,7 @@ public class Protocol {
} else if (opcode == ServerProt.MESSAGE_GAME) {
@Pc(245) JagString message = inboundBuffer.gjstr();
if (message.endsWith(TRADEREQ)) {
- JagString name = message.substring(message.indexOf(DateUtil.COLON), 0);
+ JagString name = message.substring(message.indexOf(JagString.COLON), 0);
long name37 = name.encode37();
boolean ignored = false;
for (int i = 0; i < IgnoreList.size; i++) {
@@ -980,7 +981,7 @@ public class Protocol {
Chat.add(name, 4, LocalizedText.TRADEREQ);
}
} else if (message.endsWith(CHALREQ)) {
- JagString name = message.substring(message.indexOf(DateUtil.COLON), 0);
+ JagString name = message.substring(message.indexOf(JagString.COLON), 0);
long name37 = name.encode37();
boolean ignored = false;
for (int i = 0; i < IgnoreList.size; i++) {
@@ -990,11 +991,11 @@ public class Protocol {
}
}
if (!ignored && Player.inTutorialIsland == 0) {
- JagString local506 = message.substring(message.length() - 9, message.indexOf(DateUtil.COLON) + 1);
+ JagString local506 = message.substring(message.length() - 9, message.indexOf(JagString.COLON) + 1);
Chat.add(name, 8, local506);
}
} else if (message.endsWith(ASSISTREQ)) {
- JagString name = message.substring(message.indexOf(DateUtil.COLON), 0);
+ JagString name = message.substring(message.indexOf(JagString.COLON), 0);
long name37 = name.encode37();
boolean ignored = false;
for (int i = 0; i < IgnoreList.size; i++) {
@@ -1020,7 +1021,7 @@ public class Protocol {
Chat.add(JagString.EMPTY, 13, name);
}
} else if (message.endsWith(DUELSTAKE)) {
- JagString name = message.substring(message.indexOf(DateUtil.COLON), 0);
+ JagString name = message.substring(message.indexOf(JagString.COLON), 0);
long name37 = name.encode37();
boolean ignored = false;
for (int i = 0; i < IgnoreList.size; i++) {
@@ -1033,7 +1034,7 @@ public class Protocol {
Chat.add(name, 14, JagString.EMPTY);
}
} else if (message.endsWith(DUELFRIEND)) {
- JagString name = message.substring(message.indexOf(DateUtil.COLON), 0);
+ JagString name = message.substring(message.indexOf(JagString.COLON), 0);
long name37 = name.encode37();
boolean ignored = false;
for (int local277 = 0; local277 < IgnoreList.size; local277++) {
@@ -1046,7 +1047,7 @@ public class Protocol {
Chat.add(name, 15, JagString.EMPTY);
}
} else if (message.endsWith(aClass100_916)) {
- JagString name = message.substring(message.indexOf(DateUtil.COLON), 0);
+ JagString name = message.substring(message.indexOf(JagString.COLON), 0);
long name37 = name.encode37();
boolean ignored = false;
for (int i = 0; i < IgnoreList.size; i++) {
@@ -1059,7 +1060,7 @@ public class Protocol {
Chat.add(name, 16, JagString.EMPTY);
}
} else if (message.endsWith(aClass100_770)) {
- JagString name = message.substring(message.indexOf(DateUtil.COLON), 0);
+ JagString name = message.substring(message.indexOf(JagString.COLON), 0);
long name37 = name.encode37();
boolean ignored = false;
for (int i = 0; i < IgnoreList.size; i++) {
@@ -1069,7 +1070,7 @@ public class Protocol {
}
}
if (!ignored && Player.inTutorialIsland == 0) {
- JagString local506 = message.substring(message.length() - 9, message.indexOf(DateUtil.COLON) + 1);
+ JagString local506 = message.substring(message.length() - 9, message.indexOf(JagString.COLON) + 1);
Chat.add(name, 21, local506);
}
} else {
@@ -1459,6 +1460,7 @@ public class Protocol {
PlayerSkillXpTable.baseLevels[skill] = i + 2;
}
}
+ PluginRepository.OnXPUpdate(skill, xp);
PlayerSkillXpTable.updatedStats[PlayerSkillXpTable.updatedStatsWriterIndex++ & 0x1F] = skill;
opcode = -1;
return true;
diff --git a/client/src/main/java/rt4/client.java b/client/src/main/java/rt4/client.java
index dd87073..eee446d 100644
--- a/client/src/main/java/rt4/client.java
+++ b/client/src/main/java/rt4/client.java
@@ -776,7 +776,7 @@ public final class client extends GameShell {
} else if (gameState == 30) {
LoginManager.method1841();
} else if (gameState == 40) {
- Fonts.drawTextOnScreen(false, JagString.concatenate(new JagString[]{LocalizedText.CONLOST, Cs1ScriptRunner.aClass100_556, LocalizedText.ATTEMPT_TO_REESTABLISH}));
+ Fonts.drawTextOnScreen(false, JagString.concatenate(new JagString[]{LocalizedText.CONLOST, JagString.aClass100_556, LocalizedText.ATTEMPT_TO_REESTABLISH}));
}
if (GlRenderer.enabled && gameState != 0) {
GlRenderer.swapBuffers();
@@ -1020,7 +1020,7 @@ public final class client extends GameShell {
}
mainLoadPrimaryText = LocalizedText.GAME0_LOADING;
if (modeWhere != 0) {
- Cheat.displayFps = true;
+ //Cheat.displayFps = true;
}
}
diff --git a/plugin-playground/build.gradle b/plugin-playground/build.gradle
index 3000054..e993027 100644
--- a/plugin-playground/build.gradle
+++ b/plugin-playground/build.gradle
@@ -1,5 +1,6 @@
plugins {
id 'java'
+ id 'org.jetbrains.kotlin.jvm' version '1.4.10'
}
version 'unspecified'
@@ -15,6 +16,7 @@ dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
implementation(rootProject.project("client"))
+ compile 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.10'
}
test {
@@ -63,4 +65,6 @@ task buildPlugins(type: Copy, dependsOn: classes) {
def pluginsPath = rootProject.project("client").projectDir.absolutePath + File.separator + "plugins"
from "build/classes/java/main"
into pluginsPath
+ from "build/classes/kotlin/main"
+ into pluginsPath
}
\ No newline at end of file
diff --git a/plugin-playground/src/main/java/VarpLogPlugin/plugin.java b/plugin-playground/src/main/java/VarpLogPlugin/plugin.java
index a78ebe7..32c5431 100644
--- a/plugin-playground/src/main/java/VarpLogPlugin/plugin.java
+++ b/plugin-playground/src/main/java/VarpLogPlugin/plugin.java
@@ -8,7 +8,7 @@ import java.util.ArrayList;
import java.util.Date;
public class plugin extends Plugin {
- boolean isEnabled;
+ boolean isEnabled = false;
int MAX_VISIBLE_UPDATES = 5;
diff --git a/plugin-playground/src/main/kotlin/XPDropPlugin/plugin.kt b/plugin-playground/src/main/kotlin/XPDropPlugin/plugin.kt
new file mode 100644
index 0000000..f206877
--- /dev/null
+++ b/plugin-playground/src/main/kotlin/XPDropPlugin/plugin.kt
@@ -0,0 +1,171 @@
+package XPDropPlugin;
+
+import plugin.Plugin
+import plugin.api.*
+import java.awt.Color
+import kotlin.math.ceil
+
+/**
+ * Displays some simple XP drops.
+ * @author Ceikry
+ */
+class plugin : Plugin() {
+ private val displayTimeout = 10000L // 10 seconds
+ private val drawStart = 175
+ private val drawPadding = 25
+ private val drawClear = 60
+ private val lastXp = IntArray(24)
+ private var totalXp = 0
+ private val activeGains = ArrayList()
+ private var lastGain = 0L
+
+ override fun Draw(deltaTime: Long) {
+ if (System.currentTimeMillis() - lastGain >= displayTimeout && activeGains.isEmpty())
+ return
+
+ drawTotalXPBox()
+
+ val removeList = ArrayList()
+ var posX = API.GetWindowDimensions().width / 2
+
+ if (API.GetWindowMode() == WindowMode.FIXED)
+ posX += 60
+
+ for(gain in activeGains) {
+ gain.currentPos -= ceil(deltaTime / 20.0).toInt()
+ if (gain.currentPos <= drawClear) {
+ removeList.add(gain)
+ totalXp += gain.xp
+ } else if (gain.currentPos <= drawStart){
+ val sprite = API.GetSprite(getSpriteArchive(gain.skill))
+ sprite?.render(posX - 25, gain.currentPos - 20)
+ API.DrawText(
+ FontType.SMALL,
+ FontColor.fromColor(Color.WHITE),
+ TextModifier.LEFT,
+ addCommas(gain.xp.toString()),
+ posX,
+ gain.currentPos
+ )
+ }
+ }
+
+ activeGains.removeAll(removeList.toSet())
+ }
+
+ override fun OnXPUpdate(skill: Int, xp: Int) {
+ if (xp == lastXp[skill]) return
+
+ val gain = xp - lastXp[skill]
+ if (gain <= 0) return
+
+ lastXp[skill] = xp
+
+ val currentTail = try {
+ activeGains.last().currentPos
+ } catch (e: Exception) {
+ drawStart - drawPadding
+ }
+
+ activeGains.add(XPGain(skill, gain, currentTail + drawPadding))
+ lastGain = System.currentTimeMillis()
+ }
+
+ override fun OnLogout() {
+ lastGain = 0L
+ for (i in 0 until 24) lastXp[i] = 0
+ totalXp = 0
+ activeGains.clear()
+ }
+
+ private fun drawTotalXPBox() {
+ var posX = API.GetWindowDimensions().width / 2
+ val posY = API.GetWindowDimensions().height / 4
+
+ if (API.GetWindowMode() == WindowMode.FIXED)
+ posX += 60
+
+ API.ClipRect(0, 0, posX * 2, posY * 4)
+
+ val horizontal = API.GetSprite(822)
+ val horizontalTop = API.GetSprite(820)
+ val tlCorner = API.GetSprite(824)
+ val blCorner = API.GetSprite(826)
+ val trCorner = API.GetSprite(825)
+ val brCorner = API.GetSprite(827)
+ val bg = API.GetSprite(657)
+
+ bg?.render(posX - 77, 10)
+ API.FillRect(posX - 75, 5, 140, 30, 0, 64)
+
+ blCorner?.render(posX - 77, 10)
+ tlCorner?.render(posX - 77, 5)
+ trCorner?.render(posX + 41, 5)
+ brCorner?.render(posX + 41, 10)
+
+ horizontalTop?.render(posX - 45, -8)
+ horizontal?.render(posX - 45, 22)
+ horizontalTop?.render(posX - 15, -8)
+ horizontal?.render(posX - 15, 22)
+ horizontalTop?.render(posX + 9, -8)
+ horizontal?.render(posX + 9, 22)
+
+ API.DrawText(
+ FontType.SMALL,
+ FontColor.fromColor(Color.WHITE),
+ TextModifier.LEFT,
+ "Total Xp: ${addCommas(totalXp.toString())}",
+ posX - 65,
+ 28
+ )
+ }
+
+ data class XPGain(val skill: Int, val xp: Int, var currentPos: Int)
+
+ fun addCommas(num: String): String{
+ var newString = ""
+ if(num.length > 9){
+ return "Lots!"
+ }
+ var counter = 1
+ num.reversed().forEach {
+ if(counter % 3 == 0 && counter != num.length){
+ newString += "$it,"
+ } else {
+ newString += it
+ }
+ counter++
+ }
+ return newString.reversed()
+ }
+
+ fun getSpriteArchive(skillId: Int): Int{
+ return when(skillId) {
+ 0 -> 197
+ 1 -> 199
+ 2 -> 198
+ 3 -> 203
+ 4 -> 200
+ 5 -> 201
+ 6 -> 202
+ 7 -> 212
+ 8 -> 214
+ 9 -> 208
+ 10 -> 211
+ 11 -> 213
+ 12 -> 207
+ 13 -> 210
+ 14 -> 209
+ 15 -> 205
+ 16 -> 204
+ 17 -> 206
+ 18 -> 216
+ 19 -> 217
+ 20 -> 215
+ 21 -> 220
+ 22 -> 221
+ 23 -> 222
+ else -> 222
+ }
+ }
+}
diff --git a/plugin-playground/src/main/kotlin/XPDropPlugin/plugin.properties b/plugin-playground/src/main/kotlin/XPDropPlugin/plugin.properties
new file mode 100644
index 0000000..1e4001d
--- /dev/null
+++ b/plugin-playground/src/main/kotlin/XPDropPlugin/plugin.properties
@@ -0,0 +1,3 @@
+AUTHOR='Ceikry'
+DESCRIPTION='Displays some pretty awesome XP drops :)'
+VERSION=-1.1