From b2ec04227bb25214ee8221eb64bf2b23d75f2a5d Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 30 Jan 2020 19:58:09 -0500 Subject: [PATCH 1/5] Add cli functionality to set the world loaded by the client on startup: --world | id must be > 300 --- .../java/net/runelite/client/RuneLite.java | 12 +++++-- .../net/runelite/client/rs/ClientLoader.java | 18 +++++++++-- .../net/runelite/client/rs/WorldSupplier.java | 31 ++++++++++++++++++- 3 files changed, 56 insertions(+), 5 deletions(-) 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 14f93d3cc3..d5c605bc0e 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLite.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLite.java @@ -192,7 +192,9 @@ public class RuneLite final ArgumentAcceptingOptionSpec proxyInfo = parser .accepts("proxy") .withRequiredArg().ofType(String.class); - + final ArgumentAcceptingOptionSpec worldInfo = parser + .accepts("world") + .withRequiredArg().ofType(Integer.class); final ArgumentAcceptingOptionSpec updateMode = parser .accepts("rs", "Select client type") .withRequiredArg() @@ -252,10 +254,16 @@ public class RuneLite } } + Integer world = null; + if(options.has("world")) + { + world = options.valueOf(worldInfo); + } + SentryClient client = Sentry.init("https://fa31d674e44247fa93966c69a903770f@sentry.io/1811856"); client.setRelease(RuneLiteProperties.getPlusVersion()); - final ClientLoader clientLoader = new ClientLoader(options.valueOf(updateMode)); + final ClientLoader clientLoader = new ClientLoader(options.valueOf(updateMode), world); Completable.fromAction(clientLoader::get) .subscribeOn(Schedulers.computation()) .subscribe(); 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 266a0cce8e..dfd514005d 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 @@ -49,14 +49,16 @@ public class ClientLoader implements Supplier private static final int NUM_ATTEMPTS = 10; private final ClientUpdateCheckMode updateCheckMode; + private final Integer worldNumber; private Object client = null; private WorldSupplier worldSupplier = new WorldSupplier(); private RSConfig config; - public ClientLoader(ClientUpdateCheckMode updateCheckMode) + public ClientLoader(ClientUpdateCheckMode updateCheckMode, Integer worldNumber) { this.updateCheckMode = updateCheckMode; + this.worldNumber = worldNumber; } @Override @@ -126,6 +128,18 @@ public class ClientLoader implements Supplier throw new IOException("Invalid or missing jav_config"); } + if(worldNumber != null) + { + final World world = worldSupplier.get(w -> w.getId() == worldNumber); + if(world == null) + { + log.warn("The provided world: {} could not be found. Reverting to random P2P world.", worldNumber); + return; + } + log.info("Set world to: {}", worldNumber); + config.getAppletProperties().replace("12", worldNumber.toString()); + } + return; } catch (IOException e) @@ -222,4 +236,4 @@ public class ClientLoader implements Supplier rs.setStub(new RSAppletStub(config)); return rs; } -} \ No newline at end of file +} diff --git a/runelite-client/src/main/java/net/runelite/client/rs/WorldSupplier.java b/runelite-client/src/main/java/net/runelite/client/rs/WorldSupplier.java index 956ce1fbda..d32f44087a 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/WorldSupplier.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/WorldSupplier.java @@ -31,8 +31,11 @@ import java.util.EnumSet; import java.util.List; import java.util.Queue; import java.util.Random; +import java.util.function.Function; +import java.util.function.Predicate; import java.util.function.Supplier; import java.util.stream.Collectors; +import javax.annotation.Nullable; import lombok.extern.slf4j.Slf4j; import net.runelite.http.api.RuneLiteAPI; import net.runelite.http.api.worlds.World; @@ -83,4 +86,30 @@ class WorldSupplier implements Supplier return worlds.poll(); } -} \ No newline at end of file + + @Nullable + public World get(Predicate filter) + { + try + { + List filteredWorlds = new WorldClient(RuneLiteAPI.CLIENT) + .lookupWorlds() + .getWorlds() + .stream() + .filter(filter) + .collect(Collectors.toList()); + + Collections.shuffle(filteredWorlds, random); + + if(filteredWorlds.size() > 0) + { + return filteredWorlds.get(0); + } + } + catch (IOException e) + { + log.warn("Unable to retrieve world list", e); + } + return null; + } +} From 52c44c4ace2b71ba8a71c8d30433bf143512e467 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 30 Jan 2020 20:09:44 -0500 Subject: [PATCH 2/5] Add cli functionality to set the world loaded by the client on startup: --world | id must be > 300 --- .../src/main/java/net/runelite/client/rs/WorldSupplier.java | 1 - 1 file changed, 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/rs/WorldSupplier.java b/runelite-client/src/main/java/net/runelite/client/rs/WorldSupplier.java index d32f44087a..e60cd0baaa 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/WorldSupplier.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/WorldSupplier.java @@ -31,7 +31,6 @@ import java.util.EnumSet; import java.util.List; import java.util.Queue; import java.util.Random; -import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; import java.util.stream.Collectors; From 8d9e9e6f164e63321c6ee8a2643dfa6476985f5c Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 30 Jan 2020 20:56:31 -0500 Subject: [PATCH 3/5] Checkstyle fixes --- .../java/net/runelite/client/RuneLite.java | 2 +- .../net/runelite/client/rs/ClientLoader.java | 122 +++++++++--------- .../net/runelite/client/rs/WorldSupplier.java | 2 +- 3 files changed, 63 insertions(+), 63 deletions(-) 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 d5c605bc0e..080348ce07 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLite.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLite.java @@ -255,7 +255,7 @@ public class RuneLite } Integer world = null; - if(options.has("world")) + if (options.has("world")) { world = options.valueOf(worldInfo); } 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 dfd514005d..31911fdaba 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 @@ -61,6 +61,65 @@ public class ClientLoader implements Supplier this.worldNumber = worldNumber; } + private static Applet loadRLPlus(final RSConfig config) + throws ClassNotFoundException, InstantiationException, IllegalAccessException + { + RuneLiteSplashScreen.stage(.465, "Starting Open Old School RuneScape"); + + ClassLoader rsClassLoader = new ClassLoader(ClientLoader.class.getClassLoader()) + { + @Override + protected Class findClass(String name) throws ClassNotFoundException + { + String path = name.replace('.', '/').concat(".class"); + InputStream inputStream = ClientLoader.class.getResourceAsStream(path); + if (inputStream == null) + { + throw new ClassNotFoundException(name + " " + path); + } + byte[] data; + try + { + data = ByteStreams.toByteArray(inputStream); + } + catch (IOException e) + { + e.printStackTrace(); + RuneLiteSplashScreen.setError("Failed to load!", "Failed to load class: " + name + " " + path); + throw new RuntimeException("Failed to load class: " + name + " " + path); + } + return defineClass(name, data, 0, data.length); + } + }; + Class clientClass = rsClassLoader.loadClass("client"); + return loadFromClass(config, clientClass); + } + + private static Applet loadVanilla(final RSConfig config) + throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException + { + RuneLiteSplashScreen.stage(.465, "Starting Vanilla Old School RuneScape"); + + final String codebase = config.getCodeBase(); + final String initialJar = config.getInitialJar(); + final String initialClass = config.getInitialClass(); + final URL url = new URL(codebase + initialJar); + + // Must set parent classloader to null, or it will pull from + // this class's classloader first + final URLClassLoader classloader = new URLClassLoader(new URL[]{url}, null); + final Class clientClass = classloader.loadClass(initialClass); + return loadFromClass(config, clientClass); + } + + private static Applet loadFromClass(final RSConfig config, final Class clientClass) + throws IllegalAccessException, InstantiationException + { + final Applet rs = (Applet) clientClass.newInstance(); + rs.setStub(new RSAppletStub(config)); + return rs; + } + @Override public synchronized Applet get() { @@ -128,10 +187,10 @@ public class ClientLoader implements Supplier throw new IOException("Invalid or missing jav_config"); } - if(worldNumber != null) + if (worldNumber != null) { final World world = worldSupplier.get(w -> w.getId() == worldNumber); - if(world == null) + if (world == null) { log.warn("The provided world: {} could not be found. Reverting to random P2P world.", worldNumber); return; @@ -177,63 +236,4 @@ public class ClientLoader implements Supplier throw err; // use error from Jagex's servers } } - - private static Applet loadRLPlus(final RSConfig config) - throws ClassNotFoundException, InstantiationException, IllegalAccessException - { - RuneLiteSplashScreen.stage(.465, "Starting Open Old School RuneScape"); - - ClassLoader rsClassLoader = new ClassLoader(ClientLoader.class.getClassLoader()) - { - @Override - protected Class findClass(String name) throws ClassNotFoundException - { - String path = name.replace('.', '/').concat(".class"); - InputStream inputStream = ClientLoader.class.getResourceAsStream(path); - if (inputStream == null) - { - throw new ClassNotFoundException(name + " " + path); - } - byte[] data; - try - { - data = ByteStreams.toByteArray(inputStream); - } - catch (IOException e) - { - e.printStackTrace(); - RuneLiteSplashScreen.setError("Failed to load!", "Failed to load class: " + name + " " + path); - throw new RuntimeException("Failed to load class: " + name + " " + path); - } - return defineClass(name, data, 0, data.length); - } - }; - Class clientClass = rsClassLoader.loadClass("client"); - return loadFromClass(config, clientClass); - } - - private static Applet loadVanilla(final RSConfig config) - throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException - { - RuneLiteSplashScreen.stage(.465, "Starting Vanilla Old School RuneScape"); - - final String codebase = config.getCodeBase(); - final String initialJar = config.getInitialJar(); - final String initialClass = config.getInitialClass(); - final URL url = new URL(codebase + initialJar); - - // Must set parent classloader to null, or it will pull from - // this class's classloader first - final URLClassLoader classloader = new URLClassLoader(new URL[]{url}, null); - final Class clientClass = classloader.loadClass(initialClass); - return loadFromClass(config, clientClass); - } - - private static Applet loadFromClass(final RSConfig config, final Class clientClass) - throws IllegalAccessException, InstantiationException - { - final Applet rs = (Applet) clientClass.newInstance(); - rs.setStub(new RSAppletStub(config)); - return rs; - } } diff --git a/runelite-client/src/main/java/net/runelite/client/rs/WorldSupplier.java b/runelite-client/src/main/java/net/runelite/client/rs/WorldSupplier.java index e60cd0baaa..3254595ca7 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/WorldSupplier.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/WorldSupplier.java @@ -100,7 +100,7 @@ class WorldSupplier implements Supplier Collections.shuffle(filteredWorlds, random); - if(filteredWorlds.size() > 0) + if (filteredWorlds.size() > 0) { return filteredWorlds.get(0); } From 539312ef1d9d3801775da70bf9efabd11f67c6ab Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 30 Jan 2020 23:46:56 -0500 Subject: [PATCH 4/5] Add default world plugin override when CLI world argument is present --- .../java/net/runelite/client/RuneLite.java | 55 ++++++++++++++++++- .../defaultworld/DefaultWorldPlugin.java | 5 ++ .../net/runelite/client/rs/ClientLoader.java | 16 +----- .../net/runelite/client/rs/WorldSupplier.java | 26 --------- 4 files changed, 58 insertions(+), 44 deletions(-) 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 080348ce07..488c2520ce 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLite.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLite.java @@ -40,6 +40,7 @@ import java.lang.management.RuntimeMXBean; import java.net.Authenticator; import java.net.PasswordAuthentication; import java.util.Locale; +import java.util.Optional; import javax.annotation.Nullable; import javax.inject.Provider; import javax.inject.Singleton; @@ -63,6 +64,7 @@ import net.runelite.client.game.ClanManager; import net.runelite.client.game.ItemManager; import net.runelite.client.game.LootManager; import net.runelite.client.game.PlayerManager; +import net.runelite.client.game.WorldService; import net.runelite.client.game.XpDropManager; import net.runelite.client.game.chatbox.ChatboxPanelManager; import net.runelite.client.graphics.ModelOutlineRenderer; @@ -81,7 +83,10 @@ import net.runelite.client.ui.overlay.arrow.ArrowWorldOverlay; import net.runelite.client.ui.overlay.infobox.InfoBoxOverlay; import net.runelite.client.ui.overlay.tooltip.TooltipOverlay; import net.runelite.client.ui.overlay.worldmap.WorldMapOverlay; +import net.runelite.client.util.WorldUtil; import net.runelite.client.ws.PartyService; +import net.runelite.http.api.worlds.World; +import net.runelite.http.api.worlds.WorldResult; import org.slf4j.LoggerFactory; @Singleton @@ -103,6 +108,8 @@ public class RuneLite @Inject public DiscordService discordService; @Inject + private WorldService worldService; + @Inject private PluginManager pluginManager; @Inject private ConfigManager configManager; @@ -254,16 +261,16 @@ public class RuneLite } } - Integer world = null; if (options.has("world")) { - world = options.valueOf(worldInfo); + int world = options.valueOf(worldInfo); + System.setProperty("cli.world", String.valueOf(world)); } SentryClient client = Sentry.init("https://fa31d674e44247fa93966c69a903770f@sentry.io/1811856"); client.setRelease(RuneLiteProperties.getPlusVersion()); - final ClientLoader clientLoader = new ClientLoader(options.valueOf(updateMode), world); + final ClientLoader clientLoader = new ClientLoader(options.valueOf(updateMode)); Completable.fromAction(clientLoader::get) .subscribeOn(Schedulers.computation()) .subscribe(); @@ -364,6 +371,10 @@ public class RuneLite RuneLiteSplashScreen.stage(.80, "Initialize UI"); clientUI.init(this); + //Set the world if specified via CLI args - will not work until clientUI.init is called + Optional worldArg = Optional.ofNullable(System.getProperty("cli.world")).map(Integer::parseInt); + worldArg.ifPresent(this::setWorld); + // Initialize Discord service discordService.init(); @@ -412,6 +423,44 @@ public class RuneLite clientUI.show(); } + private void setWorld(int cliWorld) + { + int correctedWorld = cliWorld < 300 ? cliWorld + 300 : cliWorld; + + if (correctedWorld <= 300 || client.getWorld() == correctedWorld) + { + return; + } + + final WorldResult worldResult = worldService.getWorlds(); + + if (worldResult == null) + { + log.warn("Failed to lookup worlds."); + return; + } + + final World world = worldResult.findWorld(correctedWorld); + + if (world != null) + { + final net.runelite.api.World rsWorld = client.createWorld(); + rsWorld.setActivity(world.getActivity()); + rsWorld.setAddress(world.getAddress()); + rsWorld.setId(world.getId()); + rsWorld.setPlayerCount(world.getPlayers()); + rsWorld.setLocation(world.getLocation()); + rsWorld.setTypes(WorldUtil.toWorldTypes(world.getTypes())); + + client.changeWorld(rsWorld); + log.debug("Applied new world {}", correctedWorld); + } + else + { + log.warn("World {} not found.", correctedWorld); + } + } + public void shutdown() { configManager.sendConfig(); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/defaultworld/DefaultWorldPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/defaultworld/DefaultWorldPlugin.java index 0f98862c3a..d069019388 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/defaultworld/DefaultWorldPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/defaultworld/DefaultWorldPlugin.java @@ -157,6 +157,11 @@ public class DefaultWorldPlugin extends Plugin log.debug("Stored old world {}", worldCache); } + if (System.getProperty("cli.world") != null) + { + return; + } + final int newWorld = !config.useLastWorld() ? config.getWorld() : config.lastWorld(); changeWorld(newWorld); } 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 31911fdaba..d19329652a 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 @@ -49,16 +49,14 @@ public class ClientLoader implements Supplier private static final int NUM_ATTEMPTS = 10; private final ClientUpdateCheckMode updateCheckMode; - private final Integer worldNumber; private Object client = null; private WorldSupplier worldSupplier = new WorldSupplier(); private RSConfig config; - public ClientLoader(ClientUpdateCheckMode updateCheckMode, Integer worldNumber) + public ClientLoader(ClientUpdateCheckMode updateCheckMode) { this.updateCheckMode = updateCheckMode; - this.worldNumber = worldNumber; } private static Applet loadRLPlus(final RSConfig config) @@ -187,18 +185,6 @@ public class ClientLoader implements Supplier throw new IOException("Invalid or missing jav_config"); } - if (worldNumber != null) - { - final World world = worldSupplier.get(w -> w.getId() == worldNumber); - if (world == null) - { - log.warn("The provided world: {} could not be found. Reverting to random P2P world.", worldNumber); - return; - } - log.info("Set world to: {}", worldNumber); - config.getAppletProperties().replace("12", worldNumber.toString()); - } - return; } catch (IOException e) diff --git a/runelite-client/src/main/java/net/runelite/client/rs/WorldSupplier.java b/runelite-client/src/main/java/net/runelite/client/rs/WorldSupplier.java index 3254595ca7..a82f180ead 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/WorldSupplier.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/WorldSupplier.java @@ -85,30 +85,4 @@ class WorldSupplier implements Supplier return worlds.poll(); } - - @Nullable - public World get(Predicate filter) - { - try - { - List filteredWorlds = new WorldClient(RuneLiteAPI.CLIENT) - .lookupWorlds() - .getWorlds() - .stream() - .filter(filter) - .collect(Collectors.toList()); - - Collections.shuffle(filteredWorlds, random); - - if (filteredWorlds.size() > 0) - { - return filteredWorlds.get(0); - } - } - catch (IOException e) - { - log.warn("Unable to retrieve world list", e); - } - return null; - } } From 1beb983d41ae8bd66b22995171e5803cd1f4f259 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 30 Jan 2020 23:53:34 -0500 Subject: [PATCH 5/5] Remove unused imports --- .../src/main/java/net/runelite/client/rs/WorldSupplier.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/rs/WorldSupplier.java b/runelite-client/src/main/java/net/runelite/client/rs/WorldSupplier.java index a82f180ead..6e143b1326 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/WorldSupplier.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/WorldSupplier.java @@ -31,10 +31,8 @@ import java.util.EnumSet; import java.util.List; import java.util.Queue; import java.util.Random; -import java.util.function.Predicate; import java.util.function.Supplier; import java.util.stream.Collectors; -import javax.annotation.Nullable; import lombok.extern.slf4j.Slf4j; import net.runelite.http.api.RuneLiteAPI; import net.runelite.http.api.worlds.World;