From 1cf30d5375a472ccf41ac56ebbd44ef69a1473d6 Mon Sep 17 00:00:00 2001 From: George Farrell Date: Sun, 20 May 2018 18:45:43 +0100 Subject: [PATCH 01/34] [BUGFIX] Java check version --- src/main/java/org/parabot/Landing.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main/java/org/parabot/Landing.java b/src/main/java/org/parabot/Landing.java index 51c6a67..64bac34 100644 --- a/src/main/java/org/parabot/Landing.java +++ b/src/main/java/org/parabot/Landing.java @@ -24,9 +24,22 @@ import java.io.IOException; public final class Landing { private static String username; private static String password; + private static double JAVA_VERSION = getVersion (); + + static double getVersion () { + String version = System.getProperty("java.version"); + int pos = version.indexOf('.'); + pos = version.indexOf('.', pos+1); + return Double.parseDouble (version.substring (0, pos)); + } + public static void main(String... args) throws IOException { + if (JAVA_VERSION >= 9){ + UILog.log("Parabot", "Please downgrade to Java 8 in order to use Parabot"); + System.exit(0); + } parseArgs(args); Directories.validate(); From 01a12a50b560f7167967f9429c2a3bddeba7d3b8 Mon Sep 17 00:00:00 2001 From: George Farrell Date: Sun, 20 May 2018 23:36:10 +0100 Subject: [PATCH 02/34] Update Landing.java --- src/main/java/org/parabot/Landing.java | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/parabot/Landing.java b/src/main/java/org/parabot/Landing.java index 64bac34..bf79736 100644 --- a/src/main/java/org/parabot/Landing.java +++ b/src/main/java/org/parabot/Landing.java @@ -1,6 +1,7 @@ package org.parabot; import org.parabot.api.translations.TranslationHelper; +import org.parabot.core.Context; import org.parabot.core.Core; import org.parabot.core.Directories; import org.parabot.core.forum.AccountManager; @@ -9,6 +10,7 @@ import org.parabot.core.network.proxy.ProxySocket; import org.parabot.core.network.proxy.ProxyType; import org.parabot.core.ui.BotUI; import org.parabot.core.ui.ServerSelector; +import org.parabot.core.ui.utils.UILog; import javax.swing.*; import java.io.File; @@ -24,22 +26,15 @@ import java.io.IOException; public final class Landing { private static String username; private static String password; - private static double JAVA_VERSION = getVersion (); - - static double getVersion () { - String version = System.getProperty("java.version"); - int pos = version.indexOf('.'); - pos = version.indexOf('.', pos+1); - return Double.parseDouble (version.substring (0, pos)); - } public static void main(String... args) throws IOException { - if (JAVA_VERSION >= 9){ + if (Context.getJavaVersion() >= 9){ UILog.log("Parabot", "Please downgrade to Java 8 in order to use Parabot"); System.exit(0); } + parseArgs(args); Directories.validate(); From c754cd2ef06a8f111bcf32d905a54c3cff674e04 Mon Sep 17 00:00:00 2001 From: George Farrell Date: Sun, 20 May 2018 23:36:53 +0100 Subject: [PATCH 03/34] Update Context.java --- src/main/java/org/parabot/core/Context.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/org/parabot/core/Context.java b/src/main/java/org/parabot/core/Context.java index 943d051..981eb8f 100644 --- a/src/main/java/org/parabot/core/Context.java +++ b/src/main/java/org/parabot/core/Context.java @@ -72,6 +72,13 @@ public class Context { this.defaultErr = System.err; } + public static double getJavaVersion() { + String version = System.getProperty("java.version"); + int pos = version.indexOf('.'); + pos = version.indexOf('.', pos+1); + return Double.parseDouble (version.substring (0, pos)); + } + public static Context getInstance(ServerProvider serverProvider) { return instance == null ? instance = new Context(serverProvider) : instance; } From f54dc2ff738b423b89bd53cca03532d84a07a6f7 Mon Sep 17 00:00:00 2001 From: Alexander Bielen Date: Wed, 24 Oct 2018 19:38:58 +0200 Subject: [PATCH 04/34] Added conditional sleep with minimum timeout --- .../parabot/environment/api/utils/Time.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/main/java/org/parabot/environment/api/utils/Time.java b/src/main/java/org/parabot/environment/api/utils/Time.java index 5418f42..29b5ad7 100644 --- a/src/main/java/org/parabot/environment/api/utils/Time.java +++ b/src/main/java/org/parabot/environment/api/utils/Time.java @@ -53,6 +53,30 @@ public final class Time { return true; } + /** + * Sleeps until SleepCondition is valid, but with a minimum timeout. + * + * @param conn the condition. + * @param timeout the time in milliseconds before it stops sleeping. + * @param minimumTimeout the minimum time to sleep. + * + * @return whether it ran successfully without timing out. + */ + public static boolean sleep(SleepCondition conn, int timeout, int minimumTimeout) { + long start = System.currentTimeMillis(); + while (!conn.isValid()) { + if (start + timeout < System.currentTimeMillis()) { + return false; + } + Time.sleep(50); + } + long t; + if((t = System.currentTimeMillis() - start) < minimumTimeout) { + Time.sleep((int)(minimumTimeout - t)); + } + return true; + } + /** * Gets current time in milliseconds * From cbc5c3cc7d520807b1fca9f2fbd379bd7bf12f3f Mon Sep 17 00:00:00 2001 From: Alexander Bielen Date: Fri, 26 Oct 2018 18:27:04 +0200 Subject: [PATCH 05/34] Removed duplicate code by calling original sleep function --- src/main/java/org/parabot/environment/api/utils/Time.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/main/java/org/parabot/environment/api/utils/Time.java b/src/main/java/org/parabot/environment/api/utils/Time.java index 29b5ad7..86c1ee8 100644 --- a/src/main/java/org/parabot/environment/api/utils/Time.java +++ b/src/main/java/org/parabot/environment/api/utils/Time.java @@ -64,12 +64,7 @@ public final class Time { */ public static boolean sleep(SleepCondition conn, int timeout, int minimumTimeout) { long start = System.currentTimeMillis(); - while (!conn.isValid()) { - if (start + timeout < System.currentTimeMillis()) { - return false; - } - Time.sleep(50); - } + if(!sleep(conn, timeout)) return false; long t; if((t = System.currentTimeMillis() - start) < minimumTimeout) { Time.sleep((int)(minimumTimeout - t)); From 893f384d3381f99fe2fa8420d5bcca09a66f7851 Mon Sep 17 00:00:00 2001 From: Alexander Bielen Date: Fri, 26 Oct 2018 19:32:21 +0200 Subject: [PATCH 06/34] Added brackets to if statement --- src/main/java/org/parabot/environment/api/utils/Time.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/parabot/environment/api/utils/Time.java b/src/main/java/org/parabot/environment/api/utils/Time.java index 86c1ee8..ef8509c 100644 --- a/src/main/java/org/parabot/environment/api/utils/Time.java +++ b/src/main/java/org/parabot/environment/api/utils/Time.java @@ -64,7 +64,9 @@ public final class Time { */ public static boolean sleep(SleepCondition conn, int timeout, int minimumTimeout) { long start = System.currentTimeMillis(); - if(!sleep(conn, timeout)) return false; + if(!sleep(conn, timeout)) { + return false; + } long t; if((t = System.currentTimeMillis() - start) < minimumTimeout) { Time.sleep((int)(minimumTimeout - t)); From b427c4b629d7f12cef0ad054c5e8ca11d880ff06 Mon Sep 17 00:00:00 2001 From: Alexander Bielen Date: Fri, 26 Oct 2018 19:38:28 +0200 Subject: [PATCH 07/34] Added whitespaces for readability --- src/main/java/org/parabot/environment/api/utils/Time.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/org/parabot/environment/api/utils/Time.java b/src/main/java/org/parabot/environment/api/utils/Time.java index ef8509c..c790ed0 100644 --- a/src/main/java/org/parabot/environment/api/utils/Time.java +++ b/src/main/java/org/parabot/environment/api/utils/Time.java @@ -64,13 +64,16 @@ public final class Time { */ public static boolean sleep(SleepCondition conn, int timeout, int minimumTimeout) { long start = System.currentTimeMillis(); + if(!sleep(conn, timeout)) { return false; } + long t; if((t = System.currentTimeMillis() - start) < minimumTimeout) { Time.sleep((int)(minimumTimeout - t)); } + return true; } From f571b3ca880a6d67383bbb045bd45cde634a26b5 Mon Sep 17 00:00:00 2001 From: Alexander Bielen Date: Tue, 30 Oct 2018 19:07:16 +0100 Subject: [PATCH 08/34] Added class with functions that are frequently used for making paints --- .../environment/api/utils/PaintUtil.java | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/main/java/org/parabot/environment/api/utils/PaintUtil.java diff --git a/src/main/java/org/parabot/environment/api/utils/PaintUtil.java b/src/main/java/org/parabot/environment/api/utils/PaintUtil.java new file mode 100644 index 0000000..202f446 --- /dev/null +++ b/src/main/java/org/parabot/environment/api/utils/PaintUtil.java @@ -0,0 +1,51 @@ +package org.parabot.environment.api.utils; + +import java.text.DecimalFormat; + +/** + * Functions frequently used for displaying data on paints + * + * @author AlexanderBielen + */ +public class PaintUtil { + + /** + * Calculates how much given variable has gained per hour + * + * @param currentAmount total gained amount + * @param start time from which to start counting in milliseconds + * @return rate per hour + */ + public static long calculatePerHour(int currentAmount, long start) { + return calculatePerHour(currentAmount, 0, start); + } + + /** + * Calculates how much given variable has gained per hour, with variable start amount + * + * @param currentAmount total gained amount + * @param startAmount start amount + * @param start time from which to start counting in milliseconds + * @return rate per hour + */ + public static long calculatePerHour(int currentAmount, int startAmount, long start) { + return (int)(((double)(currentAmount - startAmount) * 3600000D) / (double)(System.currentTimeMillis() - start)); + } + + /** + * Formats a time difference from given timestamp till present into readable hh:mm:ss format + * + * @param start start time in milliseconds + * @return readable timestamp + */ + public static String formatRunTime(long start) { + DecimalFormat df = new DecimalFormat("00"); + long currentTime = System.currentTimeMillis() - start; + long hours = currentTime / (3600000); + currentTime -= hours * (3600000); + long minutes = currentTime / (60000); + currentTime -= minutes * (60000); + long seconds = currentTime / (1000); + return df.format(hours) + ":" + df.format(minutes) + ":" + df.format(seconds); + } +} \ No newline at end of file From 95ae255b077720a1d22eb32510f0d9fcb717de44 Mon Sep 17 00:00:00 2001 From: Alexander Bielen Date: Tue, 30 Oct 2018 19:32:08 +0100 Subject: [PATCH 09/34] Merged unique code into Timer --- .../environment/api/utils/PaintUtil.java | 51 ------------------- .../parabot/environment/api/utils/Timer.java | 13 ++++- 2 files changed, 12 insertions(+), 52 deletions(-) delete mode 100644 src/main/java/org/parabot/environment/api/utils/PaintUtil.java diff --git a/src/main/java/org/parabot/environment/api/utils/PaintUtil.java b/src/main/java/org/parabot/environment/api/utils/PaintUtil.java deleted file mode 100644 index 202f446..0000000 --- a/src/main/java/org/parabot/environment/api/utils/PaintUtil.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.parabot.environment.api.utils; - -import java.text.DecimalFormat; - -/** - * Functions frequently used for displaying data on paints - * - * @author AlexanderBielen - */ -public class PaintUtil { - - /** - * Calculates how much given variable has gained per hour - * - * @param currentAmount total gained amount - * @param start time from which to start counting in milliseconds - * @return rate per hour - */ - public static long calculatePerHour(int currentAmount, long start) { - return calculatePerHour(currentAmount, 0, start); - } - - /** - * Calculates how much given variable has gained per hour, with variable start amount - * - * @param currentAmount total gained amount - * @param startAmount start amount - * @param start time from which to start counting in milliseconds - * @return rate per hour - */ - public static long calculatePerHour(int currentAmount, int startAmount, long start) { - return (int)(((double)(currentAmount - startAmount) * 3600000D) / (double)(System.currentTimeMillis() - start)); - } - - /** - * Formats a time difference from given timestamp till present into readable hh:mm:ss format - * - * @param start start time in milliseconds - * @return readable timestamp - */ - public static String formatRunTime(long start) { - DecimalFormat df = new DecimalFormat("00"); - long currentTime = System.currentTimeMillis() - start; - long hours = currentTime / (3600000); - currentTime -= hours * (3600000); - long minutes = currentTime / (60000); - currentTime -= minutes * (60000); - long seconds = currentTime / (1000); - return df.format(hours) + ":" + df.format(minutes) + ":" + df.format(seconds); - } -} \ No newline at end of file diff --git a/src/main/java/org/parabot/environment/api/utils/Timer.java b/src/main/java/org/parabot/environment/api/utils/Timer.java index fa3c07e..5b44fdc 100644 --- a/src/main/java/org/parabot/environment/api/utils/Timer.java +++ b/src/main/java/org/parabot/environment/api/utils/Timer.java @@ -105,7 +105,18 @@ public class Timer { * @return hourly gains */ public int getPerHour(final int gained) { - return (int) ((gained) * 3600000D / (System.currentTimeMillis() - start)); + return getPerHour(gained, 0); + } + + /** + * Calculates hourly gains based on given variable, with variable start amount + * + * @param gained total gained amount + * @param startAmount start amount + * @return hourly gains + */ + public int getPerHour(final int gained, int startAmount) { + return (int) (((gained - startAmount) * 3600000D) / (System.currentTimeMillis() - start)); } /** From 76b46f1eff2be15bbba8f3d9a4165dc0810a0e89 Mon Sep 17 00:00:00 2001 From: Alexander Bielen Date: Tue, 30 Oct 2018 19:43:23 +0100 Subject: [PATCH 10/34] Corrected code to conform with the rest of the class --- src/main/java/org/parabot/environment/api/utils/Timer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/parabot/environment/api/utils/Timer.java b/src/main/java/org/parabot/environment/api/utils/Timer.java index 5b44fdc..5a457cf 100644 --- a/src/main/java/org/parabot/environment/api/utils/Timer.java +++ b/src/main/java/org/parabot/environment/api/utils/Timer.java @@ -115,7 +115,7 @@ public class Timer { * @param startAmount start amount * @return hourly gains */ - public int getPerHour(final int gained, int startAmount) { + public int getPerHour(final int gained, final int startAmount) { return (int) (((gained - startAmount) * 3600000D) / (System.currentTimeMillis() - start)); } From a284417b5a37c981f6c58b51848b8c9f11e6f348 Mon Sep 17 00:00:00 2001 From: Jak Date: Sun, 11 Nov 2018 09:26:16 +0000 Subject: [PATCH 11/34] Update Landing.java --- src/main/java/org/parabot/Landing.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/parabot/Landing.java b/src/main/java/org/parabot/Landing.java index 0507987..15b02e0 100644 --- a/src/main/java/org/parabot/Landing.java +++ b/src/main/java/org/parabot/Landing.java @@ -31,7 +31,7 @@ public final class Landing { public static void main(String... args) throws IOException { if (Context.getJavaVersion() >= 9){ - UILog.log("Parabot", "Please downgrade to Java 8 in order to use Parabot"); + UILog.log("Parabot", "Parabot doesn't support Java 9+ currently. Please downgrade to Java 8 to ensure Parabot is working correctly."); System.exit(0); } From 34ec727ca1b6b9e3f200ba4e7ca8e8ddc596fbc2 Mon Sep 17 00:00:00 2001 From: Alexander Bielen Date: Mon, 26 Nov 2018 19:10:36 +0100 Subject: [PATCH 12/34] [TASK]Added getResource() to catch error and fixed inverted statement --- .../org/parabot/core/asm/redirect/ClassRedirect.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/parabot/core/asm/redirect/ClassRedirect.java b/src/main/java/org/parabot/core/asm/redirect/ClassRedirect.java index 0925aeb..6ca9985 100644 --- a/src/main/java/org/parabot/core/asm/redirect/ClassRedirect.java +++ b/src/main/java/org/parabot/core/asm/redirect/ClassRedirect.java @@ -7,6 +7,7 @@ import org.parabot.environment.scripts.Script; import java.io.InputStream; import java.lang.annotation.Annotation; import java.lang.reflect.*; +import java.net.URL; import java.security.AccessController; import java.security.PrivilegedAction; import java.security.ProtectionDomain; @@ -58,6 +59,15 @@ public class ClassRedirect { return Class.forName(name); } + public static URL getResource(Class c, String path) { + if(validStack() || validRequest(c)) { + return c.getResource(path); + } + + System.err.println(c.getName() + "#getResource(" + path + ") Blocked."); + throw RedirectClassAdapter.createSecurityException(); + } + public static ClassLoader getClassLoader(Class c) { System.err.println(c.getName() + "#getClassLoader()" + " Blocked."); throw RedirectClassAdapter.createSecurityException(); @@ -213,6 +223,6 @@ public class ClassRedirect { private static boolean validRequest(Class c) { Core.verbose("Got request for class: " + c.getName()); - return !c.getName().toLowerCase().contains("parabot"); + return c.getName().toLowerCase().contains("parabot"); } } From 38f7961dc5415edcd54fa90200ff174000a0d568 Mon Sep 17 00:00:00 2001 From: Alexander Bielen Date: Tue, 27 Nov 2018 12:04:30 +0100 Subject: [PATCH 13/34] [FEATURE]Added catch for broken hooks and added dialog to display the error --- .../parabot/core/asm/wrappers/Callback.java | 15 ++++++++++++ .../org/parabot/core/asm/wrappers/Getter.java | 19 ++++++++++++++- .../parabot/core/asm/wrappers/Invoker.java | 8 +++++++ .../org/parabot/core/asm/wrappers/Setter.java | 19 ++++++++++++++- .../environment/servers/ServerProvider.java | 23 +++++++++++++++++-- 5 files changed, 80 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/parabot/core/asm/wrappers/Callback.java b/src/main/java/org/parabot/core/asm/wrappers/Callback.java index 5917f0f..5673d28 100644 --- a/src/main/java/org/parabot/core/asm/wrappers/Callback.java +++ b/src/main/java/org/parabot/core/asm/wrappers/Callback.java @@ -49,4 +49,19 @@ public class Callback implements Injectable { this.invokeMethod, this.desc, this.args, this.conditional); } + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + sb.append("Injectable type: Callback"); + + if(method != null) { + sb.append(", intercepts method: ").append(method.name); + } + + sb.append(", calls class: ").append(invokeClass) + .append(", calls method: ").append(invokeMethod); + + return sb.toString(); + } } diff --git a/src/main/java/org/parabot/core/asm/wrappers/Getter.java b/src/main/java/org/parabot/core/asm/wrappers/Getter.java index f11d12f..cb55aeb 100644 --- a/src/main/java/org/parabot/core/asm/wrappers/Getter.java +++ b/src/main/java/org/parabot/core/asm/wrappers/Getter.java @@ -38,7 +38,7 @@ public class Getter implements Injectable { this.fieldLocation = ASMUtils.getClass(fieldLocation); this.fieldNode = ASMUtils.getField(ASMUtils.getClass(fieldLocation), fieldNode, fieldDesc); this.methodName = methodName; - this.returnDesc = returnDesc == null ? this.fieldNode.desc : returnDesc; + this.returnDesc = returnDesc == null && this.fieldNode != null ? this.fieldNode.desc : returnDesc; this.staticMethod = staticMethod; this.multiplier = multiplier; Core.verbose(methodName + "[" + fieldLocation + "." + fieldNode + "]"); @@ -77,4 +77,21 @@ public class Getter implements Injectable { return new AddGetterAdapter(into, fieldLocation, fieldNode, methodName, returnDesc, staticMethod, multiplier); } + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("Injectable type: Getter"); + + if(fieldLocation.interfaces.size() > 0) { + sb.append(", accessor type: ").append(fieldLocation.interfaces.get(0).toString().replace('/', '.')); + } + + if(fieldNode != null) { + sb.append(", field: ").append(fieldNode.name); + } + + sb.append(", method name: ").append(methodName); + + return sb.toString(); + } } diff --git a/src/main/java/org/parabot/core/asm/wrappers/Invoker.java b/src/main/java/org/parabot/core/asm/wrappers/Invoker.java index 328e073..9349d61 100644 --- a/src/main/java/org/parabot/core/asm/wrappers/Invoker.java +++ b/src/main/java/org/parabot/core/asm/wrappers/Invoker.java @@ -79,4 +79,12 @@ public class Invoker implements Injectable { this.argsDesc, this.returnDesc, this.methodName, this.isInterface, this.instanceCast, this.argsCheckCastDesc); } + @Override + public String toString() { + return new StringBuilder() + .append("Injectable type: Invoker") + .append(", accessor: ").append(methodLocation.name) + .append(", method name: ").append(methodName) + .append(", invokes method: ").append(mName).toString(); + } } diff --git a/src/main/java/org/parabot/core/asm/wrappers/Setter.java b/src/main/java/org/parabot/core/asm/wrappers/Setter.java index 99b4074..5436cc6 100644 --- a/src/main/java/org/parabot/core/asm/wrappers/Setter.java +++ b/src/main/java/org/parabot/core/asm/wrappers/Setter.java @@ -25,7 +25,7 @@ public class Setter implements Injectable { this.into = ASMUtils.getClass(into); this.field = ASMUtils.getField(this.fieldLocation, fieldName, fieldDesc); this.name = methodName; - this.desc = (desc == null) ? this.field.desc : desc; + this.desc = (desc == null) && this.field != null ? this.field.desc : desc; this.methodStatic = methodStatic; } @@ -52,4 +52,21 @@ public class Setter implements Injectable { return new AddSetterAdapter(fieldLocation, into, field, name, desc, methodStatic); } + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("Injectable type: Setter"); + + if(fieldLocation.interfaces.size() > 0) { + sb.append(", accessor type: ").append(fieldLocation.interfaces.get(0).toString().replace('/', '.')); + } + + if(field != null) { + sb.append(", field: ").append(field.name); + } + + sb.append(", method name: ").append(name); + + return sb.toString(); + } } diff --git a/src/main/java/org/parabot/environment/servers/ServerProvider.java b/src/main/java/org/parabot/environment/servers/ServerProvider.java index 6765781..ac9bf38 100644 --- a/src/main/java/org/parabot/environment/servers/ServerProvider.java +++ b/src/main/java/org/parabot/environment/servers/ServerProvider.java @@ -5,6 +5,7 @@ import org.parabot.core.Context; import org.parabot.core.asm.hooks.HookFile; import org.parabot.core.asm.interfaces.Injectable; import org.parabot.core.parsers.hooks.HookParser; +import org.parabot.core.ui.utils.UILog; import org.parabot.environment.input.Keyboard; import org.parabot.environment.input.Mouse; import org.parabot.environment.scripts.Script; @@ -21,6 +22,7 @@ import java.net.URL; * @author Everel */ public abstract class ServerProvider implements Opcodes { + private boolean crashed = false; /** * Get the game/applet dimensions @@ -74,12 +76,29 @@ public abstract class ServerProvider implements Opcodes { HookParser parser = hookFile.getParser(); Injectable[] injectables = parser.getInjectables(); + if (injectables == null) { return; } - for (Injectable inj : injectables) { - inj.inject(); + + int index = 0; + + try { + for (Injectable inj : injectables) { + inj.inject(); + index++; + } + } catch (NullPointerException ex) { + if(!crashed) { + Injectable inj = injectables[index]; + + UILog.log("Outdated client", "This server currently has outdated hooks, please report it to a member of the Parabot staff/Dev Team.\r\n\r\n" + + "Broken hook:\r\n"+inj, JOptionPane.ERROR_MESSAGE); + } + crashed = true; + throw ex; } + Context.getInstance().setHookParser(parser); } From 2523cd19e374fa308ac738e2dff061a22ae2d1f6 Mon Sep 17 00:00:00 2001 From: Alexander Bielen Date: Tue, 27 Nov 2018 20:12:54 +0100 Subject: [PATCH 14/34] [CLEANUP] Switched to String.format and cleanup --- src/main/java/org/parabot/core/asm/wrappers/Getter.java | 2 +- src/main/java/org/parabot/core/asm/wrappers/Invoker.java | 6 +----- src/main/java/org/parabot/core/asm/wrappers/Setter.java | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/parabot/core/asm/wrappers/Getter.java b/src/main/java/org/parabot/core/asm/wrappers/Getter.java index cb55aeb..e7ef7a7 100644 --- a/src/main/java/org/parabot/core/asm/wrappers/Getter.java +++ b/src/main/java/org/parabot/core/asm/wrappers/Getter.java @@ -38,7 +38,7 @@ public class Getter implements Injectable { this.fieldLocation = ASMUtils.getClass(fieldLocation); this.fieldNode = ASMUtils.getField(ASMUtils.getClass(fieldLocation), fieldNode, fieldDesc); this.methodName = methodName; - this.returnDesc = returnDesc == null && this.fieldNode != null ? this.fieldNode.desc : returnDesc; + this.returnDesc = (returnDesc == null && this.fieldNode != null) ? this.fieldNode.desc : returnDesc; this.staticMethod = staticMethod; this.multiplier = multiplier; Core.verbose(methodName + "[" + fieldLocation + "." + fieldNode + "]"); diff --git a/src/main/java/org/parabot/core/asm/wrappers/Invoker.java b/src/main/java/org/parabot/core/asm/wrappers/Invoker.java index 9349d61..a8bc7d8 100644 --- a/src/main/java/org/parabot/core/asm/wrappers/Invoker.java +++ b/src/main/java/org/parabot/core/asm/wrappers/Invoker.java @@ -81,10 +81,6 @@ public class Invoker implements Injectable { @Override public String toString() { - return new StringBuilder() - .append("Injectable type: Invoker") - .append(", accessor: ").append(methodLocation.name) - .append(", method name: ").append(methodName) - .append(", invokes method: ").append(mName).toString(); + return String.format("Injectable type: Invoker, accessor: %s, method name: %s, invokes method: %s", methodLocation.name, methodName, mName); } } diff --git a/src/main/java/org/parabot/core/asm/wrappers/Setter.java b/src/main/java/org/parabot/core/asm/wrappers/Setter.java index 5436cc6..94ce25d 100644 --- a/src/main/java/org/parabot/core/asm/wrappers/Setter.java +++ b/src/main/java/org/parabot/core/asm/wrappers/Setter.java @@ -25,7 +25,7 @@ public class Setter implements Injectable { this.into = ASMUtils.getClass(into); this.field = ASMUtils.getField(this.fieldLocation, fieldName, fieldDesc); this.name = methodName; - this.desc = (desc == null) && this.field != null ? this.field.desc : desc; + this.desc = (desc == null && this.field != null) ? this.field.desc : desc; this.methodStatic = methodStatic; } From b072069b0570c1ee07c83750e072de04df947545 Mon Sep 17 00:00:00 2001 From: Alexander Bielen Date: Tue, 27 Nov 2018 22:51:03 +0100 Subject: [PATCH 15/34] [FEATURE] Added bit version check at startup --- src/main/java/org/parabot/Landing.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/org/parabot/Landing.java b/src/main/java/org/parabot/Landing.java index 15b02e0..398eda0 100644 --- a/src/main/java/org/parabot/Landing.java +++ b/src/main/java/org/parabot/Landing.java @@ -35,6 +35,11 @@ public final class Landing { System.exit(0); } + if(!System.getProperty("os.arch").contains("64")) { + UILog.log("Parabot", "You are not running a 64-bit version of java, this might cause the client to lag or crash unexpectedly.\r\n" + + "It's recommended to upgrade to a 64-bit version."); + } + parseArgs(args); Directories.validate(); From 31261f658d4525c59724eed7ae1b28979f56557c Mon Sep 17 00:00:00 2001 From: Alexander Bielen Date: Tue, 27 Nov 2018 23:33:28 +0100 Subject: [PATCH 16/34] [CLEANUP] Fixed typo --- src/main/java/org/parabot/Landing.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/parabot/Landing.java b/src/main/java/org/parabot/Landing.java index 398eda0..503e106 100644 --- a/src/main/java/org/parabot/Landing.java +++ b/src/main/java/org/parabot/Landing.java @@ -36,7 +36,7 @@ public final class Landing { } if(!System.getProperty("os.arch").contains("64")) { - UILog.log("Parabot", "You are not running a 64-bit version of java, this might cause the client to lag or crash unexpectedly.\r\n" + + UILog.log("Parabot", "You are not running a 64-bit version of Java, this might cause the client to lag or crash unexpectedly.\r\n" + "It's recommended to upgrade to a 64-bit version."); } From 0af111dc2d49428b112a296072e06a9713080145 Mon Sep 17 00:00:00 2001 From: Alexander Bielen Date: Thu, 29 Nov 2018 12:16:18 +0100 Subject: [PATCH 17/34] [FEATURE] Added local preference manager to store settings in a local json file --- .../environment/api/utils/FileUtil.java | 17 ++- .../api/utils/PBLocalPreferences.java | 113 ++++++++++++++++++ 2 files changed, 126 insertions(+), 4 deletions(-) create mode 100644 src/main/java/org/parabot/environment/api/utils/PBLocalPreferences.java diff --git a/src/main/java/org/parabot/environment/api/utils/FileUtil.java b/src/main/java/org/parabot/environment/api/utils/FileUtil.java index ce954d3..6f33897 100644 --- a/src/main/java/org/parabot/environment/api/utils/FileUtil.java +++ b/src/main/java/org/parabot/environment/api/utils/FileUtil.java @@ -1,10 +1,8 @@ package org.parabot.environment.api.utils; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; +import java.io.*; import java.nio.channels.FileChannel; +import java.nio.file.Files; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -88,4 +86,15 @@ public class FileUtil { } destination.close(); } + + public static String getFileContents(File file) throws IOException { + return new String(Files.readAllBytes(file.toPath())); + } + + public static void writeFileContents(File file, String contents) throws IOException { + BufferedWriter writer = new BufferedWriter(new FileWriter(file.getAbsolutePath())); + writer.write(contents); + + writer.close(); + } } diff --git a/src/main/java/org/parabot/environment/api/utils/PBLocalPreferences.java b/src/main/java/org/parabot/environment/api/utils/PBLocalPreferences.java new file mode 100644 index 0000000..66c84b7 --- /dev/null +++ b/src/main/java/org/parabot/environment/api/utils/PBLocalPreferences.java @@ -0,0 +1,113 @@ +package org.parabot.environment.api.utils; + +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.parabot.core.Directories; + +import java.io.File; +import java.util.HashMap; + +/** + * Manages preferences in a local json file in the Parabot settings folder + * + * @author AlexanderBielen + */ +public class PBLocalPreferences { + private static JSONParser parser = new JSONParser(); + private File settingsFile; + + + public PBLocalPreferences(String fileName) { + settingsFile = new File(Directories.getSettingsPath() + "/" + secureFileName(fileName)); + } + + /** + * Gets all settings inside the file + * + * @return JSONObject or null if anything went wrong + */ + public JSONObject getSettings() { + try { + String stringContents = FileUtil.getFileContents(settingsFile); + return (JSONObject) parser.parse(stringContents); + } catch(Exception ex) { + return null; + } + } + + /** + * Convert a HashMap to json and writes it to the file + * + * @param settings HashMap + * @param append If true, append to existing settings in file + */ + public void writeSettings(HashMap settings, boolean append) { + JSONObject existingSettings; + if(append && (existingSettings = getSettings()) != null) { + existingSettings.putAll(settings); + settings = existingSettings; + } + + try { + if (!settingsFile.exists()) { + settingsFile.createNewFile(); + } + FileUtil.writeFileContents(settingsFile, new JSONObject(settings).toJSONString()); + + } catch (Exception ignore) { + ignore.printStackTrace(); + } + + } + + /** + * Adds a setting, or overwrites it if it exists + * + * @param key + * @param value + */ + public void addSetting(String key, String value) { + HashMap pair = new HashMap<>(); + pair.put(key, value); + writeSettings(pair, true); + } + + /** + * Fetches a setting + * + * @param key + * @return + */ + public String getSetting(String key) { + if(getSettings() == null) { + return null; + } + + return getSettings().get(key).toString(); + } + + /** + * Adjusts an existing setting + * + * @param key + * @param value + */ + public void adjustSetting(String key, String value) { + addSetting(key, value); + } + + /** + * Removes a setting + * + * @param key + */ + public void removeSetting(String key) { + JSONObject json = getSettings(); + json.remove(key); + writeSettings(json, false); + } + + private static String secureFileName(String fileName) { + return fileName.replace("..", ""); + } +} From 47e61636c117e3effb63ea0e4006be7b7e79bec2 Mon Sep 17 00:00:00 2001 From: Alexander Bielen Date: Sun, 2 Dec 2018 18:24:54 +0100 Subject: [PATCH 18/34] [FEATURE] Storing provider version locally and clear cache when outdated --- .../parabot/core/desc/ServerProviderInfo.java | 28 +++++++++++++++++++ .../executers/PublicServerExecuter.java | 22 +++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/src/main/java/org/parabot/core/desc/ServerProviderInfo.java b/src/main/java/org/parabot/core/desc/ServerProviderInfo.java index a4e8c98..9e2682f 100644 --- a/src/main/java/org/parabot/core/desc/ServerProviderInfo.java +++ b/src/main/java/org/parabot/core/desc/ServerProviderInfo.java @@ -182,4 +182,32 @@ public class ServerProviderInfo { // Will never return null, unless the BDN URL is changed. It shouldn't be. return null; } + + + /** + * This is a temporary method until the bdn gets updated + * @param serverName + * @return + */ + public static String getProviderVersion(String serverName) { + try { + serverName = serverName.toLowerCase(); + String providerInfo = String.format("http://v3.bdn.parabot.org/api/bot/list/%s-provider?latest=true", serverName); + String response = WebUtil.getContents(providerInfo); + + if (response.length() > 0) { + JSONObject jsonObject = (JSONObject) WebUtil.getJsonParser().parse(response); + + if (jsonObject.get("version") != null) { + return jsonObject.get("version").toString(); + } + } else if (response.equals("")) { + return getProviderVersion("default"); + } + } catch(Exception ex) { + ex.printStackTrace(); + } + + return null; + } } diff --git a/src/main/java/org/parabot/environment/servers/executers/PublicServerExecuter.java b/src/main/java/org/parabot/environment/servers/executers/PublicServerExecuter.java index b98bd3c..3e76f16 100644 --- a/src/main/java/org/parabot/environment/servers/executers/PublicServerExecuter.java +++ b/src/main/java/org/parabot/environment/servers/executers/PublicServerExecuter.java @@ -11,6 +11,7 @@ import org.parabot.core.forum.AccountManager; import org.parabot.core.forum.AccountManagerAccess; import org.parabot.core.ui.components.VerboseLoader; import org.parabot.core.ui.utils.UILog; +import org.parabot.environment.api.utils.PBLocalPreferences; import org.parabot.environment.api.utils.WebUtil; import org.parabot.environment.servers.ServerProvider; import org.parabot.environment.servers.loader.ServerLoader; @@ -37,6 +38,9 @@ public class PublicServerExecuter extends ServerExecuter { }; private String serverName; + private PBLocalPreferences settings; + private final String CACHE_VERSION_KEY = "cachedProviderVersion"; + public PublicServerExecuter(final String serverName) { this.serverName = serverName; } @@ -53,6 +57,24 @@ public class PublicServerExecuter extends ServerExecuter { Core.verbose("Downloading: " + jarUrl + " ..."); + String providerVersion = ServerProviderInfo.getProviderVersion(serverName); + if(providerVersion == null) { + providerVersion = "error"; + } + + settings = new PBLocalPreferences(serverProviderInfo.getClientCRC32()+".json"); + if(settings.getSetting(CACHE_VERSION_KEY) != null) { + Core.verbose(String.format("Latest provider version: %s, local provider version: %s", settings.getSetting(CACHE_VERSION_KEY), providerVersion)); + if(!settings.getSetting(CACHE_VERSION_KEY).equals(providerVersion)) { + Core.verbose("Local provider outdated, clearing cache."); + Directories.clearCache(); + } + } else { + Core.verbose("No local provider version in settings, adding to settings file"); + } + + settings.addSetting(CACHE_VERSION_KEY, providerVersion); + if (destination.exists()) { Core.verbose("Found cached server provider [CRC32: " + serverProviderInfo.getCRC32() + "]"); } else { From 9caecc34789b25fd31007d6f5794c000a2ca5331 Mon Sep 17 00:00:00 2001 From: Alexander Bielen Date: Tue, 4 Dec 2018 21:11:05 +0100 Subject: [PATCH 19/34] [FEATURE] Added button to direct user to forums for reporting hook issues --- src/main/java/org/parabot/core/Configuration.java | 6 ++++-- src/main/java/org/parabot/core/ui/utils/UILog.java | 9 +++++++++ .../environment/servers/ServerProvider.java | 14 ++++++++++++-- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/parabot/core/Configuration.java b/src/main/java/org/parabot/core/Configuration.java index 6217c67..4a2ea44 100644 --- a/src/main/java/org/parabot/core/Configuration.java +++ b/src/main/java/org/parabot/core/Configuration.java @@ -18,10 +18,12 @@ public class Configuration extends org.parabot.api.Configuration { public static final String GET_BOT_VERSION = "http://bdn.parabot.org/api/v2/bot/version"; public static final String API_DOWNLOAD_BOT = "http://v3.bdn.parabot.org/api/bot/download/client"; public static final String DOWNLOAD_BOT = "http://bdn.parabot.org/versions/"; - public static final String REGISTRATION_PAGE = "https://www.parabot.org/community/register/"; public static final String GET_RANDOMS = "http://v3.bdn.parabot.org/api/bot/download/randoms"; public static final String DATA_API = "http://bdn.parabot.org/api/v2/data/"; public static final String ITEM_API = DATA_API + "items/"; - public static final Version BOT_VERSION = ProjectProperties.getProjectVersion(); + public static final Version BOT_VERSION = ProjectProperties.getProjectVersion(); + + public static final String COMMUNITY = "https://www.parabot.org/community/"; + public static final String REGISTRATION_PAGE = COMMUNITY + "register/"; } diff --git a/src/main/java/org/parabot/core/ui/utils/UILog.java b/src/main/java/org/parabot/core/ui/utils/UILog.java index ff00260..d1261f6 100644 --- a/src/main/java/org/parabot/core/ui/utils/UILog.java +++ b/src/main/java/org/parabot/core/ui/utils/UILog.java @@ -30,4 +30,13 @@ public class UILog { public static int alert(final String title, final String message, int optionType, int messageType) { return JOptionPane.showConfirmDialog(null, message, title, optionType, messageType); } + + public static int alert(final String title, final String message, Object[] options) { + return alert(title, message, options, JOptionPane.INFORMATION_MESSAGE); + } + + public static int alert(final String title, final String message, Object[] options, int messageType) { + return JOptionPane.showOptionDialog(null, message, title, + JOptionPane.YES_NO_CANCEL_OPTION, messageType, null, options, null); + } } diff --git a/src/main/java/org/parabot/environment/servers/ServerProvider.java b/src/main/java/org/parabot/environment/servers/ServerProvider.java index ac9bf38..f023cd6 100644 --- a/src/main/java/org/parabot/environment/servers/ServerProvider.java +++ b/src/main/java/org/parabot/environment/servers/ServerProvider.java @@ -1,6 +1,7 @@ package org.parabot.environment.servers; import org.objectweb.asm.Opcodes; +import org.parabot.core.Configuration; import org.parabot.core.Context; import org.parabot.core.asm.hooks.HookFile; import org.parabot.core.asm.interfaces.Injectable; @@ -14,6 +15,8 @@ import javax.swing.*; import java.applet.Applet; import java.applet.AppletStub; import java.awt.*; +import java.io.IOException; +import java.net.URI; import java.net.URL; /** @@ -92,8 +95,15 @@ public abstract class ServerProvider implements Opcodes { if(!crashed) { Injectable inj = injectables[index]; - UILog.log("Outdated client", "This server currently has outdated hooks, please report it to a member of the Parabot staff/Dev Team.\r\n\r\n" + - "Broken hook:\r\n"+inj, JOptionPane.ERROR_MESSAGE); + int resp = UILog.alert("Outdated client", "This server currently has outdated hooks, please report it to a member of the Parabot staff/Dev Team.\r\n\r\n" + + "Broken hook:\r\n"+inj, new Object[]{"Close", "Report here..."}, JOptionPane.ERROR_MESSAGE); + + if(resp == 1) { + URI uri = URI.create(Configuration.COMMUNITY + "forum/135-reports/"); + try { + Desktop.getDesktop().browse(uri); + } catch (IOException ignore) {} + } } crashed = true; throw ex; From b6a091cb074f5d63076eb6e52a680e147517946f Mon Sep 17 00:00:00 2001 From: Alexander Bielen Date: Tue, 4 Dec 2018 21:21:52 +0100 Subject: [PATCH 20/34] [TASK] Apply requested changes --- src/main/java/org/parabot/core/Configuration.java | 4 ++-- .../java/org/parabot/environment/servers/ServerProvider.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/parabot/core/Configuration.java b/src/main/java/org/parabot/core/Configuration.java index 4a2ea44..a8185a6 100644 --- a/src/main/java/org/parabot/core/Configuration.java +++ b/src/main/java/org/parabot/core/Configuration.java @@ -24,6 +24,6 @@ public class Configuration extends org.parabot.api.Configuration { public static final Version BOT_VERSION = ProjectProperties.getProjectVersion(); - public static final String COMMUNITY = "https://www.parabot.org/community/"; - public static final String REGISTRATION_PAGE = COMMUNITY + "register/"; + public static final String COMMUNITY_PAGE = "https://www.parabot.org/community/"; + public static final String REGISTRATION_PAGE = COMMUNITY_PAGE + "register/"; } diff --git a/src/main/java/org/parabot/environment/servers/ServerProvider.java b/src/main/java/org/parabot/environment/servers/ServerProvider.java index f023cd6..ae9b5ba 100644 --- a/src/main/java/org/parabot/environment/servers/ServerProvider.java +++ b/src/main/java/org/parabot/environment/servers/ServerProvider.java @@ -95,11 +95,11 @@ public abstract class ServerProvider implements Opcodes { if(!crashed) { Injectable inj = injectables[index]; - int resp = UILog.alert("Outdated client", "This server currently has outdated hooks, please report it to a member of the Parabot staff/Dev Team.\r\n\r\n" + + int resp = UILog.alert("Outdated client", "This server currently has outdated hooks, please report it to a member of the Parabot staff.\r\n\r\n" + "Broken hook:\r\n"+inj, new Object[]{"Close", "Report here..."}, JOptionPane.ERROR_MESSAGE); if(resp == 1) { - URI uri = URI.create(Configuration.COMMUNITY + "forum/135-reports/"); + URI uri = URI.create(Configuration.COMMUNITY_PAGE + "forum/135-reports/"); try { Desktop.getDesktop().browse(uri); } catch (IOException ignore) {} From aed8cd012bb3558c9fafbd6684b8972daeb17e20 Mon Sep 17 00:00:00 2001 From: Shadowrs Date: Sun, 9 Dec 2018 12:26:24 +0000 Subject: [PATCH 21/34] Replace JavaFX-Application based UIs with FX-embedded-in-swing --- pom.xml | 4 +- src/main/java/org/parabot/core/ui/BotUI.java | 3 +- .../notifications/NotificationUI.java | 54 ++++++++++++++----- .../org/parabot/environment/Environment.java | 2 +- .../resources/storage/ui/notifications.fxml | 3 +- 5 files changed, 46 insertions(+), 20 deletions(-) diff --git a/pom.xml b/pom.xml index 04ea80a..d95bb32 100755 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.parabot client - 2.7 + 2.7.1 jar @@ -73,7 +73,7 @@ org.parabot internal-api - 1.52.1 + 1.53.1 diff --git a/src/main/java/org/parabot/core/ui/BotUI.java b/src/main/java/org/parabot/core/ui/BotUI.java index 90b384f..4765394 100644 --- a/src/main/java/org/parabot/core/ui/BotUI.java +++ b/src/main/java/org/parabot/core/ui/BotUI.java @@ -1,6 +1,5 @@ package org.parabot.core.ui; -import javafx.application.Application; import org.parabot.core.Configuration; import org.parabot.core.Context; import org.parabot.core.Directories; @@ -248,7 +247,7 @@ public class BotUI extends JFrame implements ActionListener, ComponentListener, Directories.clearCache(); break; case "Notifications": - Application.launch(NotificationUI.class); + NotificationUI.create(); break; default: System.out.println("Invalid command: " + command); diff --git a/src/main/java/org/parabot/core/ui/components/notifications/NotificationUI.java b/src/main/java/org/parabot/core/ui/components/notifications/NotificationUI.java index bc55311..de7c59c 100644 --- a/src/main/java/org/parabot/core/ui/components/notifications/NotificationUI.java +++ b/src/main/java/org/parabot/core/ui/components/notifications/NotificationUI.java @@ -1,20 +1,48 @@ package org.parabot.core.ui.components.notifications; -import javafx.application.Application; -import javafx.fxml.FXMLLoader; -import javafx.scene.Scene; -import javafx.scene.layout.BorderPane; -import javafx.stage.Stage; -import org.parabot.core.Configuration; +import org.parabot.api.output.Verboser; +import org.parabot.api.ui.JavaFxUtil; -public class NotificationUI extends Application { +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +/** + * A JavaFX Panel embedded into a Swing JFrame - handles notification settings + * + * @author Shadowrs + */ +public class NotificationUI extends JavaFxUtil { + + final NotificationUI n; + + private NotificationUI() { + super("/storage/ui/notifications.fxml", NotificationUIController.class); + this.n = this; + } + + public static void create() { + new NotificationUI(); + } @Override - public void start(Stage stage) throws Exception { - //noinspection RedundantCast - BorderPane root = (BorderPane) FXMLLoader.load(this.getClass().getResource("/storage/ui/notifications.fxml")); - stage.setTitle(Configuration.BOT_TITLE); - stage.setScene(new Scene(root)); - stage.show(); + public WindowAdapter getWindowAdapter() { + return new WindowAdapter() { + @Override + public void windowClosed(WindowEvent e) { + Verboser.verbose("NotificationUI closed " + e); + } + + @Override + public void windowClosing(WindowEvent e) { + // Anything here. JFrame hides on exit. + Verboser.verbose("NotificationUI closing " + e); + n.getFrame().dispose(); + } + }; + } + + @Override + protected void onLaunched() { + n.getFrame().setTitle("Notifications"); } } \ No newline at end of file diff --git a/src/main/java/org/parabot/environment/Environment.java b/src/main/java/org/parabot/environment/Environment.java index 88cf093..0e05b0d 100644 --- a/src/main/java/org/parabot/environment/Environment.java +++ b/src/main/java/org/parabot/environment/Environment.java @@ -33,7 +33,7 @@ public class Environment extends org.parabot.api.io.libraries.Environment { loadLibrary(lib, true); } - Core.verbose("Loading server: " + desc.toString() + "..."); + Core.verbose("[Environment] Loading server: " + desc.toString() + "..."); ServerParser.SERVER_CACHE.get(desc).run(); } diff --git a/src/main/resources/storage/ui/notifications.fxml b/src/main/resources/storage/ui/notifications.fxml index 1e6ac7b..6577abd 100644 --- a/src/main/resources/storage/ui/notifications.fxml +++ b/src/main/resources/storage/ui/notifications.fxml @@ -4,8 +4,7 @@ + prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1">