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 d62a77f102..e2b4c897c1 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLite.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLite.java @@ -84,7 +84,7 @@ public class RuneLite public static final File PROFILES_DIR = new File(RUNELITE_DIR, "profiles"); public static final File PLUGIN_DIR = new File(RUNELITE_DIR, "plugins"); public static final File SCREENSHOT_DIR = new File(RUNELITE_DIR, "screenshots"); - private static final RuneLiteSplashScreen splashScreen = new RuneLiteSplashScreen(); + public static RuneLiteSplashScreen splashScreen = new RuneLiteSplashScreen(); @Getter @@ -233,7 +233,8 @@ public class RuneLite } // The submessage is shown in case the connection is slow - splashScreen.setMessage("Loading client", "And checking for updates..."); + splashScreen.setMessage("Starting RuneLite Injector"); + splashScreen.setSubMessage( " "); final long start = System.currentTimeMillis(); @@ -242,7 +243,7 @@ public class RuneLite developerMode)); injector.getInstance(RuneLite.class).start(); - + splashScreen.setProgress(1, 4); final long end = System.currentTimeMillis(); final RuntimeMXBean rb = ManagementFactory.getRuntimeMXBean(); final long uptime = rb.getUptime(); @@ -263,6 +264,7 @@ public class RuneLite // Load user configuration splashScreen.setMessage("Loading configuration"); configManager.load(); + splashScreen.setProgress(2, 4); // Load the session, including saved configuration sessionManager.loadSession(); @@ -275,8 +277,10 @@ public class RuneLite // Load the plugins, but does not start them yet. // This will initialize configuration - splashScreen.setMessage("Loading plugins and patches", "Starting session..."); + splashScreen.setMessage("Loading plugins and patches"); + splashScreen.setSubMessage("Starting session..."); pluginManager.loadCorePlugins(); + splashScreen.setProgress(3, 4); // Plugins have provided their config, so set default config // to main settings @@ -287,6 +291,7 @@ public class RuneLite // Load the session, including saved configuration splashScreen.setMessage("Loading interface"); + splashScreen.setProgress(4, 4); // Initialize UI clientUI.open(this); 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 30c143a33e..97968032ac 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 @@ -92,6 +92,7 @@ public class ClientLoader private ClientUpdateCheckMode updateCheckMode; private JarOutputStream target; private static String[] preotectedStuffs; + private static int stepCount; @Inject private ClientLoader( @@ -240,6 +241,7 @@ public class ClientLoader hooks.actorClass.equals("") || hooks.playerClass.equals("")) { System.out.println("[RuneLitePlus] Bad hooks, re-scraping."); + stepCount = getStepCount(ByteCodeUtils.injectedClientFile.getPath()); ByteCodePatcher.clientInstance = initHookScrape(ByteCodeUtils.injectedClientFile.getPath()); ByteCodePatcher.findHooks(injectedClientFile.getPath()); } else { @@ -250,6 +252,7 @@ public class ClientLoader } else { System.out.println("[RuneLitePlus] Hooks file not found, scraping hooks."); + stepCount = getStepCount(ByteCodeUtils.injectedClientFile.getPath()); ByteCodePatcher.clientInstance = initHookScrape(ByteCodeUtils.injectedClientFile.getPath()); ByteCodePatcher.hooks.protectedStuff = preotectedStuffs; ByteCodePatcher.findHooks(injectedClientFile.getPath()); @@ -340,7 +343,35 @@ public class ClientLoader return certificates.toArray(new Certificate[certificates.size()]); } + public static int getStepCount(String jarFile) { + int stepCount = 0; + JarClassLoader jcl = new JarClassLoader(); + try { + ClassPool classPool = new ClassPool(true); + classPool.appendClassPath(RuneLite.RUNELITE_DIR+"/injectedClient-"+ RuneLiteAPI.getVersion() +"-.jar"); + } catch (NotFoundException e) { + e.printStackTrace(); + } + + try { + jcl.add(new FileInputStream(jarFile)); + try (JarInputStream in = new JarInputStream(new BufferedInputStream(new FileInputStream(jarFile)))) { + JarEntry entry; + while ((entry = in.getNextJarEntry()) != null) { + if (entry.getName().endsWith(".class")) { + stepCount++; + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return stepCount; + } + public static String initHookScrape(String jarFile) { + int currentStep = 0; + RuneLite.splashScreen.setMessage("Analyzing injected client"); List protectedStuff = new ArrayList(); String clientInstance = ""; JarClassLoader jcl = new JarClassLoader(); @@ -366,6 +397,9 @@ public class ClientLoader ); try { Class classToLoad = Class.forName(entry.getName().replace(".class", ""), false, child); + RuneLite.splashScreen.setSubMessage(entry.getName()); + currentStep++; + RuneLite.splashScreen.setProgress(currentStep, stepCount); JarClassLoader jcl2 = new JarClassLoader(); try { jcl2.add(new FileInputStream(ByteCodeUtils.injectedClientFile)); @@ -386,6 +420,8 @@ public class ClientLoader } } for (Method m : methods) { + RuneLite.splashScreen.setSubMessage("Checked "+m.getName()); + RuneLite.splashScreen.setProgress(currentStep, stepCount); if (m.getName().contains("$")) { protectedStuff.add(classToLoad.getName()+"."+m.getName()); } @@ -396,7 +432,7 @@ public class ClientLoader } catch (Exception e) { e.printStackTrace(); } - + RuneLite.splashScreen.setProgress(2, 5); } catch (Exception e) { e.printStackTrace(); System.out.println("Class not found: "+entry.getName()); diff --git a/runelite-client/src/main/java/net/runelite/client/rs/bytecode/ByteCodePatcher.java b/runelite-client/src/main/java/net/runelite/client/rs/bytecode/ByteCodePatcher.java index 8534123b60..c0be6da6eb 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/bytecode/ByteCodePatcher.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/bytecode/ByteCodePatcher.java @@ -15,6 +15,7 @@ import net.runelite.client.rs.bytecode.transformers.ProjectileTransform; import net.runelite.http.api.RuneLiteAPI; import org.xeustechnologies.jcl.JarClassLoader; +import javax.swing.*; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; @@ -37,27 +38,42 @@ public class ByteCodePatcher { public static JarClassLoader jcl = new JarClassLoader(); public static ClassPool classPool = null; public static ClassLoader cl = ClassLoader.getSystemClassLoader(); + public static int classCount = 0; public static void applyHooks(File jf, Hooks hooks) { + RuneLite.splashScreen.setProgress(0, 5); + RuneLite.splashScreen.setMessage("Applying cached bytecode patches..."); try { URLClassLoader child = new URLClassLoader( new URL[] {jf.toURI().toURL()}, cl ); try { + RuneLite.splashScreen.setSubMessage("Transforming Actor"); Class actorClass = Class.forName(hooks.actorClass, false, child); transformActor(actorClass); + RuneLite.splashScreen.setProgress(1, 5); + + RuneLite.splashScreen.setSubMessage("Transforming Projectile"); Class projectileClass = Class.forName(hooks.projectileClass, false, child); transformProjectile(projectileClass); + RuneLite.splashScreen.setProgress(2, 5); + + RuneLite.splashScreen.setSubMessage("Transforming Player"); Class playerClass = Class.forName(hooks.playerClass, false, child); transformPlayer(playerClass); + RuneLite.splashScreen.setProgress(3, 5); + + RuneLite.splashScreen.setSubMessage("Transforming Client"); Class clientClass = Class.forName("client", false, child); transformClient(clientClass); + RuneLite.splashScreen.setProgress(4, 5); //Odds and ends + RuneLite.splashScreen.setSubMessage("Transforming Error method"); ErrorTransform et = new ErrorTransform(); et.modify(null); - + RuneLite.splashScreen.setProgress(5, 5); ByteCodeUtils.updateHijackedJar(); } catch (Exception e) { e.printStackTrace(); @@ -69,6 +85,7 @@ public class ByteCodePatcher { } public static void findHooks(String jf) { + RuneLite.splashScreen.setMessage("Intercepting Classes"); try { classPool = new ClassPool(true); classPool.appendClassPath(RuneLite.RUNELITE_DIR+"/injectedClient-"+ RuneLiteAPI.getVersion() +"-.jar"); @@ -82,7 +99,20 @@ public class ByteCodePatcher { JarEntry entry; while ((entry = in.getNextJarEntry()) != null) { if (entry.getName().endsWith(".class")) { + classCount++; + } + } + } + int i = 0; + jcl.add(new FileInputStream(jf)); + try (JarInputStream in = new JarInputStream(new BufferedInputStream(new FileInputStream(jf)))) { + JarEntry entry; + while ((entry = in.getNextJarEntry()) != null) { + if (entry.getName().endsWith(".class")) { + RuneLite.splashScreen.setProgress(i, classCount); + RuneLite.splashScreen.setSubMessage("Checking "+entry.getName()); checkClasses(new File(jf), entry); + i++; } } } @@ -194,5 +224,4 @@ public class ByteCodePatcher { bt.modify(clazz); } - } diff --git a/runelite-client/src/main/java/net/runelite/client/ui/RuneLiteSplashScreen.java b/runelite-client/src/main/java/net/runelite/client/ui/RuneLiteSplashScreen.java index 08bd88afba..4ff3e51196 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/RuneLiteSplashScreen.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/RuneLiteSplashScreen.java @@ -51,10 +51,10 @@ public class RuneLiteSplashScreen { private RuneLiteProperties runeLiteProperties = new RuneLiteProperties(); - private JFrame frame; - private JLabel messageLabel; - private JLabel subMessageLabel; - private JProgressBar progressBar; + public JFrame frame; + public JLabel messageLabel; + public JLabel subMessageLabel; + public JProgressBar progressBar; private int currentStep; @@ -191,21 +191,7 @@ public class RuneLiteSplashScreen }); } - /** - * Set a loading message. The subMessage will also be removed. - * @param message The main message. It will automatically append an ellipsis. - */ public void setMessage(final String message) - { - setMessage(message, " "); - } - - /** - * Set a loading message. - * @param message The main message. It will automatically append an ellipsis. - * @param subMessage A separate alternate title. - */ - public void setMessage(final String message, final String subMessage) { SwingUtilities.invokeLater(() -> { @@ -213,10 +199,32 @@ public class RuneLiteSplashScreen { return; } + messageLabel.setText(message); + }); + } - messageLabel.setText(message + "..."); + public void setSubMessage(final String subMessage) + { + SwingUtilities.invokeLater(() -> + { + if (notActive()) + { + return; + } subMessageLabel.setText(subMessage); - progressBar.setValue(++currentStep); + }); + } + + public void setProgress(int currentProgress, int progressGoal) + { + SwingUtilities.invokeLater(() -> + { + if (notActive()) + { + return; + } + progressBar.setMaximum(progressGoal); + progressBar.setValue(currentProgress); }); } }