diff --git a/runelite-client/src/main/java/net/runelite/client/ClientSessionManager.java b/runelite-client/src/main/java/net/runelite/client/ClientSessionManager.java index f672a0d05e..fc26d2c8af 100644 --- a/runelite-client/src/main/java/net/runelite/client/ClientSessionManager.java +++ b/runelite-client/src/main/java/net/runelite/client/ClientSessionManager.java @@ -79,7 +79,7 @@ public class ClientSessionManager } sessionId = null; } - + scheduledFuture.cancel(true); } diff --git a/runelite-client/src/main/java/net/runelite/client/Notifier.java b/runelite-client/src/main/java/net/runelite/client/Notifier.java index d1423f168e..3978bebfa4 100644 --- a/runelite-client/src/main/java/net/runelite/client/Notifier.java +++ b/runelite-client/src/main/java/net/runelite/client/Notifier.java @@ -100,7 +100,7 @@ public class Notifier // First check if we are running in launcher this.terminalNotifierAvailable = !Strings.isNullOrEmpty(RuneLiteProperties.getLauncherVersion()) - && isTerminalNotifierAvailable(); + && isTerminalNotifierAvailable(); storeIcon(); } 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 c9c575bd36..81b0249b89 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLite.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLite.java @@ -59,7 +59,6 @@ import net.runelite.client.menus.MenuManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginInstantiationException; import net.runelite.client.plugins.PluginManager; -import net.runelite.client.plugins.config.ConfigPanel; import net.runelite.client.rs.ClientUpdateCheckMode; import net.runelite.client.task.Scheduler; import net.runelite.client.ui.ClientUI; @@ -86,10 +85,10 @@ 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"); - public static RuneLiteSplashScreen splashScreen = new RuneLiteSplashScreen(); + static final RuneLiteSplashScreen splashScreen = new RuneLiteSplashScreen(); - @Getter + @Getter private static Injector injector; @Inject @@ -242,7 +241,7 @@ public class RuneLite // The submessage is shown in case the connection is slow splashScreen.setMessage("Starting RuneLite Injector"); - splashScreen.setSubMessage( " "); + splashScreen.setSubMessage(" "); final long start = System.currentTimeMillis(); diff --git a/runelite-client/src/main/java/net/runelite/client/RuneLiteProperties.java b/runelite-client/src/main/java/net/runelite/client/RuneLiteProperties.java index e86e436c54..b3ca2cafcf 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLiteProperties.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLiteProperties.java @@ -80,9 +80,12 @@ public class RuneLiteProperties public String getDiscordAppId() { - if (RuneLitePlusPlugin.customPresenceEnabled) { + if (RuneLitePlusPlugin.customPresenceEnabled) + { return properties.getProperty(RuneLitePlusPlugin.rlPlusDiscordApp); - } else { + } + else + { return properties.getProperty(DISCORD_APP_ID); } } diff --git a/runelite-client/src/main/java/net/runelite/client/SessionClient.java b/runelite-client/src/main/java/net/runelite/client/SessionClient.java index 9d02ee1961..658c73b571 100644 --- a/runelite-client/src/main/java/net/runelite/client/SessionClient.java +++ b/runelite-client/src/main/java/net/runelite/client/SessionClient.java @@ -50,7 +50,7 @@ class SessionClient try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute()) { ResponseBody body = response.body(); - + InputStream in = body.byteStream(); return RuneLiteAPI.GSON.fromJson(new InputStreamReader(in), UUID.class); } diff --git a/runelite-client/src/main/java/net/runelite/client/account/SessionManager.java b/runelite-client/src/main/java/net/runelite/client/account/SessionManager.java index 6ef8c82e73..4fc8152126 100644 --- a/runelite-client/src/main/java/net/runelite/client/account/SessionManager.java +++ b/runelite-client/src/main/java/net/runelite/client/account/SessionManager.java @@ -1,232 +1,232 @@ -/* - * Copyright (c) 2017, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.account; - -import com.google.gson.Gson; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStreamReader; -import java.time.Instant; -import java.util.UUID; -import javax.inject.Inject; -import javax.inject.Singleton; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import net.runelite.client.events.SessionClose; -import net.runelite.client.events.SessionOpen; -import net.runelite.client.RuneLite; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.EventBus; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.util.LinkBrowser; -import net.runelite.client.ws.WSClient; -import net.runelite.http.api.account.AccountClient; -import net.runelite.http.api.account.OAuthResponse; -import net.runelite.http.api.ws.messages.LoginResponse; - -@Singleton -@Slf4j -public class SessionManager -{ - private static final File SESSION_FILE = new File(RuneLite.RUNELITE_DIR, "session"); - - @Getter - private AccountSession accountSession; - - private final EventBus eventBus; - private final ConfigManager configManager; - private final WSClient wsClient; - - @Inject - private SessionManager(ConfigManager configManager, EventBus eventBus, WSClient wsClient) - { - this.configManager = configManager; - this.eventBus = eventBus; - this.wsClient = wsClient; - eventBus.register(this); - } - - public void loadSession() - { - if (!SESSION_FILE.exists()) - { - log.info("No session file exists"); - return; - } - - AccountSession session; - - try (FileInputStream in = new FileInputStream(SESSION_FILE)) - { - session = new Gson().fromJson(new InputStreamReader(in), AccountSession.class); - - log.debug("Loaded session for {}", session.getUsername()); - } - catch (Exception ex) - { - log.warn("Unable to load session file", ex); - return; - } - - // Check if session is still valid - AccountClient accountClient = new AccountClient(session.getUuid()); - if (!accountClient.sesssionCheck()) - { - log.debug("Loaded session {} is invalid", session.getUuid()); - return; - } - - openSession(session, false); - } - - private void saveSession() - { - if (accountSession == null) - { - return; - } - - try (FileWriter fw = new FileWriter(SESSION_FILE)) - { - new Gson().toJson(accountSession, fw); - - log.debug("Saved session to {}", SESSION_FILE); - } - catch (IOException ex) - { - log.warn("Unable to save session file", ex); - } - } - - private void deleteSession() - { - SESSION_FILE.delete(); - } - - /** - * Set the given session as the active session and open a socket to the - * server with the given session - * - * @param session session - */ - private void openSession(AccountSession session, boolean openSocket) - { - // Change session on the websocket - if (openSocket) - { - wsClient.changeSession(session.getUuid()); - } - - accountSession = session; - - if (session.getUsername() != null) - { - // Initialize config for new session - // If the session isn't logged in yet, don't switch to the new config - configManager.switchSession(session); - } - - eventBus.post(new SessionOpen()); - } - - private void closeSession() - { - wsClient.changeSession(null); - - if (accountSession == null) - { - return; - } - - log.debug("Logging out of account {}", accountSession.getUsername()); - - AccountClient client = new AccountClient(accountSession.getUuid()); - try - { - client.logout(); - } - catch (IOException ex) - { - log.warn("Unable to logout of session", ex); - } - - accountSession = null; // No more account - - // Restore config - configManager.switchSession(null); - - eventBus.post(new SessionClose()); - } - - public void login() - { - // If a session is already open, use that id. Otherwise generate a new id. - UUID uuid = wsClient.getSessionId() != null ? wsClient.getSessionId() : UUID.randomUUID(); - AccountClient loginClient = new AccountClient(uuid); - - final OAuthResponse login; - - try - { - login = loginClient.login(); - } - catch (IOException ex) - { - log.warn("Unable to get oauth url", ex); - return; - } - - // Create new session - openSession(new AccountSession(login.getUid(), Instant.now()), true); - - // Navigate to login link - LinkBrowser.browse(login.getOauthUrl()); - } - - @Subscribe - public void onLoginResponse(LoginResponse loginResponse) - { - log.debug("Now logged in as {}", loginResponse.getUsername()); - - AccountSession session = getAccountSession(); - session.setUsername(loginResponse.getUsername()); - - // Open session, again, now that we have a username - // This triggers onSessionOpen - // The socket is already opened here anyway so we pass true for openSocket - openSession(session, true); - - // Save session to disk - saveSession(); - } - - public void logout() - { - closeSession(); - deleteSession(); - } -} +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.account; + +import com.google.gson.Gson; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.time.Instant; +import java.util.UUID; +import javax.inject.Inject; +import javax.inject.Singleton; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.client.RuneLite; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.EventBus; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.events.SessionClose; +import net.runelite.client.events.SessionOpen; +import net.runelite.client.util.LinkBrowser; +import net.runelite.client.ws.WSClient; +import net.runelite.http.api.account.AccountClient; +import net.runelite.http.api.account.OAuthResponse; +import net.runelite.http.api.ws.messages.LoginResponse; + +@Singleton +@Slf4j +public class SessionManager +{ + private static final File SESSION_FILE = new File(RuneLite.RUNELITE_DIR, "session"); + + @Getter + private AccountSession accountSession; + + private final EventBus eventBus; + private final ConfigManager configManager; + private final WSClient wsClient; + + @Inject + private SessionManager(ConfigManager configManager, EventBus eventBus, WSClient wsClient) + { + this.configManager = configManager; + this.eventBus = eventBus; + this.wsClient = wsClient; + eventBus.register(this); + } + + public void loadSession() + { + if (!SESSION_FILE.exists()) + { + log.info("No session file exists"); + return; + } + + AccountSession session; + + try (FileInputStream in = new FileInputStream(SESSION_FILE)) + { + session = new Gson().fromJson(new InputStreamReader(in), AccountSession.class); + + log.debug("Loaded session for {}", session.getUsername()); + } + catch (Exception ex) + { + log.warn("Unable to load session file", ex); + return; + } + + // Check if session is still valid + AccountClient accountClient = new AccountClient(session.getUuid()); + if (!accountClient.sesssionCheck()) + { + log.debug("Loaded session {} is invalid", session.getUuid()); + return; + } + + openSession(session, false); + } + + private void saveSession() + { + if (accountSession == null) + { + return; + } + + try (FileWriter fw = new FileWriter(SESSION_FILE)) + { + new Gson().toJson(accountSession, fw); + + log.debug("Saved session to {}", SESSION_FILE); + } + catch (IOException ex) + { + log.warn("Unable to save session file", ex); + } + } + + private void deleteSession() + { + SESSION_FILE.delete(); + } + + /** + * Set the given session as the active session and open a socket to the + * server with the given session + * + * @param session session + */ + private void openSession(AccountSession session, boolean openSocket) + { + // Change session on the websocket + if (openSocket) + { + wsClient.changeSession(session.getUuid()); + } + + accountSession = session; + + if (session.getUsername() != null) + { + // Initialize config for new session + // If the session isn't logged in yet, don't switch to the new config + configManager.switchSession(session); + } + + eventBus.post(new SessionOpen()); + } + + private void closeSession() + { + wsClient.changeSession(null); + + if (accountSession == null) + { + return; + } + + log.debug("Logging out of account {}", accountSession.getUsername()); + + AccountClient client = new AccountClient(accountSession.getUuid()); + try + { + client.logout(); + } + catch (IOException ex) + { + log.warn("Unable to logout of session", ex); + } + + accountSession = null; // No more account + + // Restore config + configManager.switchSession(null); + + eventBus.post(new SessionClose()); + } + + public void login() + { + // If a session is already open, use that id. Otherwise generate a new id. + UUID uuid = wsClient.getSessionId() != null ? wsClient.getSessionId() : UUID.randomUUID(); + AccountClient loginClient = new AccountClient(uuid); + + final OAuthResponse login; + + try + { + login = loginClient.login(); + } + catch (IOException ex) + { + log.warn("Unable to get oauth url", ex); + return; + } + + // Create new session + openSession(new AccountSession(login.getUid(), Instant.now()), true); + + // Navigate to login link + LinkBrowser.browse(login.getOauthUrl()); + } + + @Subscribe + public void onLoginResponse(LoginResponse loginResponse) + { + log.debug("Now logged in as {}", loginResponse.getUsername()); + + AccountSession session = getAccountSession(); + session.setUsername(loginResponse.getUsername()); + + // Open session, again, now that we have a username + // This triggers onSessionOpen + // The socket is already opened here anyway so we pass true for openSocket + openSession(session, true); + + // Save session to disk + saveSession(); + } + + public void logout() + { + closeSession(); + deleteSession(); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java b/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java index 12de2c567b..efe003367b 100644 --- a/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java +++ b/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java @@ -374,6 +374,7 @@ public class Hooks implements Callbacks /** * Copy an image + * * @param src * @return */ diff --git a/runelite-client/src/main/java/net/runelite/client/config/ConfigInvocationHandler.java b/runelite-client/src/main/java/net/runelite/client/config/ConfigInvocationHandler.java index f2aa57ff3e..e1813a6fac 100644 --- a/runelite-client/src/main/java/net/runelite/client/config/ConfigInvocationHandler.java +++ b/runelite-client/src/main/java/net/runelite/client/config/ConfigInvocationHandler.java @@ -1,153 +1,153 @@ -/* - * Copyright (c) 2017, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.config; - -import java.lang.invoke.MethodHandles; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.util.Objects; -import lombok.extern.slf4j.Slf4j; - -@Slf4j -class ConfigInvocationHandler implements InvocationHandler -{ - private final ConfigManager manager; - - public ConfigInvocationHandler(ConfigManager manager) - { - this.manager = manager; - } - - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable - { - Class iface = proxy.getClass().getInterfaces()[0]; - - ConfigGroup group = iface.getAnnotation(ConfigGroup.class); - ConfigItem item = method.getAnnotation(ConfigItem.class); - - if (group == null) - { - log.warn("Configuration proxy class {} has no @ConfigGroup!", proxy.getClass()); - return null; - } - - if (item == null) - { - log.warn("Configuration method {} has no @ConfigItem!", method); - return null; - } - - if (args == null) - { - // Getting configuration item - String value = manager.getConfiguration(group.value(), item.keyName()); - - if (value == null) - { - if (method.isDefault()) - { - return callDefaultMethod(proxy, method, null); - } - - return null; - } - - // Convert value to return type - Class returnType = method.getReturnType(); - - try - { - return ConfigManager.stringToObject(value, returnType); - } - catch (Exception e) - { - log.warn("Unable to unmarshal {}.{} ", group.value(), item.keyName(), e); - if (method.isDefault()) - { - return callDefaultMethod(proxy, method, null); - } - return null; - } - } - else - { - // Setting a configuration value - - if (args.length != 1) - { - throw new RuntimeException("Invalid number of arguents to configuration method"); - } - - Object newValue = args[0]; - - Class type = method.getParameterTypes()[0]; - Object oldValue = manager.getConfiguration(group.value(), item.keyName(), type); - - if (Objects.equals(oldValue, newValue)) - { - // nothing to do - return null; - } - - if (method.isDefault()) - { - Object defaultValue = callDefaultMethod(proxy, method, args); - - if (Objects.equals(newValue, defaultValue)) - { - // Just unset if it goes back to the default - manager.unsetConfiguration(group.value(), item.keyName()); - return null; - } - } - - if (newValue == null) - { - manager.unsetConfiguration(group.value(), item.keyName()); - } - else - { - String newValueStr = ConfigManager.objectToString(newValue); - manager.setConfiguration(group.value(), item.keyName(), newValueStr); - } - return null; - } - } - - static Object callDefaultMethod(Object proxy, Method method, Object[] args) throws Throwable - { - // Call the default method implementation - https://rmannibucau.wordpress.com/2014/03/27/java-8-default-interface-methods-and-jdk-dynamic-proxies/ - Constructor constructor = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class, int.class); - constructor.setAccessible(true); - - Class declaringClass = method.getDeclaringClass(); - return constructor.newInstance(declaringClass, MethodHandles.Lookup.PUBLIC | MethodHandles.Lookup.PRIVATE) - .unreflectSpecial(method, declaringClass) - .bindTo(proxy) - .invokeWithArguments(args); - } -} +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.config; + +import java.lang.invoke.MethodHandles; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.util.Objects; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +class ConfigInvocationHandler implements InvocationHandler +{ + private final ConfigManager manager; + + public ConfigInvocationHandler(ConfigManager manager) + { + this.manager = manager; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable + { + Class iface = proxy.getClass().getInterfaces()[0]; + + ConfigGroup group = iface.getAnnotation(ConfigGroup.class); + ConfigItem item = method.getAnnotation(ConfigItem.class); + + if (group == null) + { + log.warn("Configuration proxy class {} has no @ConfigGroup!", proxy.getClass()); + return null; + } + + if (item == null) + { + log.warn("Configuration method {} has no @ConfigItem!", method); + return null; + } + + if (args == null) + { + // Getting configuration item + String value = manager.getConfiguration(group.value(), item.keyName()); + + if (value == null) + { + if (method.isDefault()) + { + return callDefaultMethod(proxy, method, null); + } + + return null; + } + + // Convert value to return type + Class returnType = method.getReturnType(); + + try + { + return ConfigManager.stringToObject(value, returnType); + } + catch (Exception e) + { + log.warn("Unable to unmarshal {}.{} ", group.value(), item.keyName(), e); + if (method.isDefault()) + { + return callDefaultMethod(proxy, method, null); + } + return null; + } + } + else + { + // Setting a configuration value + + if (args.length != 1) + { + throw new RuntimeException("Invalid number of arguents to configuration method"); + } + + Object newValue = args[0]; + + Class type = method.getParameterTypes()[0]; + Object oldValue = manager.getConfiguration(group.value(), item.keyName(), type); + + if (Objects.equals(oldValue, newValue)) + { + // nothing to do + return null; + } + + if (method.isDefault()) + { + Object defaultValue = callDefaultMethod(proxy, method, args); + + if (Objects.equals(newValue, defaultValue)) + { + // Just unset if it goes back to the default + manager.unsetConfiguration(group.value(), item.keyName()); + return null; + } + } + + if (newValue == null) + { + manager.unsetConfiguration(group.value(), item.keyName()); + } + else + { + String newValueStr = ConfigManager.objectToString(newValue); + manager.setConfiguration(group.value(), item.keyName(), newValueStr); + } + return null; + } + } + + static Object callDefaultMethod(Object proxy, Method method, Object[] args) throws Throwable + { + // Call the default method implementation - https://rmannibucau.wordpress.com/2014/03/27/java-8-default-interface-methods-and-jdk-dynamic-proxies/ + Constructor constructor = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class, int.class); + constructor.setAccessible(true); + + Class declaringClass = method.getDeclaringClass(); + return constructor.newInstance(declaringClass, MethodHandles.Lookup.PUBLIC | MethodHandles.Lookup.PRIVATE) + .unreflectSpecial(method, declaringClass) + .bindTo(proxy) + .invokeWithArguments(args); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/config/ConfigItemsGroup.java b/runelite-client/src/main/java/net/runelite/client/config/ConfigItemsGroup.java index 51363c81c4..3c78e8f331 100644 --- a/runelite-client/src/main/java/net/runelite/client/config/ConfigItemsGroup.java +++ b/runelite-client/src/main/java/net/runelite/client/config/ConfigItemsGroup.java @@ -1,52 +1,52 @@ -/* - * Copyright (c) 2018, Craftiii4 - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.config; - -import lombok.AccessLevel; -import lombok.Getter; -import java.util.ArrayList; -import java.util.Collection; - -public class ConfigItemsGroup -{ - - @Getter(AccessLevel.PUBLIC) - private final String group; - - @Getter(AccessLevel.PUBLIC) - private Collection items; - - public ConfigItemsGroup(String group) - { - this.group = group; - this.items = new ArrayList<>(); - } - - public void addItem(ConfigItemDescriptor item) - { - items.add(item); - } - -} +/* + * Copyright (c) 2018, Craftiii4 + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.config; + +import java.util.ArrayList; +import java.util.Collection; +import lombok.AccessLevel; +import lombok.Getter; + +public class ConfigItemsGroup +{ + + @Getter(AccessLevel.PUBLIC) + private final String group; + + @Getter(AccessLevel.PUBLIC) + private Collection items; + + public ConfigItemsGroup(String group) + { + this.group = group; + this.items = new ArrayList<>(); + } + + public void addItem(ConfigItemDescriptor item) + { + items.add(item); + } + +} diff --git a/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java b/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java index da8b608aa3..b0f42f7bf1 100644 --- a/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java +++ b/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java @@ -364,9 +364,9 @@ public class ConfigManager } itemGroups = itemGroups.stream().sorted((a, b) -> ComparisonChain.start() - .compare(a.getGroup(), b.getGroup()) - .result()) - .collect(Collectors.toList()); + .compare(a.getGroup(), b.getGroup()) + .result()) + .collect(Collectors.toList()); return new ConfigDescriptor(group, itemGroups); } @@ -511,22 +511,22 @@ public class ConfigManager { return Duration.ofMillis(Long.parseLong(str)); } - if (type == Map.class) - { - Map output = new HashMap<>(); - str = str.substring(1, str.length() - 1); - String[] splitStr = str.split(", "); - for (String s : splitStr) - { - String[] keyVal = s.split("="); - if (keyVal.length > 1) - { - output.put(keyVal[0], keyVal[1]); - } - } + if (type == Map.class) + { + Map output = new HashMap<>(); + str = str.substring(1, str.length() - 1); + String[] splitStr = str.split(", "); + for (String s : splitStr) + { + String[] keyVal = s.split("="); + if (keyVal.length > 1) + { + output.put(keyVal[0], keyVal[1]); + } + } - return output; - } + return output; + } return str; } diff --git a/runelite-client/src/main/java/net/runelite/client/config/FontType.java b/runelite-client/src/main/java/net/runelite/client/config/FontType.java index 8ed57bd302..c8a28dd262 100644 --- a/runelite-client/src/main/java/net/runelite/client/config/FontType.java +++ b/runelite-client/src/main/java/net/runelite/client/config/FontType.java @@ -1,49 +1,48 @@ -/* - * Copyright (c) 2018, Tanner - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.config; - -import lombok.RequiredArgsConstructor; -import lombok.Getter; -import net.runelite.client.ui.FontManager; - -import java.awt.Font; - -@Getter -@RequiredArgsConstructor -public enum FontType -{ - REGULAR("Regular", FontManager.getRunescapeFont()), - BOLD("Bold", FontManager.getRunescapeBoldFont()), - SMALL("Small", FontManager.getRunescapeSmallFont()); - - private final String name; - private final Font font; - - @Override - public String toString() - { - return name; - } -} +/* + * Copyright (c) 2018, Tanner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.config; + +import java.awt.Font; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import net.runelite.client.ui.FontManager; + +@Getter +@RequiredArgsConstructor +public enum FontType +{ + REGULAR("Regular", FontManager.getRunescapeFont()), + BOLD("Bold", FontManager.getRunescapeBoldFont()), + SMALL("Small", FontManager.getRunescapeSmallFont()); + + private final String name; + private final Font font; + + @Override + public String toString() + { + return name; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/config/RuneLiteConfig.java b/runelite-client/src/main/java/net/runelite/client/config/RuneLiteConfig.java index 78ec89a46f..be6fef1d6d 100644 --- a/runelite-client/src/main/java/net/runelite/client/config/RuneLiteConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/config/RuneLiteConfig.java @@ -67,7 +67,7 @@ public interface RuneLiteConfig extends Config keyName = "enablePlugins", name = "Enable loading of external plugins", description = "Enable loading of external plugins", - position = 10 + position = 10 ) default boolean enablePlugins() { diff --git a/runelite-client/src/main/java/net/runelite/client/discord/DiscordService.java b/runelite-client/src/main/java/net/runelite/client/discord/DiscordService.java index c125ca0feb..dbf3c36ba2 100644 --- a/runelite-client/src/main/java/net/runelite/client/discord/DiscordService.java +++ b/runelite-client/src/main/java/net/runelite/client/discord/DiscordService.java @@ -106,7 +106,7 @@ public class DiscordService implements AutoCloseable discordEventHandlers.joinGame = this::joinGame; discordEventHandlers.spectateGame = this::spectateGame; discordEventHandlers.joinRequest = this::joinRequest; - discordRPC.Discord_Initialize(runeLiteProperties.discordAppID, discordEventHandlers, true, null); + discordRPC.Discord_Initialize(RuneLiteProperties.discordAppID, discordEventHandlers, true, null); executorService.scheduleAtFixedRate(discordRPC::Discord_RunCallbacks, 0, 2, TimeUnit.SECONDS); } diff --git a/runelite-client/src/main/java/net/runelite/client/flexo/Flexo.java b/runelite-client/src/main/java/net/runelite/client/flexo/Flexo.java index 3427279226..bb810d69a8 100644 --- a/runelite-client/src/main/java/net/runelite/client/flexo/Flexo.java +++ b/runelite-client/src/main/java/net/runelite/client/flexo/Flexo.java @@ -35,248 +35,307 @@ for mouse motion. package net.runelite.client.flexo; import com.github.joonasvali.naturalmouse.api.MouseMotionFactory; -import net.runelite.api.Client; -import net.runelite.client.ui.ClientUI; -import sun.awt.ComponentFactory; - -import javax.swing.*; -import java.awt.*; +import java.awt.AWTException; +import java.awt.Color; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.Point; +import java.awt.Robot; +import java.awt.Toolkit; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.peer.RobotPeer; import java.util.Random; import java.util.logging.Logger; +import net.runelite.api.Client; +import net.runelite.api.Constants; +import net.runelite.client.ui.ClientUI; +import sun.awt.ComponentFactory; -public class Flexo extends Robot { - public ThreadGroup flexoThreads = new ThreadGroup("flexo"); - public static boolean isActive; - public static double scale; - public static Client client; - public static ClientUI clientUI; - public static int fixedWidth = 765; - public static int fixedHeight = 503; - public static boolean isStretched; - public static int minDelay = 45; - public static MouseMotionFactory currentMouseMotionFactory; - public boolean pausedIndefinitely = false; - private Thread holdKeyThread; - private RobotPeer peer; +public class Flexo extends Robot +{ + public ThreadGroup flexoThreads = new ThreadGroup("flexo"); + public static boolean isActive; + public static double scale; + public static Client client; + public static ClientUI clientUI; + public static int fixedWidth = Constants.GAME_FIXED_WIDTH; + public static int fixedHeight = Constants.GAME_FIXED_HEIGHT; + public static boolean isStretched; + public static int minDelay = 45; + public static MouseMotionFactory currentMouseMotionFactory; + public boolean pausedIndefinitely = false; + private Thread holdKeyThread; + private RobotPeer peer; - public Flexo() throws AWTException { - if (GraphicsEnvironment.isHeadless()) { - throw new AWTException("headless environment"); - } - init(GraphicsEnvironment.getLocalGraphicsEnvironment() - .getDefaultScreenDevice()); - } + public Flexo() throws AWTException + { + if (GraphicsEnvironment.isHeadless()) + { + throw new AWTException("headless environment"); + } + init(GraphicsEnvironment.getLocalGraphicsEnvironment() + .getDefaultScreenDevice()); + } - private void init(GraphicsDevice screen) throws AWTException { - Toolkit toolkit = Toolkit.getDefaultToolkit(); - if (toolkit instanceof ComponentFactory) { - peer = ((ComponentFactory)toolkit).createRobot(this, screen); - RobotDisposer disposer = new RobotDisposer(peer); - sun.java2d.Disposer.addRecord(anchor, disposer); - } - } + private void init(GraphicsDevice screen) throws AWTException + { + Toolkit toolkit = Toolkit.getDefaultToolkit(); + if (toolkit instanceof ComponentFactory) + { + peer = ((ComponentFactory) toolkit).createRobot(this, screen); + RobotDisposer disposer = new RobotDisposer(peer); + sun.java2d.Disposer.addRecord(anchor, disposer); + } + } - private transient Object anchor = new Object(); + private transient Object anchor = new Object(); - static class RobotDisposer implements sun.java2d.DisposerRecord { - private final RobotPeer peer; - private RobotDisposer(RobotPeer peer) { - this.peer = peer; - } - public void dispose() { - if (peer != null) { - peer.dispose(); - } - } - } + static class RobotDisposer implements sun.java2d.DisposerRecord + { + private final RobotPeer peer; - private void pauseMS(int delayMS) { - long initialMS = System.currentTimeMillis(); - while (System.currentTimeMillis()5) { - Logger.getAnonymousLogger().warning("Invalid mouse button ID. please use 1-5."); - return; - } - peer.mousePress(InputEvent.getMaskForButton(buttonID)); - this.delay(getMinDelay()); - } + @Override + public synchronized void mouseMove(int x, int y) + { + try + { + //TODO: Must be better way to determine titlebar width + currentMouseMotionFactory.build(ClientUI.frame.getX() + x + determineHorizontalOffset(), ClientUI.frame.getY() + y + determineVerticalOffset()).move(); + this.delay(getMinDelay()); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } - public synchronized void mousePressAndRelease(int buttonID) { - if (buttonID<1 || buttonID >5) { - Logger.getAnonymousLogger().warning("Invalid mouse button ID. please use 1-5."); - return; - } - peer.mousePress(InputEvent.getMaskForButton(buttonID)); - this.delay(getMinDelay()); - peer.mouseRelease(InputEvent.getMaskForButton(buttonID)); - this.delay(getMinDelay()); - } + public synchronized void mouseMove(Point p) + { + Point p2 = p; + mouseMove((int) p.getX(), (int) p.getY()); + try + { + Thread.sleep(150); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } - //TODO: Symbols are nut supported at this time - public synchronized void typeMessage(String message) { + @Override + public synchronized void mousePress(int buttonID) + { + if (buttonID < 1 || buttonID > 5) + { + Logger.getAnonymousLogger().warning("Invalid mouse button ID. please use 1-5."); + return; + } + peer.mousePress(InputEvent.getMaskForButton(buttonID)); + this.delay(getMinDelay()); + } - Random r = new Random(); - char[] charArray = message.toCharArray(); - for (char c : charArray) { - keyPress(KeyEvent.getExtendedKeyCodeForChar(c)); - this.delay(93+r.nextInt(getMinDelay())); - } - keyPress(KeyEvent.VK_ENTER); - this.delay(93+r.nextInt(getMinDelay())); - ClientUI.allowInput = true; - } + public synchronized void mousePressAndRelease(int buttonID) + { + if (buttonID < 1 || buttonID > 5) + { + Logger.getAnonymousLogger().warning("Invalid mouse button ID. please use 1-5."); + return; + } + peer.mousePress(InputEvent.getMaskForButton(buttonID)); + this.delay(getMinDelay()); + peer.mouseRelease(InputEvent.getMaskForButton(buttonID)); + this.delay(getMinDelay()); + } + + //TODO: Symbols are nut supported at this time + public synchronized void typeMessage(String message) + { + + Random r = new Random(); + char[] charArray = message.toCharArray(); + for (char c : charArray) + { + keyPress(KeyEvent.getExtendedKeyCodeForChar(c)); + this.delay(93 + r.nextInt(getMinDelay())); + } + keyPress(KeyEvent.VK_ENTER); + this.delay(93 + r.nextInt(getMinDelay())); + ClientUI.allowInput = true; + } + @Override + public synchronized void mouseRelease(int buttonID) + { + if (buttonID < 1 || buttonID > 5) + { + Logger.getAnonymousLogger().warning("Invalid mouse button ID. please use 1-5."); + return; + } + peer.mouseRelease(InputEvent.getMaskForButton(buttonID)); + this.delay(getMinDelay()); + } - @Override - public synchronized void mouseRelease(int buttonID) { - if (buttonID<1 || buttonID >5) { - Logger.getAnonymousLogger().warning("Invalid mouse button ID. please use 1-5."); - return; - } - peer.mouseRelease(InputEvent.getMaskForButton(buttonID)); - this.delay(getMinDelay()); - } + private int getMinDelay() + { + Random random = new Random(); + int random1 = random.nextInt(minDelay); + if (random1 < minDelay / 2) + { + random1 = random.nextInt(minDelay / 2) + minDelay / 2 + random.nextInt(minDelay / 2); + } + return random1; + } - private int getMinDelay() { - Random random = new Random(); - int random1 = random.nextInt(minDelay); - if (random1 < minDelay/2) - random1 = random.nextInt(minDelay/2) + minDelay/2+random.nextInt(minDelay/2); - return random1; - } + private int getWheelDelay() + { + Random random = new Random(); + int random1 = random.nextInt(minDelay); + if (random1 < minDelay / 2) + { + random1 = random.nextInt(minDelay / 2) + minDelay / 2 + random.nextInt(minDelay / 2); + } + return random1; + } - private int getWheelDelay() { - Random random = new Random(); - int random1 = random.nextInt(minDelay); - if (random1 < minDelay/2) - random1 = random.nextInt(minDelay/2) + minDelay/2+random.nextInt(minDelay/2); - return random1; - } + /** + * Rotates the scroll wheel on wheel-equipped mice. + * + * @param wheelAmt number of "notches" to move the mouse wheel + * Negative values indicate movement up/away from the user, + * positive values indicate movement down/towards the user. + * @since 1.4 + */ + @Override + public synchronized void mouseWheel(int wheelAmt) + { + for (int i : new int[wheelAmt]) + { + peer.mouseWheel(wheelAmt); + this.delay(getWheelDelay()); + } + } - /** - * Rotates the scroll wheel on wheel-equipped mice. - * - * @param wheelAmt number of "notches" to move the mouse wheel - * Negative values indicate movement up/away from the user, - * positive values indicate movement down/towards the user. - * - * @since 1.4 - */ - @Override - public synchronized void mouseWheel(int wheelAmt) { - for (int i : new int[wheelAmt]) { - peer.mouseWheel(wheelAmt); - this.delay(getWheelDelay()); - } - } + /** + * Presses a given key. The key should be released using the + * keyRelease method. + *

+ * Key codes that have more than one physical key associated with them + * (e.g. KeyEvent.VK_SHIFT could mean either the + * left or right shift key) will map to the left key. + * + * @param keycode Key to press (e.g. KeyEvent.VK_A) + * @throws IllegalArgumentException if keycode is not + * a valid key + * @see #keyRelease(int) + * @see java.awt.event.KeyEvent + */ + @Override + public synchronized void keyPress(int keycode) + { + peer.keyPress(keycode); + this.delay(getMinDelay()); + } - /** - * Presses a given key. The key should be released using the - * keyRelease method. - *

- * Key codes that have more than one physical key associated with them - * (e.g. KeyEvent.VK_SHIFT could mean either the - * left or right shift key) will map to the left key. - * - * @param keycode Key to press (e.g. KeyEvent.VK_A) - * @throws IllegalArgumentException if keycode is not - * a valid key - * @see #keyRelease(int) - * @see java.awt.event.KeyEvent - */ - @Override - public synchronized void keyPress(int keycode) { - peer.keyPress(keycode); - this.delay(getMinDelay()); - } + @Override + public synchronized void keyRelease(int keycode) + { + peer.keyRelease(keycode); + this.delay(getMinDelay()); + } - @Override - public synchronized void keyRelease(int keycode) { - peer.keyRelease(keycode); - this.delay(getMinDelay()); - } + public synchronized void holdKey(int keycode, int timeMS) + { + new Thread(() -> + { + peer.keyPress(keycode); + long startTime = System.currentTimeMillis(); + while ((startTime + timeMS) > System.currentTimeMillis()) + { + } + peer.keyRelease(keycode); + this.delay(getMinDelay()); + }).start(); + } - public synchronized void holdKey(int keycode, int timeMS) { - new Thread(() -> { - peer.keyPress(keycode); - long startTime = System.currentTimeMillis(); - while ((startTime + timeMS) > System.currentTimeMillis()) { } - peer.keyRelease(keycode); - this.delay(getMinDelay()); - }).start(); - } + public synchronized void holdKeyIndefinitely(int keycode) + { + holdKeyThread = new Thread(() -> + { + pausedIndefinitely = true; + peer.keyPress(keycode); + while (pausedIndefinitely) + { + try + { + Thread.sleep(10); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } + peer.keyRelease(keycode); + this.delay(getMinDelay()); + }); + holdKeyThread.start(); - public synchronized void holdKeyIndefinitely(int keycode) { - holdKeyThread = new Thread(() -> { - pausedIndefinitely = true; - peer.keyPress(keycode); - while (pausedIndefinitely) { - try { - holdKeyThread.sleep(10); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - peer.keyRelease(keycode); - this.delay(getMinDelay()); - }); - holdKeyThread.start(); + } - } + @Override + public Color getPixelColor(int x, int y) + { + Color color = new Color(peer.getRGBPixel(x, y)); + return color; + } - @Override - public Color getPixelColor(int x, int y) { - Color color = new Color(peer.getRGBPixel(x, y)); - return color; - } + @Override + public void delay(int ms) + { + pauseMS(ms); + } - @Override - public void delay(int ms) { - pauseMS(ms); - } - - public int determineHorizontalOffset() { - return clientUI.getCanvasOffset().getX(); - } - - public int determineVerticalOffset() { - return clientUI.getCanvasOffset().getY(); - } + public int determineHorizontalOffset() + { + return clientUI.getCanvasOffset().getX(); + } + + public int determineVerticalOffset() + { + return clientUI.getCanvasOffset().getY(); + } } diff --git a/runelite-client/src/main/java/net/runelite/client/flexo/FlexoMouse.java b/runelite-client/src/main/java/net/runelite/client/flexo/FlexoMouse.java index 70bbf51ba6..76e1545250 100644 --- a/runelite-client/src/main/java/net/runelite/client/flexo/FlexoMouse.java +++ b/runelite-client/src/main/java/net/runelite/client/flexo/FlexoMouse.java @@ -28,163 +28,198 @@ package net.runelite.client.flexo; -import net.runelite.client.ui.ClientUI; - -import java.awt.*; +import java.awt.Point; +import java.awt.Rectangle; import java.util.Random; import java.util.logging.Logger; +import net.runelite.api.Constants; +import net.runelite.client.ui.ClientUI; -public class FlexoMouse { +public class FlexoMouse +{ - /* - Should pass unstretched coords, handles all conversions here. - */ - public static Point getClickPoint(Rectangle rect) - { - if (rect!=null) { - Random r = new Random(); - int x = -1; - int y = -1; - x = rect.x+r.nextInt(rect.width); - y = rect.y+r.nextInt(rect.height); + /* + Should pass unstretched coords, handles all conversions here. + */ + public static Point getClickPoint(Rectangle rect) + { + if (rect != null) + { + Random r = new Random(); + int x = -1; + int y = -1; + x = rect.x + r.nextInt(rect.width); + y = rect.y + r.nextInt(rect.height); - if (Flexo.isStretched) { - double wScale; - double hScale; + if (Flexo.isStretched) + { + double wScale; + double hScale; - if (Flexo.client.isResized()) { - wScale = (Flexo.client.getStretchedDimensions().width / Flexo.client.getRealDimensions().width); - hScale = (Flexo.client.getStretchedDimensions().height / Flexo.client.getRealDimensions().height); - int newX = (int)(x*wScale); - int newY = (int)(y*hScale); - if (newX>0 && newX< ClientUI.frame.getWidth()) { - if (newY>0 && newY< ClientUI.frame.getHeight()) { - return new Point(newX, newY); - } - } - Logger.getAnonymousLogger().warning("[RuneLit]Flexo - Off screen point attempted. Split the step, or rotate the screen."); - return null; - } else { - if (x>0 && x< ClientUI.frame.getWidth()) { - if (y>0 && y< ClientUI.frame.getHeight()) { - return new Point(x, y); - } - } - Logger.getAnonymousLogger().warning("[RuneLit]Flexo - Off screen point attempted. Split the step, or rotate the screen."); - return null; - } + if (Flexo.client.isResized()) + { + wScale = (Flexo.client.getStretchedDimensions().width / (double) Flexo.client.getRealDimensions().width); + hScale = (Flexo.client.getStretchedDimensions().height / (double) Flexo.client.getRealDimensions().height); + int newX = (int) (x * wScale); + int newY = (int) (y * hScale); + if (newX > 0 && newX < ClientUI.frame.getWidth()) + { + if (newY > 0 && newY < ClientUI.frame.getHeight()) + { + return new Point(newX, newY); + } + } + Logger.getAnonymousLogger().warning("[RuneLit]Flexo - Off screen point attempted. Split the step, or rotate the screen."); + return null; + } + else + { + if (x > 0 && x < ClientUI.frame.getWidth()) + { + if (y > 0 && y < ClientUI.frame.getHeight()) + { + return new Point(x, y); + } + } + Logger.getAnonymousLogger().warning("[RuneLit]Flexo - Off screen point attempted. Split the step, or rotate the screen."); + return null; + } - } else if (!Flexo.client.isResized()) { - int fixedWidth = 765; - int widthDif = ClientUI.frame.getWidth(); + } + else if (!Flexo.client.isResized()) + { + final int fixedWidth = Constants.GAME_FIXED_WIDTH; + int widthDif = ClientUI.frame.getWidth(); - if (ClientUI.pluginToolbar.isVisible()) { - widthDif -= ClientUI.pluginToolbar.getWidth(); - } - if (ClientUI.pluginPanel!=null) - widthDif -= ClientUI.pluginPanel.getWidth(); + if (ClientUI.pluginToolbar.isVisible()) + { + widthDif -= ClientUI.pluginToolbar.getWidth(); + } + if (ClientUI.pluginPanel != null) + { + widthDif -= ClientUI.pluginPanel.getWidth(); + } - widthDif -= fixedWidth; - if (x+(widthDif/2)>0 && x+(widthDif/2)< ClientUI.frame.getWidth()) { - if (y>0 && y< ClientUI.frame.getHeight()) { - return new Point(x, y); - } - } - Logger.getAnonymousLogger().warning("[RuneLit]Flexo - Off screen point attempted. Split the step, or rotate the screen."); - return null; - } - else { - if (x>0 && x< ClientUI.frame.getWidth()) { - if (y>0 && y< ClientUI.frame.getHeight()) { - return new Point(x, y); - } - } - Logger.getAnonymousLogger().warning("[RuneLit]Flexo - Off screen point attempted. Split the step, or rotate the screen."); - return null; - } - } - return null; - } + widthDif -= fixedWidth; + if (x + (widthDif / 2) > 0 && x + (widthDif / 2) < ClientUI.frame.getWidth()) + { + if (y > 0 && y < ClientUI.frame.getHeight()) + { + return new Point(x, y); + } + } + Logger.getAnonymousLogger().warning("[RuneLit]Flexo - Off screen point attempted. Split the step, or rotate the screen."); + return null; + } + else + { + if (x > 0 && x < ClientUI.frame.getWidth()) + { + if (y > 0 && y < ClientUI.frame.getHeight()) + { + return new Point(x, y); + } + } + Logger.getAnonymousLogger().warning("[RuneLit]Flexo - Off screen point attempted. Split the step, or rotate the screen."); + return null; + } + } + return null; + } - public static Rectangle getClickArea(Rectangle rect) - { - if (Flexo.isStretched) - { - double wScale; - double hScale; + public static Rectangle getClickArea(Rectangle rect) + { + if (Flexo.isStretched) + { + double wScale; + double hScale; - if (Flexo.client.isResized()) { - wScale = (Flexo.client.getStretchedDimensions().width / Flexo.client.getRealDimensions().width); - hScale = (Flexo.client.getStretchedDimensions().height / Flexo.client.getRealDimensions().height); - } else { - wScale = ((double) Flexo.client.getStretchedDimensions().width) / Flexo.fixedWidth; - hScale = ((double) Flexo.client.getStretchedDimensions().height) / Flexo.fixedHeight; - } + if (Flexo.client.isResized()) + { + wScale = (Flexo.client.getStretchedDimensions().width / (double) Flexo.client.getRealDimensions().width); + hScale = (Flexo.client.getStretchedDimensions().height / (double) Flexo.client.getRealDimensions().height); + } + else + { + wScale = (Flexo.client.getStretchedDimensions().width) / (double) Flexo.fixedWidth; + hScale = (Flexo.client.getStretchedDimensions().height) / (double) Flexo.fixedHeight; + } - int xPadding = (int)rect.getWidth()/5; - int yPadding = (int)rect.getHeight()/5; - Random r = new Random(); - Rectangle clickRect = new Rectangle(); - clickRect.width = rect.width-xPadding*2; - clickRect.height = rect.height-yPadding*2; - clickRect.x = rect.x+xPadding; - clickRect.y = rect.y+yPadding; - if (clickRect.width>0&&clickRect.height>0) { - int x = clickRect.x+r.nextInt(clickRect.width); - int y = clickRect.y+r.nextInt(clickRect.height); - double tScale = 1 + (Flexo.scale / 100); + int xPadding = (int) rect.getWidth() / 5; + int yPadding = (int) rect.getHeight() / 5; + Random r = new Random(); + Rectangle clickRect = new Rectangle(); + clickRect.width = rect.width - xPadding * 2; + clickRect.height = rect.height - yPadding * 2; + clickRect.x = rect.x + xPadding; + clickRect.y = rect.y + yPadding; + if (clickRect.width > 0 && clickRect.height > 0) + { + int x = clickRect.x + r.nextInt(clickRect.width); + int y = clickRect.y + r.nextInt(clickRect.height); + double tScale = 1 + (Flexo.scale / 100); - if (Flexo.client.isResized()) { - return new Rectangle((int)(clickRect.x * wScale), (int)(clickRect.y * wScale), (int)(clickRect.width * wScale), (int)(clickRect.getHeight()*hScale)); - } else { - return new Rectangle((int)(clickRect.x), (int)(clickRect.y), (int)(clickRect.width), (int)(clickRect.getHeight())); - } - } + if (Flexo.client.isResized()) + { + return new Rectangle((int) (clickRect.x * wScale), (int) (clickRect.y * wScale), (int) (clickRect.width * wScale), (int) (clickRect.getHeight() * hScale)); + } + else + { + return new Rectangle(clickRect.x, clickRect.y, clickRect.width, (int) (clickRect.getHeight())); + } + } - } - //Fixed, not stretched - else if (!Flexo.client.isResized()) { - int fixedWidth = 765; - int widthDif = ClientUI.frame.getWidth(); + } + //Fixed, not stretched + else if (!Flexo.client.isResized()) + { + int fixedWidth = 765; + int widthDif = ClientUI.frame.getWidth(); - if (ClientUI.pluginToolbar.isVisible()) { - widthDif -= ClientUI.pluginToolbar.getWidth(); - } - if (ClientUI.pluginPanel!=null) - widthDif -= ClientUI.pluginPanel.getWidth(); + if (ClientUI.pluginToolbar.isVisible()) + { + widthDif -= ClientUI.pluginToolbar.getWidth(); + } + if (ClientUI.pluginPanel != null) + { + widthDif -= ClientUI.pluginPanel.getWidth(); + } - widthDif -= fixedWidth; - int xPadding = (int)rect.getWidth()/5; - int yPadding = (int)rect.getHeight()/5; - Random r = new Random(); - Rectangle clickRect = new Rectangle(); - clickRect.width = rect.width-xPadding; - clickRect.height = rect.height-yPadding; - clickRect.x = rect.x+xPadding; - clickRect.y = rect.y+yPadding; - if (clickRect.height>0&&clickRect.width>0) { - int x = clickRect.x + r.nextInt(clickRect.width); - int y = clickRect.y + r.nextInt(clickRect.height); - return new Rectangle((int) (clickRect.x), (int) (clickRect.y), (int) (clickRect.width), (int) (clickRect.getHeight())); - } - } - //Resizable, not stretched - else { - int xPadding = (int)rect.getWidth()/5; - int yPadding = (int)rect.getHeight()/5; - Random r = new Random(); - Rectangle clickRect = new Rectangle(); - clickRect.width = rect.width-xPadding*2; - clickRect.height = rect.height-yPadding*2; - clickRect.x = rect.x+xPadding; - clickRect.y = rect.y+yPadding; - if (clickRect.height>0&&clickRect.width>0) { - int x = clickRect.x+r.nextInt(clickRect.width); - int y = clickRect.y+r.nextInt(clickRect.height); - return new Rectangle((int)(clickRect.x), (int)(clickRect.y), (int)(clickRect.width), (int)(clickRect.getHeight())); - } - } + widthDif -= fixedWidth; + int xPadding = (int) rect.getWidth() / 5; + int yPadding = (int) rect.getHeight() / 5; + Random r = new Random(); + Rectangle clickRect = new Rectangle(); + clickRect.width = rect.width - xPadding; + clickRect.height = rect.height - yPadding; + clickRect.x = rect.x + xPadding; + clickRect.y = rect.y + yPadding; + if (clickRect.height > 0 && clickRect.width > 0) + { + int x = clickRect.x + r.nextInt(clickRect.width); + int y = clickRect.y + r.nextInt(clickRect.height); + return new Rectangle(clickRect.x, clickRect.y, clickRect.width, (int) (clickRect.getHeight())); + } + } + //Resizable, not stretched + else + { + int xPadding = (int) rect.getWidth() / 5; + int yPadding = (int) rect.getHeight() / 5; + Random r = new Random(); + Rectangle clickRect = new Rectangle(); + clickRect.width = rect.width - xPadding * 2; + clickRect.height = rect.height - yPadding * 2; + clickRect.x = rect.x + xPadding; + clickRect.y = rect.y + yPadding; + if (clickRect.height > 0 && clickRect.width > 0) + { + int x = clickRect.x + r.nextInt(clickRect.width); + int y = clickRect.y + r.nextInt(clickRect.height); + return new Rectangle(clickRect.x, clickRect.y, clickRect.width, (int) (clickRect.getHeight())); + } + } - return null; - } + return null; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/game/AgilityShortcut.java b/runelite-client/src/main/java/net/runelite/client/game/AgilityShortcut.java index 4a0312485c..49b908992b 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/AgilityShortcut.java +++ b/runelite-client/src/main/java/net/runelite/client/game/AgilityShortcut.java @@ -26,54 +26,258 @@ package net.runelite.client.game; import lombok.Getter; -import static net.runelite.api.NullObjectID.*; -import static net.runelite.api.ObjectID.*; +import static net.runelite.api.NullObjectID.NULL_25337; +import static net.runelite.api.NullObjectID.NULL_26371; +import static net.runelite.api.NullObjectID.NULL_26375; +import static net.runelite.api.NullObjectID.NULL_26884; +import static net.runelite.api.NullObjectID.NULL_26886; +import static net.runelite.api.NullObjectID.NULL_29868; +import static net.runelite.api.NullObjectID.NULL_29869; +import static net.runelite.api.NullObjectID.NULL_29870; +import static net.runelite.api.NullObjectID.NULL_31823; +import static net.runelite.api.NullObjectID.NULL_31849; +import static net.runelite.api.NullObjectID.NULL_33327; +import static net.runelite.api.NullObjectID.NULL_33328; +import static net.runelite.api.ObjectID.A_WOODEN_LOG; +import static net.runelite.api.ObjectID.BALANCING_LEDGE_23548; +import static net.runelite.api.ObjectID.BIG_WINDOW; +import static net.runelite.api.ObjectID.BOULDER_27990; +import static net.runelite.api.ObjectID.BROKEN_FENCE; +import static net.runelite.api.ObjectID.BROKEN_FENCE_2618; +import static net.runelite.api.ObjectID.BROKEN_RAFT; +import static net.runelite.api.ObjectID.BROKEN_WALL_33344; +import static net.runelite.api.ObjectID.CASTLE_WALL; +import static net.runelite.api.ObjectID.CLIMBING_ROCKS; +import static net.runelite.api.ObjectID.CLIMBING_ROCKS_11948; +import static net.runelite.api.ObjectID.CLIMBING_ROCKS_11949; +import static net.runelite.api.ObjectID.CREVICE_16465; +import static net.runelite.api.ObjectID.CREVICE_16539; +import static net.runelite.api.ObjectID.CREVICE_16543; +import static net.runelite.api.ObjectID.CREVICE_19043; +import static net.runelite.api.ObjectID.CREVICE_30198; +import static net.runelite.api.ObjectID.CREVICE_9739; +import static net.runelite.api.ObjectID.CREVICE_9740; +import static net.runelite.api.ObjectID.CROSSBOW_TREE_17062; +import static net.runelite.api.ObjectID.CRUMBLING_WALL_24222; +import static net.runelite.api.ObjectID.DARK_TUNNEL_10047; +import static net.runelite.api.ObjectID.DENSE_FOREST; +import static net.runelite.api.ObjectID.DENSE_FOREST_3938; +import static net.runelite.api.ObjectID.DENSE_FOREST_3939; +import static net.runelite.api.ObjectID.DENSE_FOREST_3998; +import static net.runelite.api.ObjectID.DENSE_FOREST_3999; +import static net.runelite.api.ObjectID.FALLEN_TREE_33192; +import static net.runelite.api.ObjectID.FENCE_16518; +import static net.runelite.api.ObjectID.GAP; +import static net.runelite.api.ObjectID.GAP_2831; +import static net.runelite.api.ObjectID.GAP_29326; +import static net.runelite.api.ObjectID.HOLE_16520; +import static net.runelite.api.ObjectID.HOLE_30966; +import static net.runelite.api.ObjectID.HOLE_31481; +import static net.runelite.api.ObjectID.HOLE_31482; +import static net.runelite.api.ObjectID.ICE_CHUNKS_31822; +import static net.runelite.api.ObjectID.ICE_CHUNKS_31990; +import static net.runelite.api.ObjectID.JUTTING_WALL_17002; +import static net.runelite.api.ObjectID.LADDER_30938; +import static net.runelite.api.ObjectID.LADDER_30939; +import static net.runelite.api.ObjectID.LADDER_30940; +import static net.runelite.api.ObjectID.LADDER_30941; +import static net.runelite.api.ObjectID.LEAVES; +import static net.runelite.api.ObjectID.LEAVES_3924; +import static net.runelite.api.ObjectID.LEAVES_3925; +import static net.runelite.api.ObjectID.LEDGE_33190; +import static net.runelite.api.ObjectID.LITTLE_BOULDER; +import static net.runelite.api.ObjectID.LOG_BALANCE_16540; +import static net.runelite.api.ObjectID.LOG_BALANCE_16541; +import static net.runelite.api.ObjectID.LOG_BALANCE_16542; +import static net.runelite.api.ObjectID.LOG_BALANCE_16546; +import static net.runelite.api.ObjectID.LOG_BALANCE_16547; +import static net.runelite.api.ObjectID.LOG_BALANCE_16548; +import static net.runelite.api.ObjectID.LOG_BALANCE_20882; +import static net.runelite.api.ObjectID.LOG_BALANCE_20884; +import static net.runelite.api.ObjectID.LOG_BALANCE_23274; +import static net.runelite.api.ObjectID.LOG_BALANCE_3929; +import static net.runelite.api.ObjectID.LOG_BALANCE_3930; +import static net.runelite.api.ObjectID.LOG_BALANCE_3931; +import static net.runelite.api.ObjectID.LOG_BALANCE_3932; +import static net.runelite.api.ObjectID.LOG_BALANCE_3933; +import static net.runelite.api.ObjectID.LOOSE_RAILING; +import static net.runelite.api.ObjectID.LOOSE_RAILING_2186; +import static net.runelite.api.ObjectID.LOOSE_RAILING_28849; +import static net.runelite.api.ObjectID.LOW_FENCE; +import static net.runelite.api.ObjectID.MONKEYBARS_23566; +import static net.runelite.api.ObjectID.MONKEYBARS_23567; +import static net.runelite.api.ObjectID.MYSTERIOUS_PIPE; +import static net.runelite.api.ObjectID.OBSTACLE; +import static net.runelite.api.ObjectID.OBSTACLE_30767; +import static net.runelite.api.ObjectID.OBSTACLE_30962; +import static net.runelite.api.ObjectID.OBSTACLE_30964; +import static net.runelite.api.ObjectID.OBSTACLE_PIPE_16509; +import static net.runelite.api.ObjectID.OBSTACLE_PIPE_16511; +import static net.runelite.api.ObjectID.OBSTACLE_PIPE_23140; +import static net.runelite.api.ObjectID.ORNATE_RAILING; +import static net.runelite.api.ObjectID.ORNATE_RAILING_17000; +import static net.runelite.api.ObjectID.PILE_OF_RUBBLE_23563; +import static net.runelite.api.ObjectID.PILE_OF_RUBBLE_23564; +import static net.runelite.api.ObjectID.PILLAR_31561; +import static net.runelite.api.ObjectID.PILLAR_31809; +import static net.runelite.api.ObjectID.PIPE_21727; +import static net.runelite.api.ObjectID.PIPE_21728; +import static net.runelite.api.ObjectID.ROCKS; +import static net.runelite.api.ObjectID.ROCKSLIDE_33184; +import static net.runelite.api.ObjectID.ROCKSLIDE_33185; +import static net.runelite.api.ObjectID.ROCKSLIDE_33191; +import static net.runelite.api.ObjectID.ROCKS_14106; +import static net.runelite.api.ObjectID.ROCKS_16464; +import static net.runelite.api.ObjectID.ROCKS_16514; +import static net.runelite.api.ObjectID.ROCKS_16515; +import static net.runelite.api.ObjectID.ROCKS_16521; +import static net.runelite.api.ObjectID.ROCKS_16522; +import static net.runelite.api.ObjectID.ROCKS_16523; +import static net.runelite.api.ObjectID.ROCKS_16524; +import static net.runelite.api.ObjectID.ROCKS_16534; +import static net.runelite.api.ObjectID.ROCKS_16535; +import static net.runelite.api.ObjectID.ROCKS_16545; +import static net.runelite.api.ObjectID.ROCKS_16549; +import static net.runelite.api.ObjectID.ROCKS_16550; +import static net.runelite.api.ObjectID.ROCKS_16998; +import static net.runelite.api.ObjectID.ROCKS_16999; +import static net.runelite.api.ObjectID.ROCKS_17042; +import static net.runelite.api.ObjectID.ROCKS_19849; +import static net.runelite.api.ObjectID.ROCKS_2231; +import static net.runelite.api.ObjectID.ROCKS_27984; +import static net.runelite.api.ObjectID.ROCKS_27985; +import static net.runelite.api.ObjectID.ROCKS_27987; +import static net.runelite.api.ObjectID.ROCKS_27988; +import static net.runelite.api.ObjectID.ROCKS_31757; +import static net.runelite.api.ObjectID.ROCKS_31758; +import static net.runelite.api.ObjectID.ROCKS_31759; +import static net.runelite.api.ObjectID.ROCKS_34396; +import static net.runelite.api.ObjectID.ROCKS_34397; +import static net.runelite.api.ObjectID.ROCKS_34741; +import static net.runelite.api.ObjectID.ROCKS_3748; +import static net.runelite.api.ObjectID.ROCKS_3790; +import static net.runelite.api.ObjectID.ROCKS_3791; +import static net.runelite.api.ObjectID.ROCKS_3803; +import static net.runelite.api.ObjectID.ROCKS_3804; +import static net.runelite.api.ObjectID.ROCKS_6673; +import static net.runelite.api.ObjectID.ROCKY_HANDHOLDS_26400; +import static net.runelite.api.ObjectID.ROCKY_HANDHOLDS_26401; +import static net.runelite.api.ObjectID.ROCKY_HANDHOLDS_26402; +import static net.runelite.api.ObjectID.ROCKY_HANDHOLDS_26404; +import static net.runelite.api.ObjectID.ROCKY_HANDHOLDS_26405; +import static net.runelite.api.ObjectID.ROCKY_HANDHOLDS_26406; +import static net.runelite.api.ObjectID.ROCK_16115; +import static net.runelite.api.ObjectID.ROPESWING_23568; +import static net.runelite.api.ObjectID.ROPESWING_23569; +import static net.runelite.api.ObjectID.ROPE_ANCHOR; +import static net.runelite.api.ObjectID.ROPE_ANCHOR_30917; +import static net.runelite.api.ObjectID.ROPE_BRIDGE_21306; +import static net.runelite.api.ObjectID.ROPE_BRIDGE_21307; +import static net.runelite.api.ObjectID.ROPE_BRIDGE_21308; +import static net.runelite.api.ObjectID.ROPE_BRIDGE_21309; +import static net.runelite.api.ObjectID.ROPE_BRIDGE_21310; +import static net.runelite.api.ObjectID.ROPE_BRIDGE_21311; +import static net.runelite.api.ObjectID.ROPE_BRIDGE_21312; +import static net.runelite.api.ObjectID.ROPE_BRIDGE_21313; +import static net.runelite.api.ObjectID.ROPE_BRIDGE_21314; +import static net.runelite.api.ObjectID.ROPE_BRIDGE_21315; +import static net.runelite.api.ObjectID.RUBBER_CAP_MUSHROOM; +import static net.runelite.api.ObjectID.SPIKEY_CHAIN; +import static net.runelite.api.ObjectID.SPIKEY_CHAIN_16538; +import static net.runelite.api.ObjectID.STAIRS_31485; +import static net.runelite.api.ObjectID.STEPPING_STONES; +import static net.runelite.api.ObjectID.STEPPING_STONES_23646; +import static net.runelite.api.ObjectID.STEPPING_STONES_23647; +import static net.runelite.api.ObjectID.STEPPING_STONE_10663; +import static net.runelite.api.ObjectID.STEPPING_STONE_11768; +import static net.runelite.api.ObjectID.STEPPING_STONE_13504; +import static net.runelite.api.ObjectID.STEPPING_STONE_14917; +import static net.runelite.api.ObjectID.STEPPING_STONE_14918; +import static net.runelite.api.ObjectID.STEPPING_STONE_16466; +import static net.runelite.api.ObjectID.STEPPING_STONE_16513; +import static net.runelite.api.ObjectID.STEPPING_STONE_16533; +import static net.runelite.api.ObjectID.STEPPING_STONE_19040; +import static net.runelite.api.ObjectID.STEPPING_STONE_19042; +import static net.runelite.api.ObjectID.STEPPING_STONE_21738; +import static net.runelite.api.ObjectID.STEPPING_STONE_21739; +import static net.runelite.api.ObjectID.STEPPING_STONE_29728; +import static net.runelite.api.ObjectID.STEPPING_STONE_29729; +import static net.runelite.api.ObjectID.STEPPING_STONE_29730; +import static net.runelite.api.ObjectID.STEPPING_STONE_5948; +import static net.runelite.api.ObjectID.STEPPING_STONE_5949; +import static net.runelite.api.ObjectID.STEPS; +import static net.runelite.api.ObjectID.STEPS_29993; +import static net.runelite.api.ObjectID.STICKS; +import static net.runelite.api.ObjectID.STILE; +import static net.runelite.api.ObjectID.STILE_12982; +import static net.runelite.api.ObjectID.STRANGE_FLOOR; +import static net.runelite.api.ObjectID.STRANGE_FLOOR_16544; +import static net.runelite.api.ObjectID.STRONG_TREE_17074; +import static net.runelite.api.ObjectID.TIGHTGAP; +import static net.runelite.api.ObjectID.TRELLIS_20056; +import static net.runelite.api.ObjectID.TRIPWIRE; +import static net.runelite.api.ObjectID.TUNNEL_30174; +import static net.runelite.api.ObjectID.TUNNEL_30175; +import static net.runelite.api.ObjectID.TUNNEL_30959; +import static net.runelite.api.ObjectID.UNDERWALL_TUNNEL; +import static net.runelite.api.ObjectID.UNDERWALL_TUNNEL_16528; +import static net.runelite.api.ObjectID.UNDERWALL_TUNNEL_16529; +import static net.runelite.api.ObjectID.UNDERWALL_TUNNEL_16530; +import static net.runelite.api.ObjectID.UNDERWALL_TUNNEL_19032; +import static net.runelite.api.ObjectID.UNDERWALL_TUNNEL_19036; +import static net.runelite.api.ObjectID.VINE_26880; +import static net.runelite.api.ObjectID.VINE_26882; +import static net.runelite.api.ObjectID.WALL_17047; +import static net.runelite.api.ObjectID.WALL_17049; +import static net.runelite.api.ObjectID.WALL_17050; +import static net.runelite.api.ObjectID.WEATHERED_WALL; +import static net.runelite.api.ObjectID.WEATHERED_WALL_16526; import net.runelite.api.coords.WorldPoint; @Getter public enum AgilityShortcut { GENERIC_SHORTCUT(1, "Shortcut", null, - // Trollheim - ROCKS_3790, ROCKS_3791, - // Fremennik Slayer Cave - STEPS_29993, - // Fossil Island - LADDER_30938, LADDER_30939, LADDER_30940, LADDER_30941, RUBBER_CAP_MUSHROOM, - // Brimhaven dungeon - CREVICE_30198, - // Lumbridge - STILE_12982, - // Gu'Tanoth Bridge - GAP, GAP_2831, - // Lumbridge Swamp Caves - STEPPING_STONE_5948, STEPPING_STONE_5949, ROCKS_6673, - // Morytania Pirate Ship - ROCK_16115, - // Lumber Yard - BROKEN_FENCE_2618, - // McGrubor's Wood - LOOSE_RAILING, - // Underwater Area Fossil Island - TUNNEL_30959, HOLE_30966, OBSTACLE, OBSTACLE_30767, OBSTACLE_30964, OBSTACLE_30962, - // Tree Gnome Village - LOOSE_RAILING_2186, - // Burgh de Rott - LOW_FENCE, - // Taverley - STILE, - // Asgarnian Ice Dungeon - STEPS, - // Fossil Island Wyvern Cave - STAIRS_31485), + // Trollheim + ROCKS_3790, ROCKS_3791, + // Fremennik Slayer Cave + STEPS_29993, + // Fossil Island + LADDER_30938, LADDER_30939, LADDER_30940, LADDER_30941, RUBBER_CAP_MUSHROOM, + // Brimhaven dungeon + CREVICE_30198, + // Lumbridge + STILE_12982, + // Gu'Tanoth Bridge + GAP, GAP_2831, + // Lumbridge Swamp Caves + STEPPING_STONE_5948, STEPPING_STONE_5949, ROCKS_6673, + // Morytania Pirate Ship + ROCK_16115, + // Lumber Yard + BROKEN_FENCE_2618, + // McGrubor's Wood + LOOSE_RAILING, + // Underwater Area Fossil Island + TUNNEL_30959, HOLE_30966, OBSTACLE, OBSTACLE_30767, OBSTACLE_30964, OBSTACLE_30962, + // Tree Gnome Village + LOOSE_RAILING_2186, + // Burgh de Rott + LOW_FENCE, + // Taverley + STILE, + // Asgarnian Ice Dungeon + STEPS, + // Fossil Island Wyvern Cave + STAIRS_31485), BRIMHAVEN_DUNGEON_MEDIUM_PIPE_RETURN(1, "Pipe Squeeze", null, new WorldPoint(2698, 9491, 0), PIPE_21727), BRIMHAVEN_DUNGEON_PIPE_RETURN(1, "Pipe Squeeze", null, new WorldPoint(2655, 9573, 0), PIPE_21728), BRIMHAVEN_DUNGEON_STEPPING_STONES_RETURN(1, "Pipe Squeeze", null, STEPPING_STONE_21739), BRIMHAVEN_DUNGEON_LOG_BALANCE_RETURN(1, "Log Balance", null, LOG_BALANCE_20884), AGILITY_PYRAMID_ROCKS_WEST(1, "Rocks", null, CLIMBING_ROCKS_11948), CAIRN_ISLE_CLIMBING_ROCKS(1, "Rocks", null, CLIMBING_ROCKS), - KARAMJA_GLIDER_LOG(1, "Log Balance", new WorldPoint(2906, 3050, 0), A_WOODEN_LOG ), - FALADOR_CRUMBLING_WALL(5, "Crumbling Wall", new WorldPoint(2936, 3357, 0), CRUMBLING_WALL_24222 ), + KARAMJA_GLIDER_LOG(1, "Log Balance", new WorldPoint(2906, 3050, 0), A_WOODEN_LOG), + FALADOR_CRUMBLING_WALL(5, "Crumbling Wall", new WorldPoint(2936, 3357, 0), CRUMBLING_WALL_24222), RIVER_LUM_GRAPPLE_WEST(8, "Grapple Broken Raft", new WorldPoint(3245, 3179, 0), BROKEN_RAFT), RIVER_LUM_GRAPPLE_EAST(8, "Grapple Broken Raft", new WorldPoint(3258, 3179, 0), BROKEN_RAFT), CORSAIR_COVE_ROCKS(10, "Rocks", new WorldPoint(2545, 2871, 0), ROCKS_31757), @@ -84,7 +288,7 @@ public enum AgilityShortcut GOBLIN_VILLAGE_WALL(14, "Wall", new WorldPoint(2925, 3523, 0), TIGHTGAP), CORSAIR_COVE_DUNGEON_PILLAR(15, "Pillar Jump", new WorldPoint(1980, 8996, 0), PILLAR_31809), EDGEVILLE_DUNGEON_MONKEYBARS(15, "Monkey Bars", null, MONKEYBARS_23566), - TROLLHEIM_ROCKS(15, "Rocks", null, new WorldPoint(2838, 3614, 0), ROCKS_3748), // No fixed world map location, but rocks near death plateau have a requirement of 15 + TROLLHEIM_ROCKS(15, "Rocks", null, new WorldPoint(2838, 3614, 0), ROCKS_3748), // No fixed world map location, but rocks near death plateau have a requirement of 15 YANILLE_UNDERWALL_TUNNEL(16, "Underwall Tunnel", new WorldPoint(2574, 3109, 0), HOLE_16520, CASTLE_WALL), YANILLE_WATCHTOWER_TRELLIS(18, "Trellis", null, TRELLIS_20056), COAL_TRUCKS_LOG_BALANCE(20, "Log Balance", new WorldPoint(2598, 3475, 0), LOG_BALANCE_23274), @@ -128,7 +332,7 @@ public enum AgilityShortcut DEEP_WILDERNESS_DUNGEON_CREVICE_SOUTH(46, "Narrow Crevice", new WorldPoint(3045, 10327, 0), CREVICE_19043), TROLLHEIM_HARD_CLIFF_SCRAMBLE(47, "Rocks", new WorldPoint(2902, 3680, 0), ROCKS_16524), FREMENNIK_LOG_BALANCE(48, "Log Balance", new WorldPoint(2721, 3591, 0), LOG_BALANCE_16540, LOG_BALANCE_16541, LOG_BALANCE_16542), - YANILLE_DUNGEON_PIPE_SQUEEZE(49, "Pipe Squeeze", null, OBSTACLE_PIPE_23140), + YANILLE_DUNGEON_PIPE_SQUEEZE(49, "Pipe Squeeze", null, OBSTACLE_PIPE_23140), ARCEUUS_ESSENCE_MINE_BOULDER(49, "Boulder", new WorldPoint(1774, 3888, 0), BOULDER_27990), MORYTANIA_STEPPING_STONE(50, "Stepping Stone", new WorldPoint(3418, 3326, 0), STEPPING_STONE_13504), VARROCK_SEWERS_PIPE_SQUEEZE(51, "Pipe Squeeze", new WorldPoint(3152, 9905, 0), OBSTACLE_PIPE_16511), @@ -141,7 +345,7 @@ public enum AgilityShortcut ISAFDAR_FOREST_OBSTACLES(56, "Trap", null, DENSE_FOREST_3938, DENSE_FOREST_3939, DENSE_FOREST_3998, DENSE_FOREST_3999, DENSE_FOREST, LEAVES, LEAVES_3924, LEAVES_3925, STICKS, TRIPWIRE), RELEKKA_EAST_FENCE(57, "Fence", new WorldPoint(2688, 3697, 0), BROKEN_FENCE), YANILLE_DUNGEON_MONKEY_BARS(57, "Monkey Bars", null, MONKEYBARS_23567), - PHASMATYS_ECTOPOOL_SHORTCUT(58, "Weathered Wall", null , WEATHERED_WALL, WEATHERED_WALL_16526), + PHASMATYS_ECTOPOOL_SHORTCUT(58, "Weathered Wall", null, WEATHERED_WALL, WEATHERED_WALL_16526), ELVEN_OVERPASS_CLIFF_SCRAMBLE(59, "Rocks", new WorldPoint(2345, 3300, 0), ROCKS_16514, ROCKS_16515), WILDERNESS_GWD_CLIMB_EAST(60, "Rocks", new WorldPoint(2943, 3770, 0), ROCKY_HANDHOLDS_26400, ROCKY_HANDHOLDS_26401, ROCKY_HANDHOLDS_26402, ROCKY_HANDHOLDS_26404, ROCKY_HANDHOLDS_26405, ROCKY_HANDHOLDS_26406), WILDERNESS_GWD_CLIMB_WEST(60, "Rocks", new WorldPoint(2928, 3760, 0), ROCKY_HANDHOLDS_26400, ROCKY_HANDHOLDS_26401, ROCKY_HANDHOLDS_26402, ROCKY_HANDHOLDS_26404, ROCKY_HANDHOLDS_26405, ROCKY_HANDHOLDS_26406), @@ -169,22 +373,22 @@ public enum AgilityShortcut TAVERLEY_DUNGEON_PIPE_BLUE_DRAGON(70, "Pipe Squeeze", new WorldPoint(2886, 9798, 0), OBSTACLE_PIPE_16509), TAVERLEY_DUNGEON_ROCKS_NORTH(70, "Rocks", new WorldPoint(2887, 9823, 0), ROCKS, ROCKS_14106), TAVERLEY_DUNGEON_ROCKS_SOUTH(70, "Rocks", new WorldPoint(2887, 9631, 0), ROCKS, ROCKS_14106), - FOSSIL_ISLAND_HARDWOOD_NORTH(70, "Hole" , new WorldPoint(3713, 3827, 0), HOLE_31481, HOLE_31482), - FOSSIL_ISLAND_HARDWOOD_SOUTH(70, "Hole" , new WorldPoint(3715, 3817, 0), HOLE_31481, HOLE_31482), + FOSSIL_ISLAND_HARDWOOD_NORTH(70, "Hole", new WorldPoint(3713, 3827, 0), HOLE_31481, HOLE_31482), + FOSSIL_ISLAND_HARDWOOD_SOUTH(70, "Hole", new WorldPoint(3715, 3817, 0), HOLE_31481, HOLE_31482), AL_KHARID_WINDOW(70, "Window", new WorldPoint(3293, 3158, 0), BROKEN_WALL_33344, BIG_WINDOW), GWD_SARADOMIN_ROPE_NORTH(70, "Rope Descent", new WorldPoint(2912, 5300, 0), NULL_26371), GWD_SARADOMIN_ROPE_SOUTH(70, "Rope Descent", new WorldPoint(2951, 5267, 0), NULL_26375), - SLAYER_TOWER_ADVANCED_CHAIN_FIRST(71, "Spiked Chain (Floor 2)", new WorldPoint(3447, 3578, 0), SPIKEY_CHAIN ), + SLAYER_TOWER_ADVANCED_CHAIN_FIRST(71, "Spiked Chain (Floor 2)", new WorldPoint(3447, 3578, 0), SPIKEY_CHAIN), SLAYER_TOWER_ADVANCED_CHAIN_SECOND(71, "Spiked Chain (Floor 3)", new WorldPoint(3446, 3576, 0), SPIKEY_CHAIN_16538), STRONGHOLD_SLAYER_CAVE_TUNNEL(72, "Tunnel", new WorldPoint(2431, 9806, 0), TUNNEL_30174, TUNNEL_30175), TROLL_STRONGHOLD_WALL_CLIMB(73, "Rocks", new WorldPoint(2841, 3694, 0), ROCKS_16464), - ARCEUUS_ESSENSE_MINE_WEST(73, "Rock Climb", new WorldPoint(1742, 3853, 0), ROCKS_27984, ROCKS_27985 ), + ARCEUUS_ESSENSE_MINE_WEST(73, "Rock Climb", new WorldPoint(1742, 3853, 0), ROCKS_27984, ROCKS_27985), LAVA_DRAGON_ISLE_JUMP(74, "Stepping Stone", new WorldPoint(3200, 3807, 0), STEPPING_STONE_14918), REVENANT_CAVES_DEMONS_JUMP(75, "Jump", new WorldPoint(3199, 10135, 0), PILLAR_31561), REVENANT_CAVES_ANKOU_EAST(75, "Jump", new WorldPoint(3201, 10195, 0), PILLAR_31561), REVENANT_CAVES_ANKOU_NORTH(75, "Jump", new WorldPoint(3180, 10209, 0), PILLAR_31561), ZUL_ANDRA_ISLAND_CROSSING(76, "Stepping Stone", new WorldPoint(2156, 3073, 0), STEPPING_STONE_10663), - SHILO_VILLAGE_STEPPING_STONES( 77, "Stepping Stones", new WorldPoint(2863, 2974, 0), STEPPING_STONE_16466), + SHILO_VILLAGE_STEPPING_STONES(77, "Stepping Stones", new WorldPoint(2863, 2974, 0), STEPPING_STONE_16466), KHARAZI_JUNGLE_VINE_CLIMB(79, "Vine", new WorldPoint(2897, 2939, 0), NULL_26884, NULL_26886), TAVERLEY_DUNGEON_SPIKED_BLADES(80, "Strange Floor", new WorldPoint(2877, 9813, 0), STRANGE_FLOOR), SLAYER_DUNGEON_CHASM_JUMP(81, "Spiked Blades", new WorldPoint(2770, 10003, 0), STRANGE_FLOOR_16544), diff --git a/runelite-client/src/main/java/net/runelite/client/game/AsyncBufferedImage.java b/runelite-client/src/main/java/net/runelite/client/game/AsyncBufferedImage.java index 0290c7856a..c4c9a66df7 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/AsyncBufferedImage.java +++ b/runelite-client/src/main/java/net/runelite/client/game/AsyncBufferedImage.java @@ -1,84 +1,85 @@ -/* - * Copyright (c) 2018 Abex - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package net.runelite.client.game; - -import java.awt.image.BufferedImage; -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.JLabel; - -public class AsyncBufferedImage extends BufferedImage -{ - private final List listeners = new CopyOnWriteArrayList<>(); - public AsyncBufferedImage(int width, int height, int imageType) - { - super(width, height, imageType); - } - - /** - * Call when the buffer has been changed - */ - public void changed() - { - for (Runnable r : listeners) - { - r.run(); - } - } - - /** - * Register a function to be ran when the buffer has changed - */ - public void onChanged(Runnable r) - { - listeners.add(r); - } - - /** - * Calls setIcon on c, ensuring it is repainted when this changes - */ - public void addTo(JButton c) - { - c.setIcon(makeIcon(c)); - } - - /** - * Calls setIcon on c, ensuring it is repainted when this changes - */ - public void addTo(JLabel c) - { - c.setIcon(makeIcon(c)); - } - - private ImageIcon makeIcon(JComponent c) - { - listeners.add(c::repaint); - return new ImageIcon(this); - } -} +/* + * Copyright (c) 2018 Abex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package net.runelite.client.game; + +import java.awt.image.BufferedImage; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JLabel; + +public class AsyncBufferedImage extends BufferedImage +{ + private final List listeners = new CopyOnWriteArrayList<>(); + + public AsyncBufferedImage(int width, int height, int imageType) + { + super(width, height, imageType); + } + + /** + * Call when the buffer has been changed + */ + public void changed() + { + for (Runnable r : listeners) + { + r.run(); + } + } + + /** + * Register a function to be ran when the buffer has changed + */ + public void onChanged(Runnable r) + { + listeners.add(r); + } + + /** + * Calls setIcon on c, ensuring it is repainted when this changes + */ + public void addTo(JButton c) + { + c.setIcon(makeIcon(c)); + } + + /** + * Calls setIcon on c, ensuring it is repainted when this changes + */ + public void addTo(JLabel c) + { + c.setIcon(makeIcon(c)); + } + + private ImageIcon makeIcon(JComponent c) + { + listeners.add(c::repaint); + return new ImageIcon(this); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/game/ItemManager.java b/runelite-client/src/main/java/net/runelite/client/game/ItemManager.java index 0f21a5b434..a8f7200568 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/ItemManager.java +++ b/runelite-client/src/main/java/net/runelite/client/game/ItemManager.java @@ -1,475 +1,586 @@ -/* - * Copyright (c) 2017, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.game; - -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import com.google.common.collect.ImmutableMap; -import java.awt.Color; -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import javax.annotation.Nullable; -import javax.inject.Inject; -import javax.inject.Singleton; -import lombok.Value; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.Client; -import static net.runelite.api.Constants.CLIENT_DEFAULT_ZOOM; -import net.runelite.api.GameState; -import net.runelite.api.ItemComposition; -import net.runelite.api.ItemID; -import static net.runelite.api.ItemID.*; -import net.runelite.api.SpritePixels; -import net.runelite.api.events.GameStateChanged; -import net.runelite.api.events.PostItemComposition; -import net.runelite.client.callback.ClientThread; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.http.api.item.ItemClient; -import net.runelite.http.api.item.ItemPrice; -import net.runelite.http.api.item.ItemStats; - -@Singleton -@Slf4j -public class ItemManager -{ - @Value - private static class ImageKey - { - private final int itemId; - private final int itemQuantity; - private final boolean stackable; - } - - @Value - private static class OutlineKey - { - private final int itemId; - private final int itemQuantity; - private final Color outlineColor; - } - - private final Client client; - private final ScheduledExecutorService scheduledExecutorService; - private final ClientThread clientThread; - - private final ItemClient itemClient = new ItemClient(); - private Map itemPrices = Collections.emptyMap(); - private Map itemStats = Collections.emptyMap(); - private final LoadingCache itemImages; - private final LoadingCache itemCompositions; - private final LoadingCache itemOutlines; - - // Worn items with weight reducing property have a different worn and inventory ItemID - private static final ImmutableMap WORN_ITEMS = ImmutableMap.builder(). - put(BOOTS_OF_LIGHTNESS_89, BOOTS_OF_LIGHTNESS). - put(PENANCE_GLOVES_10554, PENANCE_GLOVES). - - put(GRACEFUL_HOOD_11851, GRACEFUL_HOOD). - put(GRACEFUL_CAPE_11853, GRACEFUL_CAPE). - put(GRACEFUL_TOP_11855, GRACEFUL_TOP). - put(GRACEFUL_LEGS_11857, GRACEFUL_LEGS). - put(GRACEFUL_GLOVES_11859, GRACEFUL_GLOVES). - put(GRACEFUL_BOOTS_11861, GRACEFUL_BOOTS). - put(GRACEFUL_HOOD_13580, GRACEFUL_HOOD_13579). - put(GRACEFUL_CAPE_13582, GRACEFUL_CAPE_13581). - put(GRACEFUL_TOP_13584, GRACEFUL_TOP_13583). - put(GRACEFUL_LEGS_13586, GRACEFUL_LEGS_13585). - put(GRACEFUL_GLOVES_13588, GRACEFUL_GLOVES_13587). - put(GRACEFUL_BOOTS_13590, GRACEFUL_BOOTS_13589). - put(GRACEFUL_HOOD_13592, GRACEFUL_HOOD_13591). - put(GRACEFUL_CAPE_13594, GRACEFUL_CAPE_13593). - put(GRACEFUL_TOP_13596, GRACEFUL_TOP_13595). - put(GRACEFUL_LEGS_13598, GRACEFUL_LEGS_13597). - put(GRACEFUL_GLOVES_13600, GRACEFUL_GLOVES_13599). - put(GRACEFUL_BOOTS_13602, GRACEFUL_BOOTS_13601). - put(GRACEFUL_HOOD_13604, GRACEFUL_HOOD_13603). - put(GRACEFUL_CAPE_13606, GRACEFUL_CAPE_13605). - put(GRACEFUL_TOP_13608, GRACEFUL_TOP_13607). - put(GRACEFUL_LEGS_13610, GRACEFUL_LEGS_13609). - put(GRACEFUL_GLOVES_13612, GRACEFUL_GLOVES_13611). - put(GRACEFUL_BOOTS_13614, GRACEFUL_BOOTS_13613). - put(GRACEFUL_HOOD_13616, GRACEFUL_HOOD_13615). - put(GRACEFUL_CAPE_13618, GRACEFUL_CAPE_13617). - put(GRACEFUL_TOP_13620, GRACEFUL_TOP_13619). - put(GRACEFUL_LEGS_13622, GRACEFUL_LEGS_13621). - put(GRACEFUL_GLOVES_13624, GRACEFUL_GLOVES_13623). - put(GRACEFUL_BOOTS_13626, GRACEFUL_BOOTS_13625). - put(GRACEFUL_HOOD_13628, GRACEFUL_HOOD_13627). - put(GRACEFUL_CAPE_13630, GRACEFUL_CAPE_13629). - put(GRACEFUL_TOP_13632, GRACEFUL_TOP_13631). - put(GRACEFUL_LEGS_13634, GRACEFUL_LEGS_13633). - put(GRACEFUL_GLOVES_13636, GRACEFUL_GLOVES_13635). - put(GRACEFUL_BOOTS_13638, GRACEFUL_BOOTS_13637). - put(GRACEFUL_HOOD_13668, GRACEFUL_HOOD_13667). - put(GRACEFUL_CAPE_13670, GRACEFUL_CAPE_13669). - put(GRACEFUL_TOP_13672, GRACEFUL_TOP_13671). - put(GRACEFUL_LEGS_13674, GRACEFUL_LEGS_13673). - put(GRACEFUL_GLOVES_13676, GRACEFUL_GLOVES_13675). - put(GRACEFUL_BOOTS_13678, GRACEFUL_BOOTS_13677). - put(GRACEFUL_HOOD_21063, GRACEFUL_HOOD_21061). - put(GRACEFUL_CAPE_21066, GRACEFUL_CAPE_21064). - put(GRACEFUL_TOP_21069, GRACEFUL_TOP_21067). - put(GRACEFUL_LEGS_21072, GRACEFUL_LEGS_21070). - put(GRACEFUL_GLOVES_21075, GRACEFUL_GLOVES_21073). - put(GRACEFUL_BOOTS_21078, GRACEFUL_BOOTS_21076). - - put(MAX_CAPE_13342, MAX_CAPE). - - put(SPOTTED_CAPE_10073, SPOTTED_CAPE). - put(SPOTTIER_CAPE_10074, SPOTTIER_CAPE). - - put(AGILITY_CAPET_13341, AGILITY_CAPET). - put(AGILITY_CAPE_13340, AGILITY_CAPE). - build(); - - @Inject - public ItemManager(Client client, ScheduledExecutorService executor, ClientThread clientThread) - { - this.client = client; - this.scheduledExecutorService = executor; - this.clientThread = clientThread; - - scheduledExecutorService.scheduleWithFixedDelay(this::loadPrices, 0, 30, TimeUnit.MINUTES); - scheduledExecutorService.submit(this::loadStats); - - itemImages = CacheBuilder.newBuilder() - .maximumSize(128L) - .expireAfterAccess(1, TimeUnit.HOURS) - .build(new CacheLoader() - { - @Override - public AsyncBufferedImage load(ImageKey key) throws Exception - { - return loadImage(key.itemId, key.itemQuantity, key.stackable); - } - }); - - itemCompositions = CacheBuilder.newBuilder() - .maximumSize(1024L) - .expireAfterAccess(1, TimeUnit.HOURS) - .build(new CacheLoader() - { - @Override - public ItemComposition load(Integer key) throws Exception - { - return client.getItemDefinition(key); - } - }); - - itemOutlines = CacheBuilder.newBuilder() - .maximumSize(128L) - .expireAfterAccess(1, TimeUnit.HOURS) - .build(new CacheLoader() - { - @Override - public BufferedImage load(OutlineKey key) throws Exception - { - return loadItemOutline(key.itemId, key.itemQuantity, key.outlineColor); - } - }); - } - - private void loadPrices() - { - try - { - ItemPrice[] prices = itemClient.getPrices(); - if (prices != null) - { - ImmutableMap.Builder map = ImmutableMap.builderWithExpectedSize(prices.length); - for (ItemPrice price : prices) - { - map.put(price.getId(), price); - } - itemPrices = map.build(); - } - - log.debug("Loaded {} prices", itemPrices.size()); - } - catch (IOException e) - { - log.warn("error loading prices!", e); - } - } - - private void loadStats() - { - try - { - final Map stats = itemClient.getStats(); - if (stats != null) - { - itemStats = ImmutableMap.copyOf(stats); - } - - log.debug("Loaded {} stats", itemStats.size()); - } - catch (IOException e) - { - log.warn("error loading stats!", e); - } - } - - - @Subscribe - public void onGameStateChanged(final GameStateChanged event) - { - if (event.getGameState() == GameState.HOPPING || event.getGameState() == GameState.LOGIN_SCREEN) - { - itemCompositions.invalidateAll(); - } - } - - @Subscribe - public void onPostItemComposition(PostItemComposition event) - { - itemCompositions.put(event.getItemComposition().getId(), event.getItemComposition()); - } - - /** - * Invalidates internal item manager item composition cache (but not client item composition cache) - * @see Client#getItemCompositionCache() - */ - public void invalidateItemCompositionCache() - { - itemCompositions.invalidateAll(); - } - - /** - * Look up an item's price - * - * @param itemID item id - * @return item price - */ - public int getItemPrice(int itemID) - { - if (itemID == ItemID.COINS_995) - { - return 1; - } - if (itemID == ItemID.PLATINUM_TOKEN) - { - return 1000; - } - - UntradeableItemMapping p = UntradeableItemMapping.map(ItemVariationMapping.map(itemID)); - if (p != null) - { - return getItemPrice(p.getPriceID()) * p.getQuantity(); - } - - int price = 0; - for (int mappedID : ItemMapping.map(itemID)) - { - ItemPrice ip = itemPrices.get(mappedID); - if (ip != null) - { - price += ip.getPrice(); - } - } - - return price; - } - - /** - * Look up an item's stats - * @param itemId item id - * @return item stats - */ - @Nullable - public ItemStats getItemStats(int itemId, boolean allowNote) - { - ItemComposition itemComposition = getItemComposition(itemId); - - if (itemComposition == null || itemComposition.getName() == null || (!allowNote && itemComposition.getNote() != -1)) - { - return null; - } - - return itemStats.get(canonicalize(itemId)); - } - - /** - * Search for tradeable items based on item name - * - * @param itemName item name - * @return - */ - public List search(String itemName) - { - itemName = itemName.toLowerCase(); - - List result = new ArrayList<>(); - for (ItemPrice itemPrice : itemPrices.values()) - { - final String name = itemPrice.getName(); - if (name.toLowerCase().contains(itemName)) - { - result.add(itemPrice); - } - } - return result; - } - - /** - * Look up an item's composition - * - * @param itemId item id - * @return item composition - */ - public ItemComposition getItemComposition(int itemId) - { - assert client.isClientThread() : "getItemComposition must be called on client thread"; - return itemCompositions.getUnchecked(itemId); - } - - /** - * Get an item's un-noted, un-placeholdered ID - */ - public int canonicalize(int itemID) - { - ItemComposition itemComposition = getItemComposition(itemID); - - if (itemComposition.getNote() != -1) - { - return itemComposition.getLinkedNoteId(); - } - - if (itemComposition.getPlaceholderTemplateId() != -1) - { - return itemComposition.getPlaceholderId(); - } - - return WORN_ITEMS.getOrDefault(itemID, itemID); - } - - /** - * Loads item sprite from game, makes transparent, and generates image - * - * @param itemId - * @return - */ - private AsyncBufferedImage loadImage(int itemId, int quantity, boolean stackable) - { - AsyncBufferedImage img = new AsyncBufferedImage(36, 32, BufferedImage.TYPE_INT_ARGB); - clientThread.invoke(() -> - { - if (client.getGameState().ordinal() < GameState.LOGIN_SCREEN.ordinal()) - { - return false; - } - SpritePixels sprite = client.createItemSprite(itemId, quantity, 1, SpritePixels.DEFAULT_SHADOW_COLOR, - stackable ? 1 : 0, false, CLIENT_DEFAULT_ZOOM); - if (sprite == null) - { - return false; - } - sprite.toBufferedImage(img); - img.changed(); - return true; - }); - return img; - } - - /** - * Get item sprite image as BufferedImage. - *

- * This method may return immediately with a blank image if not called on the game thread. - * The image will be filled in later. If this is used for a UI label/button, it should be added - * using AsyncBufferedImage::addTo to ensure it is painted properly - * - * @param itemId - * @return - */ - public AsyncBufferedImage getImage(int itemId) - { - return getImage(itemId, 1, false); - } - - /** - * Get item sprite image as BufferedImage. - *

- * This method may return immediately with a blank image if not called on the game thread. - * The image will be filled in later. If this is used for a UI label/button, it should be added - * using AsyncBufferedImage::addTo to ensure it is painted properly - * - * @param itemId - * @param quantity - * @return - */ - public AsyncBufferedImage getImage(int itemId, int quantity, boolean stackable) - { - try - { - return itemImages.get(new ImageKey(itemId, quantity, stackable)); - } - catch (ExecutionException ex) - { - return null; - } - } - - /** - * Create item sprite and applies an outline. - * - * @param itemId item id - * @param itemQuantity item quantity - * @param outlineColor outline color - * @return image - */ - private BufferedImage loadItemOutline(final int itemId, final int itemQuantity, final Color outlineColor) - { - final SpritePixels itemSprite = client.createItemSprite(itemId, itemQuantity, 1, 0, 0, true, 710); - return itemSprite.toBufferedOutline(outlineColor); - } - - /** - * Get item outline with a specific color. - * - * @param itemId item id - * @param itemQuantity item quantity - * @param outlineColor outline color - * @return image - */ - public BufferedImage getItemOutline(final int itemId, final int itemQuantity, final Color outlineColor) - { - try - { - return itemOutlines.get(new OutlineKey(itemId, itemQuantity, outlineColor)); - } - catch (ExecutionException e) - { - return null; - } - } -} +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.game; + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.ImmutableMap; +import java.awt.Color; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; +import javax.inject.Inject; +import javax.inject.Singleton; +import lombok.Value; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import static net.runelite.api.Constants.CLIENT_DEFAULT_ZOOM; +import net.runelite.api.GameState; +import net.runelite.api.ItemComposition; +import net.runelite.api.ItemID; +import static net.runelite.api.ItemID.AGILITY_CAPE; +import static net.runelite.api.ItemID.AGILITY_CAPET; +import static net.runelite.api.ItemID.AGILITY_CAPET_13341; +import static net.runelite.api.ItemID.AGILITY_CAPE_13340; +import static net.runelite.api.ItemID.BOOTS_OF_LIGHTNESS; +import static net.runelite.api.ItemID.BOOTS_OF_LIGHTNESS_89; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_11861; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13589; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13590; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13601; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13602; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13613; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13614; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13625; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13626; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13637; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13638; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13677; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_13678; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_21076; +import static net.runelite.api.ItemID.GRACEFUL_BOOTS_21078; +import static net.runelite.api.ItemID.GRACEFUL_CAPE; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_11853; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13581; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13582; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13593; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13594; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13605; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13606; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13617; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13618; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13629; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13630; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13669; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_13670; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_21064; +import static net.runelite.api.ItemID.GRACEFUL_CAPE_21066; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_11859; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13587; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13588; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13599; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13600; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13611; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13612; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13623; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13624; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13635; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13636; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13675; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_13676; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_21073; +import static net.runelite.api.ItemID.GRACEFUL_GLOVES_21075; +import static net.runelite.api.ItemID.GRACEFUL_HOOD; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_11851; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13579; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13580; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13591; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13592; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13603; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13604; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13615; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13616; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13627; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13628; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13667; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_13668; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_21061; +import static net.runelite.api.ItemID.GRACEFUL_HOOD_21063; +import static net.runelite.api.ItemID.GRACEFUL_LEGS; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_11857; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13585; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13586; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13597; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13598; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13609; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13610; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13621; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13622; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13633; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13634; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13673; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_13674; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_21070; +import static net.runelite.api.ItemID.GRACEFUL_LEGS_21072; +import static net.runelite.api.ItemID.GRACEFUL_TOP; +import static net.runelite.api.ItemID.GRACEFUL_TOP_11855; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13583; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13584; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13595; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13596; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13607; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13608; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13619; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13620; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13631; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13632; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13671; +import static net.runelite.api.ItemID.GRACEFUL_TOP_13672; +import static net.runelite.api.ItemID.GRACEFUL_TOP_21067; +import static net.runelite.api.ItemID.GRACEFUL_TOP_21069; +import static net.runelite.api.ItemID.MAX_CAPE; +import static net.runelite.api.ItemID.MAX_CAPE_13342; +import static net.runelite.api.ItemID.PENANCE_GLOVES; +import static net.runelite.api.ItemID.PENANCE_GLOVES_10554; +import static net.runelite.api.ItemID.SPOTTED_CAPE; +import static net.runelite.api.ItemID.SPOTTED_CAPE_10073; +import static net.runelite.api.ItemID.SPOTTIER_CAPE; +import static net.runelite.api.ItemID.SPOTTIER_CAPE_10074; +import net.runelite.api.SpritePixels; +import net.runelite.api.events.GameStateChanged; +import net.runelite.api.events.PostItemComposition; +import net.runelite.client.callback.ClientThread; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.http.api.item.ItemClient; +import net.runelite.http.api.item.ItemPrice; +import net.runelite.http.api.item.ItemStats; + +@Singleton +@Slf4j +public class ItemManager +{ + @Value + private static class ImageKey + { + private final int itemId; + private final int itemQuantity; + private final boolean stackable; + } + + @Value + private static class OutlineKey + { + private final int itemId; + private final int itemQuantity; + private final Color outlineColor; + } + + private final Client client; + private final ScheduledExecutorService scheduledExecutorService; + private final ClientThread clientThread; + + private final ItemClient itemClient = new ItemClient(); + private Map itemPrices = Collections.emptyMap(); + private Map itemStats = Collections.emptyMap(); + private final LoadingCache itemImages; + private final LoadingCache itemCompositions; + private final LoadingCache itemOutlines; + + // Worn items with weight reducing property have a different worn and inventory ItemID + private static final ImmutableMap WORN_ITEMS = ImmutableMap.builder(). + put(BOOTS_OF_LIGHTNESS_89, BOOTS_OF_LIGHTNESS). + put(PENANCE_GLOVES_10554, PENANCE_GLOVES). + + put(GRACEFUL_HOOD_11851, GRACEFUL_HOOD). + put(GRACEFUL_CAPE_11853, GRACEFUL_CAPE). + put(GRACEFUL_TOP_11855, GRACEFUL_TOP). + put(GRACEFUL_LEGS_11857, GRACEFUL_LEGS). + put(GRACEFUL_GLOVES_11859, GRACEFUL_GLOVES). + put(GRACEFUL_BOOTS_11861, GRACEFUL_BOOTS). + put(GRACEFUL_HOOD_13580, GRACEFUL_HOOD_13579). + put(GRACEFUL_CAPE_13582, GRACEFUL_CAPE_13581). + put(GRACEFUL_TOP_13584, GRACEFUL_TOP_13583). + put(GRACEFUL_LEGS_13586, GRACEFUL_LEGS_13585). + put(GRACEFUL_GLOVES_13588, GRACEFUL_GLOVES_13587). + put(GRACEFUL_BOOTS_13590, GRACEFUL_BOOTS_13589). + put(GRACEFUL_HOOD_13592, GRACEFUL_HOOD_13591). + put(GRACEFUL_CAPE_13594, GRACEFUL_CAPE_13593). + put(GRACEFUL_TOP_13596, GRACEFUL_TOP_13595). + put(GRACEFUL_LEGS_13598, GRACEFUL_LEGS_13597). + put(GRACEFUL_GLOVES_13600, GRACEFUL_GLOVES_13599). + put(GRACEFUL_BOOTS_13602, GRACEFUL_BOOTS_13601). + put(GRACEFUL_HOOD_13604, GRACEFUL_HOOD_13603). + put(GRACEFUL_CAPE_13606, GRACEFUL_CAPE_13605). + put(GRACEFUL_TOP_13608, GRACEFUL_TOP_13607). + put(GRACEFUL_LEGS_13610, GRACEFUL_LEGS_13609). + put(GRACEFUL_GLOVES_13612, GRACEFUL_GLOVES_13611). + put(GRACEFUL_BOOTS_13614, GRACEFUL_BOOTS_13613). + put(GRACEFUL_HOOD_13616, GRACEFUL_HOOD_13615). + put(GRACEFUL_CAPE_13618, GRACEFUL_CAPE_13617). + put(GRACEFUL_TOP_13620, GRACEFUL_TOP_13619). + put(GRACEFUL_LEGS_13622, GRACEFUL_LEGS_13621). + put(GRACEFUL_GLOVES_13624, GRACEFUL_GLOVES_13623). + put(GRACEFUL_BOOTS_13626, GRACEFUL_BOOTS_13625). + put(GRACEFUL_HOOD_13628, GRACEFUL_HOOD_13627). + put(GRACEFUL_CAPE_13630, GRACEFUL_CAPE_13629). + put(GRACEFUL_TOP_13632, GRACEFUL_TOP_13631). + put(GRACEFUL_LEGS_13634, GRACEFUL_LEGS_13633). + put(GRACEFUL_GLOVES_13636, GRACEFUL_GLOVES_13635). + put(GRACEFUL_BOOTS_13638, GRACEFUL_BOOTS_13637). + put(GRACEFUL_HOOD_13668, GRACEFUL_HOOD_13667). + put(GRACEFUL_CAPE_13670, GRACEFUL_CAPE_13669). + put(GRACEFUL_TOP_13672, GRACEFUL_TOP_13671). + put(GRACEFUL_LEGS_13674, GRACEFUL_LEGS_13673). + put(GRACEFUL_GLOVES_13676, GRACEFUL_GLOVES_13675). + put(GRACEFUL_BOOTS_13678, GRACEFUL_BOOTS_13677). + put(GRACEFUL_HOOD_21063, GRACEFUL_HOOD_21061). + put(GRACEFUL_CAPE_21066, GRACEFUL_CAPE_21064). + put(GRACEFUL_TOP_21069, GRACEFUL_TOP_21067). + put(GRACEFUL_LEGS_21072, GRACEFUL_LEGS_21070). + put(GRACEFUL_GLOVES_21075, GRACEFUL_GLOVES_21073). + put(GRACEFUL_BOOTS_21078, GRACEFUL_BOOTS_21076). + + put(MAX_CAPE_13342, MAX_CAPE). + + put(SPOTTED_CAPE_10073, SPOTTED_CAPE). + put(SPOTTIER_CAPE_10074, SPOTTIER_CAPE). + + put(AGILITY_CAPET_13341, AGILITY_CAPET). + put(AGILITY_CAPE_13340, AGILITY_CAPE). + build(); + + @Inject + public ItemManager(Client client, ScheduledExecutorService executor, ClientThread clientThread) + { + this.client = client; + this.scheduledExecutorService = executor; + this.clientThread = clientThread; + + scheduledExecutorService.scheduleWithFixedDelay(this::loadPrices, 0, 30, TimeUnit.MINUTES); + scheduledExecutorService.submit(this::loadStats); + + itemImages = CacheBuilder.newBuilder() + .maximumSize(128L) + .expireAfterAccess(1, TimeUnit.HOURS) + .build(new CacheLoader() + { + @Override + public AsyncBufferedImage load(ImageKey key) throws Exception + { + return loadImage(key.itemId, key.itemQuantity, key.stackable); + } + }); + + itemCompositions = CacheBuilder.newBuilder() + .maximumSize(1024L) + .expireAfterAccess(1, TimeUnit.HOURS) + .build(new CacheLoader() + { + @Override + public ItemComposition load(Integer key) throws Exception + { + return client.getItemDefinition(key); + } + }); + + itemOutlines = CacheBuilder.newBuilder() + .maximumSize(128L) + .expireAfterAccess(1, TimeUnit.HOURS) + .build(new CacheLoader() + { + @Override + public BufferedImage load(OutlineKey key) throws Exception + { + return loadItemOutline(key.itemId, key.itemQuantity, key.outlineColor); + } + }); + } + + private void loadPrices() + { + try + { + ItemPrice[] prices = itemClient.getPrices(); + if (prices != null) + { + ImmutableMap.Builder map = ImmutableMap.builderWithExpectedSize(prices.length); + for (ItemPrice price : prices) + { + map.put(price.getId(), price); + } + itemPrices = map.build(); + } + + log.debug("Loaded {} prices", itemPrices.size()); + } + catch (IOException e) + { + log.warn("error loading prices!", e); + } + } + + private void loadStats() + { + try + { + final Map stats = itemClient.getStats(); + if (stats != null) + { + itemStats = ImmutableMap.copyOf(stats); + } + + log.debug("Loaded {} stats", itemStats.size()); + } + catch (IOException e) + { + log.warn("error loading stats!", e); + } + } + + + @Subscribe + public void onGameStateChanged(final GameStateChanged event) + { + if (event.getGameState() == GameState.HOPPING || event.getGameState() == GameState.LOGIN_SCREEN) + { + itemCompositions.invalidateAll(); + } + } + + @Subscribe + public void onPostItemComposition(PostItemComposition event) + { + itemCompositions.put(event.getItemComposition().getId(), event.getItemComposition()); + } + + /** + * Invalidates internal item manager item composition cache (but not client item composition cache) + * + * @see Client#getItemCompositionCache() + */ + public void invalidateItemCompositionCache() + { + itemCompositions.invalidateAll(); + } + + /** + * Look up an item's price + * + * @param itemID item id + * @return item price + */ + public int getItemPrice(int itemID) + { + if (itemID == ItemID.COINS_995) + { + return 1; + } + if (itemID == ItemID.PLATINUM_TOKEN) + { + return 1000; + } + + UntradeableItemMapping p = UntradeableItemMapping.map(ItemVariationMapping.map(itemID)); + if (p != null) + { + return getItemPrice(p.getPriceID()) * p.getQuantity(); + } + + int price = 0; + for (int mappedID : ItemMapping.map(itemID)) + { + ItemPrice ip = itemPrices.get(mappedID); + if (ip != null) + { + price += ip.getPrice(); + } + } + + return price; + } + + /** + * Look up an item's stats + * + * @param itemId item id + * @return item stats + */ + @Nullable + public ItemStats getItemStats(int itemId, boolean allowNote) + { + ItemComposition itemComposition = getItemComposition(itemId); + + if (itemComposition == null || itemComposition.getName() == null || (!allowNote && itemComposition.getNote() != -1)) + { + return null; + } + + return itemStats.get(canonicalize(itemId)); + } + + /** + * Search for tradeable items based on item name + * + * @param itemName item name + * @return + */ + public List search(String itemName) + { + itemName = itemName.toLowerCase(); + + List result = new ArrayList<>(); + for (ItemPrice itemPrice : itemPrices.values()) + { + final String name = itemPrice.getName(); + if (name.toLowerCase().contains(itemName)) + { + result.add(itemPrice); + } + } + return result; + } + + /** + * Look up an item's composition + * + * @param itemId item id + * @return item composition + */ + public ItemComposition getItemComposition(int itemId) + { + assert client.isClientThread() : "getItemComposition must be called on client thread"; + return itemCompositions.getUnchecked(itemId); + } + + /** + * Get an item's un-noted, un-placeholdered ID + */ + public int canonicalize(int itemID) + { + ItemComposition itemComposition = getItemComposition(itemID); + + if (itemComposition.getNote() != -1) + { + return itemComposition.getLinkedNoteId(); + } + + if (itemComposition.getPlaceholderTemplateId() != -1) + { + return itemComposition.getPlaceholderId(); + } + + return WORN_ITEMS.getOrDefault(itemID, itemID); + } + + /** + * Loads item sprite from game, makes transparent, and generates image + * + * @param itemId + * @return + */ + private AsyncBufferedImage loadImage(int itemId, int quantity, boolean stackable) + { + AsyncBufferedImage img = new AsyncBufferedImage(36, 32, BufferedImage.TYPE_INT_ARGB); + clientThread.invoke(() -> + { + if (client.getGameState().ordinal() < GameState.LOGIN_SCREEN.ordinal()) + { + return false; + } + SpritePixels sprite = client.createItemSprite(itemId, quantity, 1, SpritePixels.DEFAULT_SHADOW_COLOR, + stackable ? 1 : 0, false, CLIENT_DEFAULT_ZOOM); + if (sprite == null) + { + return false; + } + sprite.toBufferedImage(img); + img.changed(); + return true; + }); + return img; + } + + /** + * Get item sprite image as BufferedImage. + *

+ * This method may return immediately with a blank image if not called on the game thread. + * The image will be filled in later. If this is used for a UI label/button, it should be added + * using AsyncBufferedImage::addTo to ensure it is painted properly + * + * @param itemId + * @return + */ + public AsyncBufferedImage getImage(int itemId) + { + return getImage(itemId, 1, false); + } + + /** + * Get item sprite image as BufferedImage. + *

+ * This method may return immediately with a blank image if not called on the game thread. + * The image will be filled in later. If this is used for a UI label/button, it should be added + * using AsyncBufferedImage::addTo to ensure it is painted properly + * + * @param itemId + * @param quantity + * @return + */ + public AsyncBufferedImage getImage(int itemId, int quantity, boolean stackable) + { + try + { + return itemImages.get(new ImageKey(itemId, quantity, stackable)); + } + catch (ExecutionException ex) + { + return null; + } + } + + /** + * Create item sprite and applies an outline. + * + * @param itemId item id + * @param itemQuantity item quantity + * @param outlineColor outline color + * @return image + */ + private BufferedImage loadItemOutline(final int itemId, final int itemQuantity, final Color outlineColor) + { + final SpritePixels itemSprite = client.createItemSprite(itemId, itemQuantity, 1, 0, 0, true, 710); + return itemSprite.toBufferedOutline(outlineColor); + } + + /** + * Get item outline with a specific color. + * + * @param itemId item id + * @param itemQuantity item quantity + * @param outlineColor outline color + * @return image + */ + public BufferedImage getItemOutline(final int itemId, final int itemQuantity, final Color outlineColor) + { + try + { + return itemOutlines.get(new OutlineKey(itemId, itemQuantity, outlineColor)); + } + catch (ExecutionException e) + { + return null; + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/game/ItemMapping.java b/runelite-client/src/main/java/net/runelite/client/game/ItemMapping.java index 22eed36031..b0e70bcd49 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/ItemMapping.java +++ b/runelite-client/src/main/java/net/runelite/client/game/ItemMapping.java @@ -1,271 +1,675 @@ -/* - * Copyright (c) 2018, Tomas Slusny - * Copyright (c) 2018, Seth - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.game; - -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Multimap; -import java.util.Collection; -import java.util.Collections; -import static net.runelite.api.ItemID.*; - -/** - * Converts untradeable items to it's tradeable counterparts - */ -public enum ItemMapping -{ - // Barrows equipment - ITEM_AHRIMS_HOOD(AHRIMS_HOOD, AHRIMS_HOOD_25, AHRIMS_HOOD_50, AHRIMS_HOOD_75, AHRIMS_HOOD_100), - ITEM_AHRIMS_ROBETOP(AHRIMS_ROBETOP, AHRIMS_ROBETOP_25, AHRIMS_ROBETOP_50, AHRIMS_ROBETOP_75, AHRIMS_ROBETOP_100), - ITEM_AHRIMS_ROBEBOTTOM(AHRIMS_ROBESKIRT, AHRIMS_ROBESKIRT_25, AHRIMS_ROBESKIRT_50, AHRIMS_ROBESKIRT_75, AHRIMS_ROBESKIRT_100), - ITEM_AHRIMS_STAFF(AHRIMS_STAFF, AHRIMS_STAFF_25, AHRIMS_STAFF_50, AHRIMS_STAFF_75, AHRIMS_STAFF_100), - ITEM_KARILS_COIF(KARILS_COIF, KARILS_COIF_25, KARILS_COIF_50, KARILS_COIF_75, KARILS_COIF_100), - ITEM_KARILS_LEATHERTOP(KARILS_LEATHERTOP, KARILS_LEATHERTOP_25, KARILS_LEATHERTOP_50, KARILS_LEATHERTOP_75, KARILS_LEATHERTOP_100), - ITEM_KARILS_LEATHERSKIRT(KARILS_LEATHERSKIRT, KARILS_LEATHERSKIRT_25, KARILS_LEATHERSKIRT_50, KARILS_LEATHERSKIRT_75, KARILS_LEATHERSKIRT_100), - ITEM_KARILS_CROSSBOW(KARILS_CROSSBOW, KARILS_CROSSBOW_25, KARILS_CROSSBOW_50, KARILS_CROSSBOW_75, KARILS_CROSSBOW_100), - ITEM_DHAROKS_HELM(DHAROKS_HELM, DHAROKS_HELM_25, DHAROKS_HELM_50, DHAROKS_HELM_75, DHAROKS_HELM_100), - ITEM_DHAROKS_PLATEBODY(DHAROKS_PLATEBODY, DHAROKS_PLATEBODY_25, DHAROKS_PLATEBODY_50, DHAROKS_PLATEBODY_75, DHAROKS_PLATEBODY_100), - ITEM_DHAROKS_PLATELEGS(DHAROKS_PLATELEGS, DHAROKS_PLATELEGS_25, DHAROKS_PLATELEGS_50, DHAROKS_PLATELEGS_75, DHAROKS_PLATELEGS_100), - ITEM_DHARKS_GREATEAXE(DHAROKS_GREATAXE, DHAROKS_GREATAXE_25, DHAROKS_GREATAXE_50, DHAROKS_GREATAXE_75, DHAROKS_GREATAXE_100), - ITEM_GUTHANS_HELM(GUTHANS_HELM, GUTHANS_HELM_25, GUTHANS_HELM_50, GUTHANS_HELM_75, GUTHANS_HELM_100), - ITEM_GUTHANS_PLATEBODY(GUTHANS_PLATEBODY, GUTHANS_PLATEBODY_25, GUTHANS_PLATEBODY_50, GUTHANS_PLATEBODY_75, GUTHANS_PLATEBODY_100), - ITEM_GUTHANS_CHAINSKIRT(GUTHANS_CHAINSKIRT, GUTHANS_CHAINSKIRT_25, GUTHANS_CHAINSKIRT_50, GUTHANS_CHAINSKIRT_75, GUTHANS_CHAINSKIRT_100), - ITEM_GUTHANS_WARSPEAR(GUTHANS_WARSPEAR, GUTHANS_WARSPEAR_25, GUTHANS_WARSPEAR_50, GUTHANS_WARSPEAR_75, GUTHANS_WARSPEAR_100), - ITEM_TORAGS_HELM(TORAGS_HELM, TORAGS_HELM_25, TORAGS_HELM_50, TORAGS_HELM_75, TORAGS_HELM_100), - ITEM_TORAGS_PLATEBODY(TORAGS_PLATEBODY, TORAGS_PLATEBODY_25, TORAGS_PLATEBODY_50, TORAGS_PLATEBODY_75, TORAGS_PLATEBODY_100), - ITEM_TORAGS_PLATELEGS(TORAGS_PLATELEGS, TORAGS_PLATELEGS_25, TORAGS_PLATELEGS_50, TORAGS_PLATELEGS_75, TORAGS_PLATELEGS_100), - ITEM_TORAGS_HAMMERS(TORAGS_HAMMERS, TORAGS_HAMMERS_25, TORAGS_HAMMERS_50, TORAGS_HAMMERS_75, TORAGS_HAMMERS_100), - ITEM_VERACS_HELM(VERACS_HELM, VERACS_HELM_25, VERACS_HELM_50, VERACS_HELM_75, VERACS_HELM_100), - ITEM_VERACS_BRASSARD(VERACS_BRASSARD, VERACS_BRASSARD_25, VERACS_BRASSARD_50, VERACS_BRASSARD_75, VERACS_BRASSARD_100), - ITEM_VERACS_PLATESKIRT(VERACS_PLATESKIRT, VERACS_PLATESKIRT_25, VERACS_PLATESKIRT_50, VERACS_PLATESKIRT_75, VERACS_PLATESKIRT_100), - ITEM_VERACS_FLAIL(VERACS_FLAIL, VERACS_FLAIL_25, VERACS_FLAIL_50, VERACS_FLAIL_75, VERACS_FLAIL_100), - - // Dragon equipment ornament kits - ITEM_DRAGON_SCIMITAR(DRAGON_SCIMITAR, DRAGON_SCIMITAR_OR), - ITEM_DRAGON_SCIMITAR_ORNAMENT_KIT(DRAGON_SCIMITAR_ORNAMENT_KIT, DRAGON_SCIMITAR_OR), - ITEM_DRAGON_DEFENDER(DRAGON_DEFENDER_ORNAMENT_KIT, DRAGON_DEFENDER_T), - ITEM_DRAGON_PICKAXE(DRAGON_PICKAXE, DRAGON_PICKAXE_12797), - ITEM_DRAGON_KITESHIELD(DRAGON_KITESHIELD, DRAGON_KITESHIELD_G), - ITEM_DRAGON_KITESHIELD_ORNAMENT_KIT(DRAGON_KITESHIELD_ORNAMENT_KIT, DRAGON_KITESHIELD_G), - ITEM_DRAGON_FULL_HELM(DRAGON_FULL_HELM, DRAGON_FULL_HELM_G), - ITEM_DRAGON_FULL_HELM_ORNAMENT_KIT(DRAGON_FULL_HELM_ORNAMENT_KIT, DRAGON_FULL_HELM_G), - ITEM_DRAGON_CHAINBODY(DRAGON_CHAINBODY_3140, DRAGON_CHAINBODY_G), - ITEM_DRAGON_CHAINBODY_ORNAMENT_KIT(DRAGON_CHAINBODY_ORNAMENT_KIT, DRAGON_CHAINBODY_G), - ITEM_DRAGON_PLATEBODY(DRAGON_PLATEBODY, DRAGON_PLATEBODY_G), - ITEM_DRAGON_PLATEBODY_ORNAMENT_KIT(DRAGON_PLATEBODY_ORNAMENT_KIT, DRAGON_PLATEBODY_G), - ITEM_DRAGON_PLATESKIRT(DRAGON_PLATESKIRT, DRAGON_PLATESKIRT_G), - ITEM_DRAGON_SKIRT_ORNAMENT_KIT(DRAGON_LEGSSKIRT_ORNAMENT_KIT, DRAGON_PLATESKIRT_G), - ITEM_DRAGON_PLATELEGS(DRAGON_PLATELEGS, DRAGON_PLATELEGS_G), - ITEM_DRAGON_LEGS_ORNAMENT_KIT(DRAGON_LEGSSKIRT_ORNAMENT_KIT, DRAGON_PLATELEGS_G), - ITEM_DRAGON_SQ_SHIELD(DRAGON_SQ_SHIELD, DRAGON_SQ_SHIELD_G), - ITEM_DRAGON_SQ_SHIELD_ORNAMENT_KIT(DRAGON_SQ_SHIELD_ORNAMENT_KIT, DRAGON_SQ_SHIELD_G), - ITEM_DRAGON_BOOTS(DRAGON_BOOTS, DRAGON_BOOTS_G), - ITEM_DRAGON_BOOTS_ORNAMENT_KIT(DRAGON_BOOTS_ORNAMENT_KIT, DRAGON_BOOTS_G), - - // Godsword ornament kits - ITEM_ARMADYL_GODSWORD(ARMADYL_GODSWORD, ARMADYL_GODSWORD_OR), - ITEM_ARMADYL_GODSWORD_ORNAMENT_KIT(ARMADYL_GODSWORD_ORNAMENT_KIT, ARMADYL_GODSWORD_OR), - ITEM_BANDOS_GODSWORD(BANDOS_GODSWORD, BANDOS_GODSWORD_OR), - ITEM_BANDOS_GODSWORD_ORNAMENT_KIT(BANDOS_GODSWORD_ORNAMENT_KIT, BANDOS_GODSWORD_OR), - ITEM_ZAMORAK_GODSWORD(ZAMORAK_GODSWORD, ZAMORAK_GODSWORD_OR), - ITEM_ZAMORAK_GODSWORD_ORNAMENT_KIT(ZAMORAK_GODSWORD_ORNAMENT_KIT, ZAMORAK_GODSWORD_OR), - ITEM_SARADOMIN_GODSWORD(SARADOMIN_GODSWORD, SARADOMIN_GODSWORD_OR), - ITEM_SARADOMIN_GODSWORD_ORNAMENT_KIT(SARADOMIN_GODSWORD_ORNAMENT_KIT, SARADOMIN_GODSWORD_OR), - - // Jewellery ornament kits - ITEM_AMULET_OF_TORTURE(AMULET_OF_TORTURE, AMULET_OF_TORTURE_OR), - ITEM_TORTURE_ORNAMENT_KIT(TORTURE_ORNAMENT_KIT, AMULET_OF_TORTURE_OR), - ITEM_NECKLACE_OF_ANGUISH(NECKLACE_OF_ANGUISH, NECKLACE_OF_ANGUISH_OR), - ITEM_ANGUISH_ORNAMENT_KIT(ANGUISH_ORNAMENT_KIT, NECKLACE_OF_ANGUISH_OR), - ITEM_OCCULT_NECKLACE(OCCULT_NECKLACE, OCCULT_NECKLACE_OR), - ITEM_OCCULT_ORNAMENT_KIT(OCCULT_ORNAMENT_KIT, OCCULT_NECKLACE_OR), - ITE_AMULET_OF_FURY(AMULET_OF_FURY, AMULET_OF_FURY_OR), - ITE_FURY_ORNAMENT_KIT(FURY_ORNAMENT_KIT, AMULET_OF_FURY_OR), - - // Ensouled heads - ITEM_ENSOULED_GOBLIN_HEAD(ENSOULED_GOBLIN_HEAD_13448, ENSOULED_GOBLIN_HEAD), - ITEM_ENSOULED_MONKEY_HEAD(ENSOULED_MONKEY_HEAD_13451, ENSOULED_MONKEY_HEAD), - ITEM_ENSOULED_IMP_HEAD(ENSOULED_IMP_HEAD_13454, ENSOULED_IMP_HEAD), - ITEM_ENSOULED_MINOTAUR_HEAD(ENSOULED_MINOTAUR_HEAD_13457, ENSOULED_MINOTAUR_HEAD), - ITEM_ENSOULED_SCORPION_HEAD(ENSOULED_SCORPION_HEAD_13460, ENSOULED_SCORPION_HEAD), - ITEM_ENSOULED_BEAR_HEAD(ENSOULED_BEAR_HEAD_13463, ENSOULED_BEAR_HEAD), - ITEM_ENSOULED_UNICORN_HEAD(ENSOULED_UNICORN_HEAD_13466, ENSOULED_UNICORN_HEAD), - ITEM_ENSOULED_DOG_HEAD(ENSOULED_DOG_HEAD_13469, ENSOULED_DOG_HEAD), - ITEM_ENSOULED_CHAOS_DRUID_HEAD(ENSOULED_CHAOS_DRUID_HEAD_13472, ENSOULED_CHAOS_DRUID_HEAD), - ITEM_ENSOULED_GIANT_HEAD(ENSOULED_GIANT_HEAD_13475, ENSOULED_GIANT_HEAD), - ITEM_ENSOULED_OGRE_HEAD(ENSOULED_OGRE_HEAD_13478, ENSOULED_OGRE_HEAD), - ITEM_ENSOULED_ELF_HEAD(ENSOULED_ELF_HEAD_13481, ENSOULED_ELF_HEAD), - ITEM_ENSOULED_TROLL_HEAD(ENSOULED_TROLL_HEAD_13484, ENSOULED_TROLL_HEAD), - ITEM_ENSOULED_HORROR_HEAD(ENSOULED_HORROR_HEAD_13487, ENSOULED_HORROR_HEAD), - ITEM_ENSOULED_KALPHITE_HEAD(ENSOULED_KALPHITE_HEAD_13490, ENSOULED_KALPHITE_HEAD), - ITEM_ENSOULED_DAGANNOTH_HEAD(ENSOULED_DAGANNOTH_HEAD_13493, ENSOULED_DAGANNOTH_HEAD), - ITEM_ENSOULED_BLOODVELD_HEAD(ENSOULED_BLOODVELD_HEAD_13496, ENSOULED_BLOODVELD_HEAD), - ITEM_ENSOULED_TZHAAR_HEAD(ENSOULED_TZHAAR_HEAD_13499, ENSOULED_TZHAAR_HEAD), - ITEM_ENSOULED_DEMON_HEAD(ENSOULED_DEMON_HEAD_13502, ENSOULED_DEMON_HEAD), - ITEM_ENSOULED_AVIANSIE_HEAD(ENSOULED_AVIANSIE_HEAD_13505, ENSOULED_AVIANSIE_HEAD), - ITEM_ENSOULED_ABYSSAL_HEAD(ENSOULED_ABYSSAL_HEAD_13508, ENSOULED_ABYSSAL_HEAD), - ITEM_ENSOULED_DRAGON_HEAD(ENSOULED_DRAGON_HEAD_13511, ENSOULED_DRAGON_HEAD), - - // Imbued rings - ITEM_BERSERKER_RING(BERSERKER_RING, BERSERKER_RING_I), - ITEM_SEERS_RING(SEERS_RING, SEERS_RING_I), - ITEM_WARRIOR_RING(WARRIOR_RING, WARRIOR_RING_I), - ITEM_ARCHERS_RING(ARCHERS_RING, ARCHERS_RING_I), - ITEM_TREASONOUS_RING(TREASONOUS_RING, TREASONOUS_RING_I), - ITEM_TYRANNICAL_RING(TYRANNICAL_RING, TYRANNICAL_RING_I), - ITEM_RING_OF_THE_GODS(RING_OF_THE_GODS, RING_OF_THE_GODS_I), - ITEM_RING_OF_SUFFERING(RING_OF_SUFFERING, RING_OF_SUFFERING_I, RING_OF_SUFFERING_R, RING_OF_SUFFERING_RI), - ITEM_GRANITE_RING(GRANITE_RING, GRANITE_RING_I), - - // Bounty hunter - ITEM_GRANITE_MAUL(GRANITE_MAUL, GRANITE_MAUL_12848), - ITEM_MAGIC_SHORTBOW(MAGIC_SHORTBOW, MAGIC_SHORTBOW_I), - ITEM_SARADOMINS_BLESSED_SWORD(SARADOMINS_TEAR, SARADOMINS_BLESSED_SWORD), - - // Jewellery with charges - ITEM_RING_OF_WEALTH(RING_OF_WEALTH, RING_OF_WEALTH_I, RING_OF_WEALTH_1, RING_OF_WEALTH_I1, RING_OF_WEALTH_2, RING_OF_WEALTH_I2, RING_OF_WEALTH_3, RING_OF_WEALTH_I3, RING_OF_WEALTH_4, RING_OF_WEALTH_I4, RING_OF_WEALTH_I5), - ITEM_AMULET_OF_GLORY(AMULET_OF_GLORY, AMULET_OF_GLORY1, AMULET_OF_GLORY2, AMULET_OF_GLORY3, AMULET_OF_GLORY5), - ITEM_AMULET_OF_GLORY_T(AMULET_OF_GLORY_T, AMULET_OF_GLORY_T1, AMULET_OF_GLORY_T2, AMULET_OF_GLORY_T3, AMULET_OF_GLORY_T5), - ITEM_SKILLS_NECKLACE(SKILLS_NECKLACE, SKILLS_NECKLACE1, SKILLS_NECKLACE2, SKILLS_NECKLACE3, SKILLS_NECKLACE5), - ITEM_RING_OF_DUELING(RING_OF_DUELING8, RING_OF_DUELING1, RING_OF_DUELING2, RING_OF_DUELING3, RING_OF_DUELING4, RING_OF_DUELING5, RING_OF_DUELING6, RING_OF_DUELING7), - ITEM_GAMES_NECKLACE(GAMES_NECKLACE8, GAMES_NECKLACE1, GAMES_NECKLACE2, GAMES_NECKLACE3, GAMES_NECKLACE4, GAMES_NECKLACE5, GAMES_NECKLACE6, GAMES_NECKLACE7), - - // Degradable/charged weaponry/armour - ITEM_ABYSSAL_WHIP(ABYSSAL_WHIP, VOLCANIC_ABYSSAL_WHIP, FROZEN_ABYSSAL_WHIP), - ITEM_KRAKEN_TENTACLE(KRAKEN_TENTACLE, ABYSSAL_TENTACLE), - ITEM_TRIDENT_OF_THE_SEAS(UNCHARGED_TRIDENT, TRIDENT_OF_THE_SEAS), - ITEM_TRIDENT_OF_THE_SEAS_E(UNCHARGED_TRIDENT_E, TRIDENT_OF_THE_SEAS_E), - ITEM_TRIDENT_OF_THE_SWAMP(UNCHARGED_TOXIC_TRIDENT, TRIDENT_OF_THE_SWAMP), - ITEM_TRIDENT_OF_THE_SWAMP_E(UNCHARGED_TOXIC_TRIDENT_E, TRIDENT_OF_THE_SWAMP_E), - ITEM_TOXIC_BLOWPIPE(TOXIC_BLOWPIPE_EMPTY, TOXIC_BLOWPIPE), - ITEM_TOXIC_STAFF_OFF_THE_DEAD(TOXIC_STAFF_UNCHARGED, TOXIC_STAFF_OF_THE_DEAD), - ITEM_SERPENTINE_HELM(SERPENTINE_HELM_UNCHARGED, SERPENTINE_HELM, TANZANITE_HELM_UNCHARGED, TANZANITE_HELM, MAGMA_HELM_UNCHARGED, MAGMA_HELM), - ITEM_DRAGONFIRE_SHIELD(DRAGONFIRE_SHIELD_11284, DRAGONFIRE_SHIELD), - ITEM_DRAGONFIRE_WARD(DRAGONFIRE_WARD_22003, DRAGONFIRE_WARD), - ITEM_ANCIENT_WYVERN_SHIELD(ANCIENT_WYVERN_SHIELD_21634, ANCIENT_WYVERN_SHIELD), - ITEM_SANGUINESTI_STAFF(SANGUINESTI_STAFF_UNCHARGED, SANGUINESTI_STAFF), - ITEM_SCYTHE_OF_VITUR(SCYTHE_OF_VITUR_UNCHARGED, SCYTHE_OF_VITUR), - ITEM_TOME_OF_FIRE(TOME_OF_FIRE_EMPTY, TOME_OF_FIRE), - ITEM_CRAWS_BOW(CRAWS_BOW_U, CRAWS_BOW), - ITEM_VIGGORAS_CHAINMACE(VIGGORAS_CHAINMACE_U, VIGGORAS_CHAINMACE), - ITEM_THAMMARONS_SCEPTRE(THAMMARONS_SCEPTRE_U, THAMMARONS_SCEPTRE), - - // Infinity colour kits - ITEM_INFINITY_TOP(INFINITY_TOP, INFINITY_TOP_10605, INFINITY_TOP_20574, DARK_INFINITY_TOP, LIGHT_INFINITY_TOP), - ITEM_INFINITY_TOP_LIGHT_COLOUR_KIT(LIGHT_INFINITY_COLOUR_KIT, LIGHT_INFINITY_TOP), - ITEM_INFINITY_TOP_DARK_COLOUR_KIT(DARK_INFINITY_COLOUR_KIT, DARK_INFINITY_TOP), - ITEM_INFINITY_BOTTOMS(INFINITY_BOTTOMS, INFINITY_BOTTOMS_20575, DARK_INFINITY_BOTTOMS, LIGHT_INFINITY_BOTTOMS), - ITEM_INFINITY_BOTTOMS_LIGHT_COLOUR_KIT(LIGHT_INFINITY_COLOUR_KIT, LIGHT_INFINITY_BOTTOMS), - ITEM_INFINITY_BOTTOMS_DARK_COLOUR_KIT(DARK_INFINITY_COLOUR_KIT, DARK_INFINITY_BOTTOMS), - ITEM_INFINITY_HAT(INFINITY_HAT, DARK_INFINITY_HAT, LIGHT_INFINITY_HAT), - ITEM_INFINITY_HAT_LIGHT_COLOUR_KIT(LIGHT_INFINITY_COLOUR_KIT, LIGHT_INFINITY_HAT), - ITEM_INFINITY_HAT_DARK_COLOUR_KIT(DARK_INFINITY_COLOUR_KIT, DARK_INFINITY_HAT), - - // Miscellaneous ornament kits - ITEM_DARK_BOW(DARK_BOW, DARK_BOW_12765, DARK_BOW_12766, DARK_BOW_12767, DARK_BOW_12768, DARK_BOW_20408), - ITEM_ODIUM_WARD(ODIUM_WARD, ODIUM_WARD_12807), - ITEM_MALEDICTION_WARD(MALEDICTION_WARD, MALEDICTION_WARD_12806), - ITEM_STEAM_BATTLESTAFF(STEAM_BATTLESTAFF, STEAM_BATTLESTAFF_12795), - ITEM_LAVA_BATTLESTAFF(LAVA_BATTLESTAFF, LAVA_BATTLESTAFF_21198), - - // Slayer helm/black mask - ITEM_BLACK_MASK( - BLACK_MASK, BLACK_MASK_I, BLACK_MASK_1, BLACK_MASK_1_I, BLACK_MASK_2, BLACK_MASK_2_I, BLACK_MASK_3, BLACK_MASK_3_I, BLACK_MASK_4, BLACK_MASK_4_I, BLACK_MASK_5, - BLACK_MASK_5_I, BLACK_MASK_6, BLACK_MASK_6_I, BLACK_MASK_7, BLACK_MASK_7_I, BLACK_MASK_8, BLACK_MASK_8_I, BLACK_MASK_9, BLACK_MASK_9_I, BLACK_MASK_10_I, - SLAYER_HELMET, SLAYER_HELMET_I, BLACK_SLAYER_HELMET, BLACK_SLAYER_HELMET_I, PURPLE_SLAYER_HELMET, PURPLE_SLAYER_HELMET_I, RED_SLAYER_HELMET, RED_SLAYER_HELMET_I, - GREEN_SLAYER_HELMET, GREEN_SLAYER_HELMET_I, TURQUOISE_SLAYER_HELMET, TURQUOISE_SLAYER_HELMET_I, HYDRA_SLAYER_HELMET, HYDRA_SLAYER_HELMET_I), - - // Pharaoh's Sceptres - ITEM_PHARAOHS_SCEPTRE_1(PHARAOHS_SCEPTRE, PHARAOHS_SCEPTRE_1), - ITEM_PHARAOHS_SCEPTRE_2(PHARAOHS_SCEPTRE, PHARAOHS_SCEPTRE_2), - ITEM_PHARAOHS_SCEPTRE_4(PHARAOHS_SCEPTRE, PHARAOHS_SCEPTRE_4), - ITEM_PHARAOHS_SCEPTRE_5(PHARAOHS_SCEPTRE, PHARAOHS_SCEPTRE_5), - ITEM_PHARAOHS_SCEPTRE_6(PHARAOHS_SCEPTRE, PHARAOHS_SCEPTRE_6), - ITEM_PHARAOHS_SCEPTRE_7(PHARAOHS_SCEPTRE, PHARAOHS_SCEPTRE_7), - ITEM_PHARAOHS_SCEPTRE_8(PHARAOHS_SCEPTRE, PHARAOHS_SCEPTRE_8), - - // Revertible items - ITEM_HYDRA_LEATHER(HYDRA_LEATHER, FEROCIOUS_GLOVES), - ITEM_HYDRA_TAIL(HYDRA_TAIL, BONECRUSHER_NECKLACE), - ITEM_DRAGONBONE_NECKLACE(DRAGONBONE_NECKLACE, BONECRUSHER_NECKLACE), - ITEM_BOTTOMLESS_COMPOST_BUCKET(BOTTOMLESS_COMPOST_BUCKET, BOTTOMLESS_COMPOST_BUCKET_22997); - - private static final Multimap MAPPINGS = HashMultimap.create(); - private final int tradeableItem; - private final int[] untradableItems; - - static - { - for (final ItemMapping item : values()) - { - for (int itemId : item.untradableItems) - { - MAPPINGS.put(itemId, item.tradeableItem); - } - } - } - - ItemMapping(int tradeableItem, int... untradableItems) - { - this.tradeableItem = tradeableItem; - this.untradableItems = untradableItems; - } - - /** - * Get collection of items that are mapped from single item id. - * - * @param itemId the item id - * @return the collection - */ - public static Collection map(int itemId) - { - final Collection mapping = MAPPINGS.get(itemId); - - if (mapping == null || mapping.isEmpty()) - { - return Collections.singleton(itemId); - } - - return mapping; - } - - /** - * Map an item from its untradeable version to its tradeable version - * - * @param itemId - * @return - */ - public static int mapFirst(int itemId) - { - final Collection mapping = MAPPINGS.get(itemId); - - if (mapping == null || mapping.isEmpty()) - { - return itemId; - } - - return mapping.iterator().next(); - } -} +/* + * Copyright (c) 2018, Tomas Slusny + * Copyright (c) 2018, Seth + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.game; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; +import java.util.Collection; +import java.util.Collections; +import static net.runelite.api.ItemID.ABYSSAL_TENTACLE; +import static net.runelite.api.ItemID.ABYSSAL_WHIP; +import static net.runelite.api.ItemID.AHRIMS_HOOD; +import static net.runelite.api.ItemID.AHRIMS_HOOD_100; +import static net.runelite.api.ItemID.AHRIMS_HOOD_25; +import static net.runelite.api.ItemID.AHRIMS_HOOD_50; +import static net.runelite.api.ItemID.AHRIMS_HOOD_75; +import static net.runelite.api.ItemID.AHRIMS_ROBESKIRT; +import static net.runelite.api.ItemID.AHRIMS_ROBESKIRT_100; +import static net.runelite.api.ItemID.AHRIMS_ROBESKIRT_25; +import static net.runelite.api.ItemID.AHRIMS_ROBESKIRT_50; +import static net.runelite.api.ItemID.AHRIMS_ROBESKIRT_75; +import static net.runelite.api.ItemID.AHRIMS_ROBETOP; +import static net.runelite.api.ItemID.AHRIMS_ROBETOP_100; +import static net.runelite.api.ItemID.AHRIMS_ROBETOP_25; +import static net.runelite.api.ItemID.AHRIMS_ROBETOP_50; +import static net.runelite.api.ItemID.AHRIMS_ROBETOP_75; +import static net.runelite.api.ItemID.AHRIMS_STAFF; +import static net.runelite.api.ItemID.AHRIMS_STAFF_100; +import static net.runelite.api.ItemID.AHRIMS_STAFF_25; +import static net.runelite.api.ItemID.AHRIMS_STAFF_50; +import static net.runelite.api.ItemID.AHRIMS_STAFF_75; +import static net.runelite.api.ItemID.AMULET_OF_FURY; +import static net.runelite.api.ItemID.AMULET_OF_FURY_OR; +import static net.runelite.api.ItemID.AMULET_OF_GLORY; +import static net.runelite.api.ItemID.AMULET_OF_GLORY1; +import static net.runelite.api.ItemID.AMULET_OF_GLORY2; +import static net.runelite.api.ItemID.AMULET_OF_GLORY3; +import static net.runelite.api.ItemID.AMULET_OF_GLORY5; +import static net.runelite.api.ItemID.AMULET_OF_GLORY_T; +import static net.runelite.api.ItemID.AMULET_OF_GLORY_T1; +import static net.runelite.api.ItemID.AMULET_OF_GLORY_T2; +import static net.runelite.api.ItemID.AMULET_OF_GLORY_T3; +import static net.runelite.api.ItemID.AMULET_OF_GLORY_T5; +import static net.runelite.api.ItemID.AMULET_OF_TORTURE; +import static net.runelite.api.ItemID.AMULET_OF_TORTURE_OR; +import static net.runelite.api.ItemID.ANCIENT_WYVERN_SHIELD; +import static net.runelite.api.ItemID.ANCIENT_WYVERN_SHIELD_21634; +import static net.runelite.api.ItemID.ANGUISH_ORNAMENT_KIT; +import static net.runelite.api.ItemID.ARCHERS_RING; +import static net.runelite.api.ItemID.ARCHERS_RING_I; +import static net.runelite.api.ItemID.ARMADYL_GODSWORD; +import static net.runelite.api.ItemID.ARMADYL_GODSWORD_OR; +import static net.runelite.api.ItemID.ARMADYL_GODSWORD_ORNAMENT_KIT; +import static net.runelite.api.ItemID.BANDOS_GODSWORD; +import static net.runelite.api.ItemID.BANDOS_GODSWORD_OR; +import static net.runelite.api.ItemID.BANDOS_GODSWORD_ORNAMENT_KIT; +import static net.runelite.api.ItemID.BERSERKER_RING; +import static net.runelite.api.ItemID.BERSERKER_RING_I; +import static net.runelite.api.ItemID.BLACK_MASK; +import static net.runelite.api.ItemID.BLACK_MASK_1; +import static net.runelite.api.ItemID.BLACK_MASK_10_I; +import static net.runelite.api.ItemID.BLACK_MASK_1_I; +import static net.runelite.api.ItemID.BLACK_MASK_2; +import static net.runelite.api.ItemID.BLACK_MASK_2_I; +import static net.runelite.api.ItemID.BLACK_MASK_3; +import static net.runelite.api.ItemID.BLACK_MASK_3_I; +import static net.runelite.api.ItemID.BLACK_MASK_4; +import static net.runelite.api.ItemID.BLACK_MASK_4_I; +import static net.runelite.api.ItemID.BLACK_MASK_5; +import static net.runelite.api.ItemID.BLACK_MASK_5_I; +import static net.runelite.api.ItemID.BLACK_MASK_6; +import static net.runelite.api.ItemID.BLACK_MASK_6_I; +import static net.runelite.api.ItemID.BLACK_MASK_7; +import static net.runelite.api.ItemID.BLACK_MASK_7_I; +import static net.runelite.api.ItemID.BLACK_MASK_8; +import static net.runelite.api.ItemID.BLACK_MASK_8_I; +import static net.runelite.api.ItemID.BLACK_MASK_9; +import static net.runelite.api.ItemID.BLACK_MASK_9_I; +import static net.runelite.api.ItemID.BLACK_MASK_I; +import static net.runelite.api.ItemID.BLACK_SLAYER_HELMET; +import static net.runelite.api.ItemID.BLACK_SLAYER_HELMET_I; +import static net.runelite.api.ItemID.BONECRUSHER_NECKLACE; +import static net.runelite.api.ItemID.BOTTOMLESS_COMPOST_BUCKET; +import static net.runelite.api.ItemID.BOTTOMLESS_COMPOST_BUCKET_22997; +import static net.runelite.api.ItemID.CRAWS_BOW; +import static net.runelite.api.ItemID.CRAWS_BOW_U; +import static net.runelite.api.ItemID.DARK_BOW; +import static net.runelite.api.ItemID.DARK_BOW_12765; +import static net.runelite.api.ItemID.DARK_BOW_12766; +import static net.runelite.api.ItemID.DARK_BOW_12767; +import static net.runelite.api.ItemID.DARK_BOW_12768; +import static net.runelite.api.ItemID.DARK_BOW_20408; +import static net.runelite.api.ItemID.DARK_INFINITY_BOTTOMS; +import static net.runelite.api.ItemID.DARK_INFINITY_COLOUR_KIT; +import static net.runelite.api.ItemID.DARK_INFINITY_HAT; +import static net.runelite.api.ItemID.DARK_INFINITY_TOP; +import static net.runelite.api.ItemID.DHAROKS_GREATAXE; +import static net.runelite.api.ItemID.DHAROKS_GREATAXE_100; +import static net.runelite.api.ItemID.DHAROKS_GREATAXE_25; +import static net.runelite.api.ItemID.DHAROKS_GREATAXE_50; +import static net.runelite.api.ItemID.DHAROKS_GREATAXE_75; +import static net.runelite.api.ItemID.DHAROKS_HELM; +import static net.runelite.api.ItemID.DHAROKS_HELM_100; +import static net.runelite.api.ItemID.DHAROKS_HELM_25; +import static net.runelite.api.ItemID.DHAROKS_HELM_50; +import static net.runelite.api.ItemID.DHAROKS_HELM_75; +import static net.runelite.api.ItemID.DHAROKS_PLATEBODY; +import static net.runelite.api.ItemID.DHAROKS_PLATEBODY_100; +import static net.runelite.api.ItemID.DHAROKS_PLATEBODY_25; +import static net.runelite.api.ItemID.DHAROKS_PLATEBODY_50; +import static net.runelite.api.ItemID.DHAROKS_PLATEBODY_75; +import static net.runelite.api.ItemID.DHAROKS_PLATELEGS; +import static net.runelite.api.ItemID.DHAROKS_PLATELEGS_100; +import static net.runelite.api.ItemID.DHAROKS_PLATELEGS_25; +import static net.runelite.api.ItemID.DHAROKS_PLATELEGS_50; +import static net.runelite.api.ItemID.DHAROKS_PLATELEGS_75; +import static net.runelite.api.ItemID.DRAGONBONE_NECKLACE; +import static net.runelite.api.ItemID.DRAGONFIRE_SHIELD; +import static net.runelite.api.ItemID.DRAGONFIRE_SHIELD_11284; +import static net.runelite.api.ItemID.DRAGONFIRE_WARD; +import static net.runelite.api.ItemID.DRAGONFIRE_WARD_22003; +import static net.runelite.api.ItemID.DRAGON_BOOTS; +import static net.runelite.api.ItemID.DRAGON_BOOTS_G; +import static net.runelite.api.ItemID.DRAGON_BOOTS_ORNAMENT_KIT; +import static net.runelite.api.ItemID.DRAGON_CHAINBODY_3140; +import static net.runelite.api.ItemID.DRAGON_CHAINBODY_G; +import static net.runelite.api.ItemID.DRAGON_CHAINBODY_ORNAMENT_KIT; +import static net.runelite.api.ItemID.DRAGON_DEFENDER_ORNAMENT_KIT; +import static net.runelite.api.ItemID.DRAGON_DEFENDER_T; +import static net.runelite.api.ItemID.DRAGON_FULL_HELM; +import static net.runelite.api.ItemID.DRAGON_FULL_HELM_G; +import static net.runelite.api.ItemID.DRAGON_FULL_HELM_ORNAMENT_KIT; +import static net.runelite.api.ItemID.DRAGON_KITESHIELD; +import static net.runelite.api.ItemID.DRAGON_KITESHIELD_G; +import static net.runelite.api.ItemID.DRAGON_KITESHIELD_ORNAMENT_KIT; +import static net.runelite.api.ItemID.DRAGON_LEGSSKIRT_ORNAMENT_KIT; +import static net.runelite.api.ItemID.DRAGON_PICKAXE; +import static net.runelite.api.ItemID.DRAGON_PICKAXE_12797; +import static net.runelite.api.ItemID.DRAGON_PLATEBODY; +import static net.runelite.api.ItemID.DRAGON_PLATEBODY_G; +import static net.runelite.api.ItemID.DRAGON_PLATEBODY_ORNAMENT_KIT; +import static net.runelite.api.ItemID.DRAGON_PLATELEGS; +import static net.runelite.api.ItemID.DRAGON_PLATELEGS_G; +import static net.runelite.api.ItemID.DRAGON_PLATESKIRT; +import static net.runelite.api.ItemID.DRAGON_PLATESKIRT_G; +import static net.runelite.api.ItemID.DRAGON_SCIMITAR; +import static net.runelite.api.ItemID.DRAGON_SCIMITAR_OR; +import static net.runelite.api.ItemID.DRAGON_SCIMITAR_ORNAMENT_KIT; +import static net.runelite.api.ItemID.DRAGON_SQ_SHIELD; +import static net.runelite.api.ItemID.DRAGON_SQ_SHIELD_G; +import static net.runelite.api.ItemID.DRAGON_SQ_SHIELD_ORNAMENT_KIT; +import static net.runelite.api.ItemID.ENSOULED_ABYSSAL_HEAD; +import static net.runelite.api.ItemID.ENSOULED_ABYSSAL_HEAD_13508; +import static net.runelite.api.ItemID.ENSOULED_AVIANSIE_HEAD; +import static net.runelite.api.ItemID.ENSOULED_AVIANSIE_HEAD_13505; +import static net.runelite.api.ItemID.ENSOULED_BEAR_HEAD; +import static net.runelite.api.ItemID.ENSOULED_BEAR_HEAD_13463; +import static net.runelite.api.ItemID.ENSOULED_BLOODVELD_HEAD; +import static net.runelite.api.ItemID.ENSOULED_BLOODVELD_HEAD_13496; +import static net.runelite.api.ItemID.ENSOULED_CHAOS_DRUID_HEAD; +import static net.runelite.api.ItemID.ENSOULED_CHAOS_DRUID_HEAD_13472; +import static net.runelite.api.ItemID.ENSOULED_DAGANNOTH_HEAD; +import static net.runelite.api.ItemID.ENSOULED_DAGANNOTH_HEAD_13493; +import static net.runelite.api.ItemID.ENSOULED_DEMON_HEAD; +import static net.runelite.api.ItemID.ENSOULED_DEMON_HEAD_13502; +import static net.runelite.api.ItemID.ENSOULED_DOG_HEAD; +import static net.runelite.api.ItemID.ENSOULED_DOG_HEAD_13469; +import static net.runelite.api.ItemID.ENSOULED_DRAGON_HEAD; +import static net.runelite.api.ItemID.ENSOULED_DRAGON_HEAD_13511; +import static net.runelite.api.ItemID.ENSOULED_ELF_HEAD; +import static net.runelite.api.ItemID.ENSOULED_ELF_HEAD_13481; +import static net.runelite.api.ItemID.ENSOULED_GIANT_HEAD; +import static net.runelite.api.ItemID.ENSOULED_GIANT_HEAD_13475; +import static net.runelite.api.ItemID.ENSOULED_GOBLIN_HEAD; +import static net.runelite.api.ItemID.ENSOULED_GOBLIN_HEAD_13448; +import static net.runelite.api.ItemID.ENSOULED_HORROR_HEAD; +import static net.runelite.api.ItemID.ENSOULED_HORROR_HEAD_13487; +import static net.runelite.api.ItemID.ENSOULED_IMP_HEAD; +import static net.runelite.api.ItemID.ENSOULED_IMP_HEAD_13454; +import static net.runelite.api.ItemID.ENSOULED_KALPHITE_HEAD; +import static net.runelite.api.ItemID.ENSOULED_KALPHITE_HEAD_13490; +import static net.runelite.api.ItemID.ENSOULED_MINOTAUR_HEAD; +import static net.runelite.api.ItemID.ENSOULED_MINOTAUR_HEAD_13457; +import static net.runelite.api.ItemID.ENSOULED_MONKEY_HEAD; +import static net.runelite.api.ItemID.ENSOULED_MONKEY_HEAD_13451; +import static net.runelite.api.ItemID.ENSOULED_OGRE_HEAD; +import static net.runelite.api.ItemID.ENSOULED_OGRE_HEAD_13478; +import static net.runelite.api.ItemID.ENSOULED_SCORPION_HEAD; +import static net.runelite.api.ItemID.ENSOULED_SCORPION_HEAD_13460; +import static net.runelite.api.ItemID.ENSOULED_TROLL_HEAD; +import static net.runelite.api.ItemID.ENSOULED_TROLL_HEAD_13484; +import static net.runelite.api.ItemID.ENSOULED_TZHAAR_HEAD; +import static net.runelite.api.ItemID.ENSOULED_TZHAAR_HEAD_13499; +import static net.runelite.api.ItemID.ENSOULED_UNICORN_HEAD; +import static net.runelite.api.ItemID.ENSOULED_UNICORN_HEAD_13466; +import static net.runelite.api.ItemID.FEROCIOUS_GLOVES; +import static net.runelite.api.ItemID.FROZEN_ABYSSAL_WHIP; +import static net.runelite.api.ItemID.FURY_ORNAMENT_KIT; +import static net.runelite.api.ItemID.GAMES_NECKLACE1; +import static net.runelite.api.ItemID.GAMES_NECKLACE2; +import static net.runelite.api.ItemID.GAMES_NECKLACE3; +import static net.runelite.api.ItemID.GAMES_NECKLACE4; +import static net.runelite.api.ItemID.GAMES_NECKLACE5; +import static net.runelite.api.ItemID.GAMES_NECKLACE6; +import static net.runelite.api.ItemID.GAMES_NECKLACE7; +import static net.runelite.api.ItemID.GAMES_NECKLACE8; +import static net.runelite.api.ItemID.GRANITE_MAUL; +import static net.runelite.api.ItemID.GRANITE_MAUL_12848; +import static net.runelite.api.ItemID.GRANITE_RING; +import static net.runelite.api.ItemID.GRANITE_RING_I; +import static net.runelite.api.ItemID.GREEN_SLAYER_HELMET; +import static net.runelite.api.ItemID.GREEN_SLAYER_HELMET_I; +import static net.runelite.api.ItemID.GUTHANS_CHAINSKIRT; +import static net.runelite.api.ItemID.GUTHANS_CHAINSKIRT_100; +import static net.runelite.api.ItemID.GUTHANS_CHAINSKIRT_25; +import static net.runelite.api.ItemID.GUTHANS_CHAINSKIRT_50; +import static net.runelite.api.ItemID.GUTHANS_CHAINSKIRT_75; +import static net.runelite.api.ItemID.GUTHANS_HELM; +import static net.runelite.api.ItemID.GUTHANS_HELM_100; +import static net.runelite.api.ItemID.GUTHANS_HELM_25; +import static net.runelite.api.ItemID.GUTHANS_HELM_50; +import static net.runelite.api.ItemID.GUTHANS_HELM_75; +import static net.runelite.api.ItemID.GUTHANS_PLATEBODY; +import static net.runelite.api.ItemID.GUTHANS_PLATEBODY_100; +import static net.runelite.api.ItemID.GUTHANS_PLATEBODY_25; +import static net.runelite.api.ItemID.GUTHANS_PLATEBODY_50; +import static net.runelite.api.ItemID.GUTHANS_PLATEBODY_75; +import static net.runelite.api.ItemID.GUTHANS_WARSPEAR; +import static net.runelite.api.ItemID.GUTHANS_WARSPEAR_100; +import static net.runelite.api.ItemID.GUTHANS_WARSPEAR_25; +import static net.runelite.api.ItemID.GUTHANS_WARSPEAR_50; +import static net.runelite.api.ItemID.GUTHANS_WARSPEAR_75; +import static net.runelite.api.ItemID.HYDRA_LEATHER; +import static net.runelite.api.ItemID.HYDRA_SLAYER_HELMET; +import static net.runelite.api.ItemID.HYDRA_SLAYER_HELMET_I; +import static net.runelite.api.ItemID.HYDRA_TAIL; +import static net.runelite.api.ItemID.INFINITY_BOTTOMS; +import static net.runelite.api.ItemID.INFINITY_BOTTOMS_20575; +import static net.runelite.api.ItemID.INFINITY_HAT; +import static net.runelite.api.ItemID.INFINITY_TOP; +import static net.runelite.api.ItemID.INFINITY_TOP_10605; +import static net.runelite.api.ItemID.INFINITY_TOP_20574; +import static net.runelite.api.ItemID.KARILS_COIF; +import static net.runelite.api.ItemID.KARILS_COIF_100; +import static net.runelite.api.ItemID.KARILS_COIF_25; +import static net.runelite.api.ItemID.KARILS_COIF_50; +import static net.runelite.api.ItemID.KARILS_COIF_75; +import static net.runelite.api.ItemID.KARILS_CROSSBOW; +import static net.runelite.api.ItemID.KARILS_CROSSBOW_100; +import static net.runelite.api.ItemID.KARILS_CROSSBOW_25; +import static net.runelite.api.ItemID.KARILS_CROSSBOW_50; +import static net.runelite.api.ItemID.KARILS_CROSSBOW_75; +import static net.runelite.api.ItemID.KARILS_LEATHERSKIRT; +import static net.runelite.api.ItemID.KARILS_LEATHERSKIRT_100; +import static net.runelite.api.ItemID.KARILS_LEATHERSKIRT_25; +import static net.runelite.api.ItemID.KARILS_LEATHERSKIRT_50; +import static net.runelite.api.ItemID.KARILS_LEATHERSKIRT_75; +import static net.runelite.api.ItemID.KARILS_LEATHERTOP; +import static net.runelite.api.ItemID.KARILS_LEATHERTOP_100; +import static net.runelite.api.ItemID.KARILS_LEATHERTOP_25; +import static net.runelite.api.ItemID.KARILS_LEATHERTOP_50; +import static net.runelite.api.ItemID.KARILS_LEATHERTOP_75; +import static net.runelite.api.ItemID.KRAKEN_TENTACLE; +import static net.runelite.api.ItemID.LAVA_BATTLESTAFF; +import static net.runelite.api.ItemID.LAVA_BATTLESTAFF_21198; +import static net.runelite.api.ItemID.LIGHT_INFINITY_BOTTOMS; +import static net.runelite.api.ItemID.LIGHT_INFINITY_COLOUR_KIT; +import static net.runelite.api.ItemID.LIGHT_INFINITY_HAT; +import static net.runelite.api.ItemID.LIGHT_INFINITY_TOP; +import static net.runelite.api.ItemID.MAGIC_SHORTBOW; +import static net.runelite.api.ItemID.MAGIC_SHORTBOW_I; +import static net.runelite.api.ItemID.MAGMA_HELM; +import static net.runelite.api.ItemID.MAGMA_HELM_UNCHARGED; +import static net.runelite.api.ItemID.MALEDICTION_WARD; +import static net.runelite.api.ItemID.MALEDICTION_WARD_12806; +import static net.runelite.api.ItemID.NECKLACE_OF_ANGUISH; +import static net.runelite.api.ItemID.NECKLACE_OF_ANGUISH_OR; +import static net.runelite.api.ItemID.OCCULT_NECKLACE; +import static net.runelite.api.ItemID.OCCULT_NECKLACE_OR; +import static net.runelite.api.ItemID.OCCULT_ORNAMENT_KIT; +import static net.runelite.api.ItemID.ODIUM_WARD; +import static net.runelite.api.ItemID.ODIUM_WARD_12807; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_1; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_2; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_4; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_5; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_6; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_7; +import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_8; +import static net.runelite.api.ItemID.PURPLE_SLAYER_HELMET; +import static net.runelite.api.ItemID.PURPLE_SLAYER_HELMET_I; +import static net.runelite.api.ItemID.RED_SLAYER_HELMET; +import static net.runelite.api.ItemID.RED_SLAYER_HELMET_I; +import static net.runelite.api.ItemID.RING_OF_DUELING1; +import static net.runelite.api.ItemID.RING_OF_DUELING2; +import static net.runelite.api.ItemID.RING_OF_DUELING3; +import static net.runelite.api.ItemID.RING_OF_DUELING4; +import static net.runelite.api.ItemID.RING_OF_DUELING5; +import static net.runelite.api.ItemID.RING_OF_DUELING6; +import static net.runelite.api.ItemID.RING_OF_DUELING7; +import static net.runelite.api.ItemID.RING_OF_DUELING8; +import static net.runelite.api.ItemID.RING_OF_SUFFERING; +import static net.runelite.api.ItemID.RING_OF_SUFFERING_I; +import static net.runelite.api.ItemID.RING_OF_SUFFERING_R; +import static net.runelite.api.ItemID.RING_OF_SUFFERING_RI; +import static net.runelite.api.ItemID.RING_OF_THE_GODS; +import static net.runelite.api.ItemID.RING_OF_THE_GODS_I; +import static net.runelite.api.ItemID.RING_OF_WEALTH; +import static net.runelite.api.ItemID.RING_OF_WEALTH_1; +import static net.runelite.api.ItemID.RING_OF_WEALTH_2; +import static net.runelite.api.ItemID.RING_OF_WEALTH_3; +import static net.runelite.api.ItemID.RING_OF_WEALTH_4; +import static net.runelite.api.ItemID.RING_OF_WEALTH_I; +import static net.runelite.api.ItemID.RING_OF_WEALTH_I1; +import static net.runelite.api.ItemID.RING_OF_WEALTH_I2; +import static net.runelite.api.ItemID.RING_OF_WEALTH_I3; +import static net.runelite.api.ItemID.RING_OF_WEALTH_I4; +import static net.runelite.api.ItemID.RING_OF_WEALTH_I5; +import static net.runelite.api.ItemID.SANGUINESTI_STAFF; +import static net.runelite.api.ItemID.SANGUINESTI_STAFF_UNCHARGED; +import static net.runelite.api.ItemID.SARADOMINS_BLESSED_SWORD; +import static net.runelite.api.ItemID.SARADOMINS_TEAR; +import static net.runelite.api.ItemID.SARADOMIN_GODSWORD; +import static net.runelite.api.ItemID.SARADOMIN_GODSWORD_OR; +import static net.runelite.api.ItemID.SARADOMIN_GODSWORD_ORNAMENT_KIT; +import static net.runelite.api.ItemID.SCYTHE_OF_VITUR; +import static net.runelite.api.ItemID.SCYTHE_OF_VITUR_UNCHARGED; +import static net.runelite.api.ItemID.SEERS_RING; +import static net.runelite.api.ItemID.SEERS_RING_I; +import static net.runelite.api.ItemID.SERPENTINE_HELM; +import static net.runelite.api.ItemID.SERPENTINE_HELM_UNCHARGED; +import static net.runelite.api.ItemID.SKILLS_NECKLACE; +import static net.runelite.api.ItemID.SKILLS_NECKLACE1; +import static net.runelite.api.ItemID.SKILLS_NECKLACE2; +import static net.runelite.api.ItemID.SKILLS_NECKLACE3; +import static net.runelite.api.ItemID.SKILLS_NECKLACE5; +import static net.runelite.api.ItemID.SLAYER_HELMET; +import static net.runelite.api.ItemID.SLAYER_HELMET_I; +import static net.runelite.api.ItemID.STEAM_BATTLESTAFF; +import static net.runelite.api.ItemID.STEAM_BATTLESTAFF_12795; +import static net.runelite.api.ItemID.TANZANITE_HELM; +import static net.runelite.api.ItemID.TANZANITE_HELM_UNCHARGED; +import static net.runelite.api.ItemID.THAMMARONS_SCEPTRE; +import static net.runelite.api.ItemID.THAMMARONS_SCEPTRE_U; +import static net.runelite.api.ItemID.TOME_OF_FIRE; +import static net.runelite.api.ItemID.TOME_OF_FIRE_EMPTY; +import static net.runelite.api.ItemID.TORAGS_HAMMERS; +import static net.runelite.api.ItemID.TORAGS_HAMMERS_100; +import static net.runelite.api.ItemID.TORAGS_HAMMERS_25; +import static net.runelite.api.ItemID.TORAGS_HAMMERS_50; +import static net.runelite.api.ItemID.TORAGS_HAMMERS_75; +import static net.runelite.api.ItemID.TORAGS_HELM; +import static net.runelite.api.ItemID.TORAGS_HELM_100; +import static net.runelite.api.ItemID.TORAGS_HELM_25; +import static net.runelite.api.ItemID.TORAGS_HELM_50; +import static net.runelite.api.ItemID.TORAGS_HELM_75; +import static net.runelite.api.ItemID.TORAGS_PLATEBODY; +import static net.runelite.api.ItemID.TORAGS_PLATEBODY_100; +import static net.runelite.api.ItemID.TORAGS_PLATEBODY_25; +import static net.runelite.api.ItemID.TORAGS_PLATEBODY_50; +import static net.runelite.api.ItemID.TORAGS_PLATEBODY_75; +import static net.runelite.api.ItemID.TORAGS_PLATELEGS; +import static net.runelite.api.ItemID.TORAGS_PLATELEGS_100; +import static net.runelite.api.ItemID.TORAGS_PLATELEGS_25; +import static net.runelite.api.ItemID.TORAGS_PLATELEGS_50; +import static net.runelite.api.ItemID.TORAGS_PLATELEGS_75; +import static net.runelite.api.ItemID.TORTURE_ORNAMENT_KIT; +import static net.runelite.api.ItemID.TOXIC_BLOWPIPE; +import static net.runelite.api.ItemID.TOXIC_BLOWPIPE_EMPTY; +import static net.runelite.api.ItemID.TOXIC_STAFF_OF_THE_DEAD; +import static net.runelite.api.ItemID.TOXIC_STAFF_UNCHARGED; +import static net.runelite.api.ItemID.TREASONOUS_RING; +import static net.runelite.api.ItemID.TREASONOUS_RING_I; +import static net.runelite.api.ItemID.TRIDENT_OF_THE_SEAS; +import static net.runelite.api.ItemID.TRIDENT_OF_THE_SEAS_E; +import static net.runelite.api.ItemID.TRIDENT_OF_THE_SWAMP; +import static net.runelite.api.ItemID.TRIDENT_OF_THE_SWAMP_E; +import static net.runelite.api.ItemID.TURQUOISE_SLAYER_HELMET; +import static net.runelite.api.ItemID.TURQUOISE_SLAYER_HELMET_I; +import static net.runelite.api.ItemID.TYRANNICAL_RING; +import static net.runelite.api.ItemID.TYRANNICAL_RING_I; +import static net.runelite.api.ItemID.UNCHARGED_TOXIC_TRIDENT; +import static net.runelite.api.ItemID.UNCHARGED_TOXIC_TRIDENT_E; +import static net.runelite.api.ItemID.UNCHARGED_TRIDENT; +import static net.runelite.api.ItemID.UNCHARGED_TRIDENT_E; +import static net.runelite.api.ItemID.VERACS_BRASSARD; +import static net.runelite.api.ItemID.VERACS_BRASSARD_100; +import static net.runelite.api.ItemID.VERACS_BRASSARD_25; +import static net.runelite.api.ItemID.VERACS_BRASSARD_50; +import static net.runelite.api.ItemID.VERACS_BRASSARD_75; +import static net.runelite.api.ItemID.VERACS_FLAIL; +import static net.runelite.api.ItemID.VERACS_FLAIL_100; +import static net.runelite.api.ItemID.VERACS_FLAIL_25; +import static net.runelite.api.ItemID.VERACS_FLAIL_50; +import static net.runelite.api.ItemID.VERACS_FLAIL_75; +import static net.runelite.api.ItemID.VERACS_HELM; +import static net.runelite.api.ItemID.VERACS_HELM_100; +import static net.runelite.api.ItemID.VERACS_HELM_25; +import static net.runelite.api.ItemID.VERACS_HELM_50; +import static net.runelite.api.ItemID.VERACS_HELM_75; +import static net.runelite.api.ItemID.VERACS_PLATESKIRT; +import static net.runelite.api.ItemID.VERACS_PLATESKIRT_100; +import static net.runelite.api.ItemID.VERACS_PLATESKIRT_25; +import static net.runelite.api.ItemID.VERACS_PLATESKIRT_50; +import static net.runelite.api.ItemID.VERACS_PLATESKIRT_75; +import static net.runelite.api.ItemID.VIGGORAS_CHAINMACE; +import static net.runelite.api.ItemID.VIGGORAS_CHAINMACE_U; +import static net.runelite.api.ItemID.VOLCANIC_ABYSSAL_WHIP; +import static net.runelite.api.ItemID.WARRIOR_RING; +import static net.runelite.api.ItemID.WARRIOR_RING_I; +import static net.runelite.api.ItemID.ZAMORAK_GODSWORD; +import static net.runelite.api.ItemID.ZAMORAK_GODSWORD_OR; +import static net.runelite.api.ItemID.ZAMORAK_GODSWORD_ORNAMENT_KIT; + +/** + * Converts untradeable items to it's tradeable counterparts + */ +public enum ItemMapping +{ + // Barrows equipment + ITEM_AHRIMS_HOOD(AHRIMS_HOOD, AHRIMS_HOOD_25, AHRIMS_HOOD_50, AHRIMS_HOOD_75, AHRIMS_HOOD_100), + ITEM_AHRIMS_ROBETOP(AHRIMS_ROBETOP, AHRIMS_ROBETOP_25, AHRIMS_ROBETOP_50, AHRIMS_ROBETOP_75, AHRIMS_ROBETOP_100), + ITEM_AHRIMS_ROBEBOTTOM(AHRIMS_ROBESKIRT, AHRIMS_ROBESKIRT_25, AHRIMS_ROBESKIRT_50, AHRIMS_ROBESKIRT_75, AHRIMS_ROBESKIRT_100), + ITEM_AHRIMS_STAFF(AHRIMS_STAFF, AHRIMS_STAFF_25, AHRIMS_STAFF_50, AHRIMS_STAFF_75, AHRIMS_STAFF_100), + ITEM_KARILS_COIF(KARILS_COIF, KARILS_COIF_25, KARILS_COIF_50, KARILS_COIF_75, KARILS_COIF_100), + ITEM_KARILS_LEATHERTOP(KARILS_LEATHERTOP, KARILS_LEATHERTOP_25, KARILS_LEATHERTOP_50, KARILS_LEATHERTOP_75, KARILS_LEATHERTOP_100), + ITEM_KARILS_LEATHERSKIRT(KARILS_LEATHERSKIRT, KARILS_LEATHERSKIRT_25, KARILS_LEATHERSKIRT_50, KARILS_LEATHERSKIRT_75, KARILS_LEATHERSKIRT_100), + ITEM_KARILS_CROSSBOW(KARILS_CROSSBOW, KARILS_CROSSBOW_25, KARILS_CROSSBOW_50, KARILS_CROSSBOW_75, KARILS_CROSSBOW_100), + ITEM_DHAROKS_HELM(DHAROKS_HELM, DHAROKS_HELM_25, DHAROKS_HELM_50, DHAROKS_HELM_75, DHAROKS_HELM_100), + ITEM_DHAROKS_PLATEBODY(DHAROKS_PLATEBODY, DHAROKS_PLATEBODY_25, DHAROKS_PLATEBODY_50, DHAROKS_PLATEBODY_75, DHAROKS_PLATEBODY_100), + ITEM_DHAROKS_PLATELEGS(DHAROKS_PLATELEGS, DHAROKS_PLATELEGS_25, DHAROKS_PLATELEGS_50, DHAROKS_PLATELEGS_75, DHAROKS_PLATELEGS_100), + ITEM_DHARKS_GREATEAXE(DHAROKS_GREATAXE, DHAROKS_GREATAXE_25, DHAROKS_GREATAXE_50, DHAROKS_GREATAXE_75, DHAROKS_GREATAXE_100), + ITEM_GUTHANS_HELM(GUTHANS_HELM, GUTHANS_HELM_25, GUTHANS_HELM_50, GUTHANS_HELM_75, GUTHANS_HELM_100), + ITEM_GUTHANS_PLATEBODY(GUTHANS_PLATEBODY, GUTHANS_PLATEBODY_25, GUTHANS_PLATEBODY_50, GUTHANS_PLATEBODY_75, GUTHANS_PLATEBODY_100), + ITEM_GUTHANS_CHAINSKIRT(GUTHANS_CHAINSKIRT, GUTHANS_CHAINSKIRT_25, GUTHANS_CHAINSKIRT_50, GUTHANS_CHAINSKIRT_75, GUTHANS_CHAINSKIRT_100), + ITEM_GUTHANS_WARSPEAR(GUTHANS_WARSPEAR, GUTHANS_WARSPEAR_25, GUTHANS_WARSPEAR_50, GUTHANS_WARSPEAR_75, GUTHANS_WARSPEAR_100), + ITEM_TORAGS_HELM(TORAGS_HELM, TORAGS_HELM_25, TORAGS_HELM_50, TORAGS_HELM_75, TORAGS_HELM_100), + ITEM_TORAGS_PLATEBODY(TORAGS_PLATEBODY, TORAGS_PLATEBODY_25, TORAGS_PLATEBODY_50, TORAGS_PLATEBODY_75, TORAGS_PLATEBODY_100), + ITEM_TORAGS_PLATELEGS(TORAGS_PLATELEGS, TORAGS_PLATELEGS_25, TORAGS_PLATELEGS_50, TORAGS_PLATELEGS_75, TORAGS_PLATELEGS_100), + ITEM_TORAGS_HAMMERS(TORAGS_HAMMERS, TORAGS_HAMMERS_25, TORAGS_HAMMERS_50, TORAGS_HAMMERS_75, TORAGS_HAMMERS_100), + ITEM_VERACS_HELM(VERACS_HELM, VERACS_HELM_25, VERACS_HELM_50, VERACS_HELM_75, VERACS_HELM_100), + ITEM_VERACS_BRASSARD(VERACS_BRASSARD, VERACS_BRASSARD_25, VERACS_BRASSARD_50, VERACS_BRASSARD_75, VERACS_BRASSARD_100), + ITEM_VERACS_PLATESKIRT(VERACS_PLATESKIRT, VERACS_PLATESKIRT_25, VERACS_PLATESKIRT_50, VERACS_PLATESKIRT_75, VERACS_PLATESKIRT_100), + ITEM_VERACS_FLAIL(VERACS_FLAIL, VERACS_FLAIL_25, VERACS_FLAIL_50, VERACS_FLAIL_75, VERACS_FLAIL_100), + + // Dragon equipment ornament kits + ITEM_DRAGON_SCIMITAR(DRAGON_SCIMITAR, DRAGON_SCIMITAR_OR), + ITEM_DRAGON_SCIMITAR_ORNAMENT_KIT(DRAGON_SCIMITAR_ORNAMENT_KIT, DRAGON_SCIMITAR_OR), + ITEM_DRAGON_DEFENDER(DRAGON_DEFENDER_ORNAMENT_KIT, DRAGON_DEFENDER_T), + ITEM_DRAGON_PICKAXE(DRAGON_PICKAXE, DRAGON_PICKAXE_12797), + ITEM_DRAGON_KITESHIELD(DRAGON_KITESHIELD, DRAGON_KITESHIELD_G), + ITEM_DRAGON_KITESHIELD_ORNAMENT_KIT(DRAGON_KITESHIELD_ORNAMENT_KIT, DRAGON_KITESHIELD_G), + ITEM_DRAGON_FULL_HELM(DRAGON_FULL_HELM, DRAGON_FULL_HELM_G), + ITEM_DRAGON_FULL_HELM_ORNAMENT_KIT(DRAGON_FULL_HELM_ORNAMENT_KIT, DRAGON_FULL_HELM_G), + ITEM_DRAGON_CHAINBODY(DRAGON_CHAINBODY_3140, DRAGON_CHAINBODY_G), + ITEM_DRAGON_CHAINBODY_ORNAMENT_KIT(DRAGON_CHAINBODY_ORNAMENT_KIT, DRAGON_CHAINBODY_G), + ITEM_DRAGON_PLATEBODY(DRAGON_PLATEBODY, DRAGON_PLATEBODY_G), + ITEM_DRAGON_PLATEBODY_ORNAMENT_KIT(DRAGON_PLATEBODY_ORNAMENT_KIT, DRAGON_PLATEBODY_G), + ITEM_DRAGON_PLATESKIRT(DRAGON_PLATESKIRT, DRAGON_PLATESKIRT_G), + ITEM_DRAGON_SKIRT_ORNAMENT_KIT(DRAGON_LEGSSKIRT_ORNAMENT_KIT, DRAGON_PLATESKIRT_G), + ITEM_DRAGON_PLATELEGS(DRAGON_PLATELEGS, DRAGON_PLATELEGS_G), + ITEM_DRAGON_LEGS_ORNAMENT_KIT(DRAGON_LEGSSKIRT_ORNAMENT_KIT, DRAGON_PLATELEGS_G), + ITEM_DRAGON_SQ_SHIELD(DRAGON_SQ_SHIELD, DRAGON_SQ_SHIELD_G), + ITEM_DRAGON_SQ_SHIELD_ORNAMENT_KIT(DRAGON_SQ_SHIELD_ORNAMENT_KIT, DRAGON_SQ_SHIELD_G), + ITEM_DRAGON_BOOTS(DRAGON_BOOTS, DRAGON_BOOTS_G), + ITEM_DRAGON_BOOTS_ORNAMENT_KIT(DRAGON_BOOTS_ORNAMENT_KIT, DRAGON_BOOTS_G), + + // Godsword ornament kits + ITEM_ARMADYL_GODSWORD(ARMADYL_GODSWORD, ARMADYL_GODSWORD_OR), + ITEM_ARMADYL_GODSWORD_ORNAMENT_KIT(ARMADYL_GODSWORD_ORNAMENT_KIT, ARMADYL_GODSWORD_OR), + ITEM_BANDOS_GODSWORD(BANDOS_GODSWORD, BANDOS_GODSWORD_OR), + ITEM_BANDOS_GODSWORD_ORNAMENT_KIT(BANDOS_GODSWORD_ORNAMENT_KIT, BANDOS_GODSWORD_OR), + ITEM_ZAMORAK_GODSWORD(ZAMORAK_GODSWORD, ZAMORAK_GODSWORD_OR), + ITEM_ZAMORAK_GODSWORD_ORNAMENT_KIT(ZAMORAK_GODSWORD_ORNAMENT_KIT, ZAMORAK_GODSWORD_OR), + ITEM_SARADOMIN_GODSWORD(SARADOMIN_GODSWORD, SARADOMIN_GODSWORD_OR), + ITEM_SARADOMIN_GODSWORD_ORNAMENT_KIT(SARADOMIN_GODSWORD_ORNAMENT_KIT, SARADOMIN_GODSWORD_OR), + + // Jewellery ornament kits + ITEM_AMULET_OF_TORTURE(AMULET_OF_TORTURE, AMULET_OF_TORTURE_OR), + ITEM_TORTURE_ORNAMENT_KIT(TORTURE_ORNAMENT_KIT, AMULET_OF_TORTURE_OR), + ITEM_NECKLACE_OF_ANGUISH(NECKLACE_OF_ANGUISH, NECKLACE_OF_ANGUISH_OR), + ITEM_ANGUISH_ORNAMENT_KIT(ANGUISH_ORNAMENT_KIT, NECKLACE_OF_ANGUISH_OR), + ITEM_OCCULT_NECKLACE(OCCULT_NECKLACE, OCCULT_NECKLACE_OR), + ITEM_OCCULT_ORNAMENT_KIT(OCCULT_ORNAMENT_KIT, OCCULT_NECKLACE_OR), + ITE_AMULET_OF_FURY(AMULET_OF_FURY, AMULET_OF_FURY_OR), + ITE_FURY_ORNAMENT_KIT(FURY_ORNAMENT_KIT, AMULET_OF_FURY_OR), + + // Ensouled heads + ITEM_ENSOULED_GOBLIN_HEAD(ENSOULED_GOBLIN_HEAD_13448, ENSOULED_GOBLIN_HEAD), + ITEM_ENSOULED_MONKEY_HEAD(ENSOULED_MONKEY_HEAD_13451, ENSOULED_MONKEY_HEAD), + ITEM_ENSOULED_IMP_HEAD(ENSOULED_IMP_HEAD_13454, ENSOULED_IMP_HEAD), + ITEM_ENSOULED_MINOTAUR_HEAD(ENSOULED_MINOTAUR_HEAD_13457, ENSOULED_MINOTAUR_HEAD), + ITEM_ENSOULED_SCORPION_HEAD(ENSOULED_SCORPION_HEAD_13460, ENSOULED_SCORPION_HEAD), + ITEM_ENSOULED_BEAR_HEAD(ENSOULED_BEAR_HEAD_13463, ENSOULED_BEAR_HEAD), + ITEM_ENSOULED_UNICORN_HEAD(ENSOULED_UNICORN_HEAD_13466, ENSOULED_UNICORN_HEAD), + ITEM_ENSOULED_DOG_HEAD(ENSOULED_DOG_HEAD_13469, ENSOULED_DOG_HEAD), + ITEM_ENSOULED_CHAOS_DRUID_HEAD(ENSOULED_CHAOS_DRUID_HEAD_13472, ENSOULED_CHAOS_DRUID_HEAD), + ITEM_ENSOULED_GIANT_HEAD(ENSOULED_GIANT_HEAD_13475, ENSOULED_GIANT_HEAD), + ITEM_ENSOULED_OGRE_HEAD(ENSOULED_OGRE_HEAD_13478, ENSOULED_OGRE_HEAD), + ITEM_ENSOULED_ELF_HEAD(ENSOULED_ELF_HEAD_13481, ENSOULED_ELF_HEAD), + ITEM_ENSOULED_TROLL_HEAD(ENSOULED_TROLL_HEAD_13484, ENSOULED_TROLL_HEAD), + ITEM_ENSOULED_HORROR_HEAD(ENSOULED_HORROR_HEAD_13487, ENSOULED_HORROR_HEAD), + ITEM_ENSOULED_KALPHITE_HEAD(ENSOULED_KALPHITE_HEAD_13490, ENSOULED_KALPHITE_HEAD), + ITEM_ENSOULED_DAGANNOTH_HEAD(ENSOULED_DAGANNOTH_HEAD_13493, ENSOULED_DAGANNOTH_HEAD), + ITEM_ENSOULED_BLOODVELD_HEAD(ENSOULED_BLOODVELD_HEAD_13496, ENSOULED_BLOODVELD_HEAD), + ITEM_ENSOULED_TZHAAR_HEAD(ENSOULED_TZHAAR_HEAD_13499, ENSOULED_TZHAAR_HEAD), + ITEM_ENSOULED_DEMON_HEAD(ENSOULED_DEMON_HEAD_13502, ENSOULED_DEMON_HEAD), + ITEM_ENSOULED_AVIANSIE_HEAD(ENSOULED_AVIANSIE_HEAD_13505, ENSOULED_AVIANSIE_HEAD), + ITEM_ENSOULED_ABYSSAL_HEAD(ENSOULED_ABYSSAL_HEAD_13508, ENSOULED_ABYSSAL_HEAD), + ITEM_ENSOULED_DRAGON_HEAD(ENSOULED_DRAGON_HEAD_13511, ENSOULED_DRAGON_HEAD), + + // Imbued rings + ITEM_BERSERKER_RING(BERSERKER_RING, BERSERKER_RING_I), + ITEM_SEERS_RING(SEERS_RING, SEERS_RING_I), + ITEM_WARRIOR_RING(WARRIOR_RING, WARRIOR_RING_I), + ITEM_ARCHERS_RING(ARCHERS_RING, ARCHERS_RING_I), + ITEM_TREASONOUS_RING(TREASONOUS_RING, TREASONOUS_RING_I), + ITEM_TYRANNICAL_RING(TYRANNICAL_RING, TYRANNICAL_RING_I), + ITEM_RING_OF_THE_GODS(RING_OF_THE_GODS, RING_OF_THE_GODS_I), + ITEM_RING_OF_SUFFERING(RING_OF_SUFFERING, RING_OF_SUFFERING_I, RING_OF_SUFFERING_R, RING_OF_SUFFERING_RI), + ITEM_GRANITE_RING(GRANITE_RING, GRANITE_RING_I), + + // Bounty hunter + ITEM_GRANITE_MAUL(GRANITE_MAUL, GRANITE_MAUL_12848), + ITEM_MAGIC_SHORTBOW(MAGIC_SHORTBOW, MAGIC_SHORTBOW_I), + ITEM_SARADOMINS_BLESSED_SWORD(SARADOMINS_TEAR, SARADOMINS_BLESSED_SWORD), + + // Jewellery with charges + ITEM_RING_OF_WEALTH(RING_OF_WEALTH, RING_OF_WEALTH_I, RING_OF_WEALTH_1, RING_OF_WEALTH_I1, RING_OF_WEALTH_2, RING_OF_WEALTH_I2, RING_OF_WEALTH_3, RING_OF_WEALTH_I3, RING_OF_WEALTH_4, RING_OF_WEALTH_I4, RING_OF_WEALTH_I5), + ITEM_AMULET_OF_GLORY(AMULET_OF_GLORY, AMULET_OF_GLORY1, AMULET_OF_GLORY2, AMULET_OF_GLORY3, AMULET_OF_GLORY5), + ITEM_AMULET_OF_GLORY_T(AMULET_OF_GLORY_T, AMULET_OF_GLORY_T1, AMULET_OF_GLORY_T2, AMULET_OF_GLORY_T3, AMULET_OF_GLORY_T5), + ITEM_SKILLS_NECKLACE(SKILLS_NECKLACE, SKILLS_NECKLACE1, SKILLS_NECKLACE2, SKILLS_NECKLACE3, SKILLS_NECKLACE5), + ITEM_RING_OF_DUELING(RING_OF_DUELING8, RING_OF_DUELING1, RING_OF_DUELING2, RING_OF_DUELING3, RING_OF_DUELING4, RING_OF_DUELING5, RING_OF_DUELING6, RING_OF_DUELING7), + ITEM_GAMES_NECKLACE(GAMES_NECKLACE8, GAMES_NECKLACE1, GAMES_NECKLACE2, GAMES_NECKLACE3, GAMES_NECKLACE4, GAMES_NECKLACE5, GAMES_NECKLACE6, GAMES_NECKLACE7), + + // Degradable/charged weaponry/armour + ITEM_ABYSSAL_WHIP(ABYSSAL_WHIP, VOLCANIC_ABYSSAL_WHIP, FROZEN_ABYSSAL_WHIP), + ITEM_KRAKEN_TENTACLE(KRAKEN_TENTACLE, ABYSSAL_TENTACLE), + ITEM_TRIDENT_OF_THE_SEAS(UNCHARGED_TRIDENT, TRIDENT_OF_THE_SEAS), + ITEM_TRIDENT_OF_THE_SEAS_E(UNCHARGED_TRIDENT_E, TRIDENT_OF_THE_SEAS_E), + ITEM_TRIDENT_OF_THE_SWAMP(UNCHARGED_TOXIC_TRIDENT, TRIDENT_OF_THE_SWAMP), + ITEM_TRIDENT_OF_THE_SWAMP_E(UNCHARGED_TOXIC_TRIDENT_E, TRIDENT_OF_THE_SWAMP_E), + ITEM_TOXIC_BLOWPIPE(TOXIC_BLOWPIPE_EMPTY, TOXIC_BLOWPIPE), + ITEM_TOXIC_STAFF_OFF_THE_DEAD(TOXIC_STAFF_UNCHARGED, TOXIC_STAFF_OF_THE_DEAD), + ITEM_SERPENTINE_HELM(SERPENTINE_HELM_UNCHARGED, SERPENTINE_HELM, TANZANITE_HELM_UNCHARGED, TANZANITE_HELM, MAGMA_HELM_UNCHARGED, MAGMA_HELM), + ITEM_DRAGONFIRE_SHIELD(DRAGONFIRE_SHIELD_11284, DRAGONFIRE_SHIELD), + ITEM_DRAGONFIRE_WARD(DRAGONFIRE_WARD_22003, DRAGONFIRE_WARD), + ITEM_ANCIENT_WYVERN_SHIELD(ANCIENT_WYVERN_SHIELD_21634, ANCIENT_WYVERN_SHIELD), + ITEM_SANGUINESTI_STAFF(SANGUINESTI_STAFF_UNCHARGED, SANGUINESTI_STAFF), + ITEM_SCYTHE_OF_VITUR(SCYTHE_OF_VITUR_UNCHARGED, SCYTHE_OF_VITUR), + ITEM_TOME_OF_FIRE(TOME_OF_FIRE_EMPTY, TOME_OF_FIRE), + ITEM_CRAWS_BOW(CRAWS_BOW_U, CRAWS_BOW), + ITEM_VIGGORAS_CHAINMACE(VIGGORAS_CHAINMACE_U, VIGGORAS_CHAINMACE), + ITEM_THAMMARONS_SCEPTRE(THAMMARONS_SCEPTRE_U, THAMMARONS_SCEPTRE), + + // Infinity colour kits + ITEM_INFINITY_TOP(INFINITY_TOP, INFINITY_TOP_10605, INFINITY_TOP_20574, DARK_INFINITY_TOP, LIGHT_INFINITY_TOP), + ITEM_INFINITY_TOP_LIGHT_COLOUR_KIT(LIGHT_INFINITY_COLOUR_KIT, LIGHT_INFINITY_TOP), + ITEM_INFINITY_TOP_DARK_COLOUR_KIT(DARK_INFINITY_COLOUR_KIT, DARK_INFINITY_TOP), + ITEM_INFINITY_BOTTOMS(INFINITY_BOTTOMS, INFINITY_BOTTOMS_20575, DARK_INFINITY_BOTTOMS, LIGHT_INFINITY_BOTTOMS), + ITEM_INFINITY_BOTTOMS_LIGHT_COLOUR_KIT(LIGHT_INFINITY_COLOUR_KIT, LIGHT_INFINITY_BOTTOMS), + ITEM_INFINITY_BOTTOMS_DARK_COLOUR_KIT(DARK_INFINITY_COLOUR_KIT, DARK_INFINITY_BOTTOMS), + ITEM_INFINITY_HAT(INFINITY_HAT, DARK_INFINITY_HAT, LIGHT_INFINITY_HAT), + ITEM_INFINITY_HAT_LIGHT_COLOUR_KIT(LIGHT_INFINITY_COLOUR_KIT, LIGHT_INFINITY_HAT), + ITEM_INFINITY_HAT_DARK_COLOUR_KIT(DARK_INFINITY_COLOUR_KIT, DARK_INFINITY_HAT), + + // Miscellaneous ornament kits + ITEM_DARK_BOW(DARK_BOW, DARK_BOW_12765, DARK_BOW_12766, DARK_BOW_12767, DARK_BOW_12768, DARK_BOW_20408), + ITEM_ODIUM_WARD(ODIUM_WARD, ODIUM_WARD_12807), + ITEM_MALEDICTION_WARD(MALEDICTION_WARD, MALEDICTION_WARD_12806), + ITEM_STEAM_BATTLESTAFF(STEAM_BATTLESTAFF, STEAM_BATTLESTAFF_12795), + ITEM_LAVA_BATTLESTAFF(LAVA_BATTLESTAFF, LAVA_BATTLESTAFF_21198), + + // Slayer helm/black mask + ITEM_BLACK_MASK( + BLACK_MASK, BLACK_MASK_I, BLACK_MASK_1, BLACK_MASK_1_I, BLACK_MASK_2, BLACK_MASK_2_I, BLACK_MASK_3, BLACK_MASK_3_I, BLACK_MASK_4, BLACK_MASK_4_I, BLACK_MASK_5, + BLACK_MASK_5_I, BLACK_MASK_6, BLACK_MASK_6_I, BLACK_MASK_7, BLACK_MASK_7_I, BLACK_MASK_8, BLACK_MASK_8_I, BLACK_MASK_9, BLACK_MASK_9_I, BLACK_MASK_10_I, + SLAYER_HELMET, SLAYER_HELMET_I, BLACK_SLAYER_HELMET, BLACK_SLAYER_HELMET_I, PURPLE_SLAYER_HELMET, PURPLE_SLAYER_HELMET_I, RED_SLAYER_HELMET, RED_SLAYER_HELMET_I, + GREEN_SLAYER_HELMET, GREEN_SLAYER_HELMET_I, TURQUOISE_SLAYER_HELMET, TURQUOISE_SLAYER_HELMET_I, HYDRA_SLAYER_HELMET, HYDRA_SLAYER_HELMET_I), + + // Pharaoh's Sceptres + ITEM_PHARAOHS_SCEPTRE_1(PHARAOHS_SCEPTRE, PHARAOHS_SCEPTRE_1), + ITEM_PHARAOHS_SCEPTRE_2(PHARAOHS_SCEPTRE, PHARAOHS_SCEPTRE_2), + ITEM_PHARAOHS_SCEPTRE_4(PHARAOHS_SCEPTRE, PHARAOHS_SCEPTRE_4), + ITEM_PHARAOHS_SCEPTRE_5(PHARAOHS_SCEPTRE, PHARAOHS_SCEPTRE_5), + ITEM_PHARAOHS_SCEPTRE_6(PHARAOHS_SCEPTRE, PHARAOHS_SCEPTRE_6), + ITEM_PHARAOHS_SCEPTRE_7(PHARAOHS_SCEPTRE, PHARAOHS_SCEPTRE_7), + ITEM_PHARAOHS_SCEPTRE_8(PHARAOHS_SCEPTRE, PHARAOHS_SCEPTRE_8), + + // Revertible items + ITEM_HYDRA_LEATHER(HYDRA_LEATHER, FEROCIOUS_GLOVES), + ITEM_HYDRA_TAIL(HYDRA_TAIL, BONECRUSHER_NECKLACE), + ITEM_DRAGONBONE_NECKLACE(DRAGONBONE_NECKLACE, BONECRUSHER_NECKLACE), + ITEM_BOTTOMLESS_COMPOST_BUCKET(BOTTOMLESS_COMPOST_BUCKET, BOTTOMLESS_COMPOST_BUCKET_22997); + + private static final Multimap MAPPINGS = HashMultimap.create(); + private final int tradeableItem; + private final int[] untradableItems; + + static + { + for (final ItemMapping item : values()) + { + for (int itemId : item.untradableItems) + { + MAPPINGS.put(itemId, item.tradeableItem); + } + } + } + + ItemMapping(int tradeableItem, int... untradableItems) + { + this.tradeableItem = tradeableItem; + this.untradableItems = untradableItems; + } + + /** + * Get collection of items that are mapped from single item id. + * + * @param itemId the item id + * @return the collection + */ + public static Collection map(int itemId) + { + final Collection mapping = MAPPINGS.get(itemId); + + if (mapping == null || mapping.isEmpty()) + { + return Collections.singleton(itemId); + } + + return mapping; + } + + /** + * Map an item from its untradeable version to its tradeable version + * + * @param itemId + * @return + */ + public static int mapFirst(int itemId) + { + final Collection mapping = MAPPINGS.get(itemId); + + if (mapping == null || mapping.isEmpty()) + { + return itemId; + } + + return mapping.iterator().next(); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/game/NPCManager.java b/runelite-client/src/main/java/net/runelite/client/game/NPCManager.java index f34d2c13ee..36693e289f 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/NPCManager.java +++ b/runelite-client/src/main/java/net/runelite/client/game/NPCManager.java @@ -1,65 +1,66 @@ -/* - * Copyright (c) 2018, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.game; - -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.lang.reflect.Type; -import java.util.Map; -import javax.annotation.Nullable; -import javax.inject.Inject; -import javax.inject.Singleton; - -@Singleton -public class NPCManager -{ - private final Map healthMap; - - @Inject - private NPCManager() - { - final Gson gson = new Gson(); - final Type typeToken = new TypeToken>() - { - }.getType(); - - final InputStream healthFile = getClass().getResourceAsStream("/npc_health.json"); - healthMap = gson.fromJson(new InputStreamReader(healthFile), typeToken); - } - - /** - * Returns health for target NPC based on it's combat level and name - * @param name npc name - * @param combatLevel npc combat level - * @return health or null if HP is unknown - */ - @Nullable - public Integer getHealth(final String name, final int combatLevel) - { - return healthMap.get(name + "_" + combatLevel); - } -} +/* + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.game; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.reflect.Type; +import java.util.Map; +import javax.annotation.Nullable; +import javax.inject.Inject; +import javax.inject.Singleton; + +@Singleton +public class NPCManager +{ + private final Map healthMap; + + @Inject + private NPCManager() + { + final Gson gson = new Gson(); + final Type typeToken = new TypeToken>() + { + }.getType(); + + final InputStream healthFile = getClass().getResourceAsStream("/npc_health.json"); + healthMap = gson.fromJson(new InputStreamReader(healthFile), typeToken); + } + + /** + * Returns health for target NPC based on it's combat level and name + * + * @param name npc name + * @param combatLevel npc combat level + * @return health or null if HP is unknown + */ + @Nullable + public Integer getHealth(final String name, final int combatLevel) + { + return healthMap.get(name + "_" + combatLevel); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxPanelManager.java b/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxPanelManager.java index ff23bb2cda..0504929cfb 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxPanelManager.java +++ b/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxPanelManager.java @@ -1,202 +1,202 @@ -/* - * Copyright (c) 2018 Abex - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.game.chatbox; - -import com.google.inject.Inject; -import com.google.inject.Provider; -import com.google.inject.Singleton; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.Client; -import net.runelite.api.GameState; -import net.runelite.api.ScriptID; -import net.runelite.api.VarClientInt; -import net.runelite.api.events.GameStateChanged; -import net.runelite.api.events.ScriptCallbackEvent; -import net.runelite.api.vars.InputType; -import net.runelite.api.widgets.JavaScriptCallback; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.client.callback.ClientThread; -import net.runelite.client.eventbus.EventBus; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.input.KeyListener; -import net.runelite.client.input.KeyManager; -import net.runelite.client.input.MouseListener; -import net.runelite.client.input.MouseManager; -import net.runelite.client.input.MouseWheelListener; - -@Singleton -@Slf4j -public class ChatboxPanelManager -{ - private final Client client; - private final ClientThread clientThread; - private final EventBus eventBus; - - private final KeyManager keyManager; - private final MouseManager mouseManager; - - private final Provider chatboxTextMenuInputProvider; - private final Provider chatboxTextInputProvider; - - @Getter - private ChatboxInput currentInput = null; - - @Inject - private ChatboxPanelManager(EventBus eventBus, Client client, ClientThread clientThread, - KeyManager keyManager, MouseManager mouseManager, - Provider chatboxTextMenuInputProvider, Provider chatboxTextInputProvider) - { - this.client = client; - this.clientThread = clientThread; - this.eventBus = eventBus; - - this.keyManager = keyManager; - this.mouseManager = mouseManager; - - this.chatboxTextMenuInputProvider = chatboxTextMenuInputProvider; - this.chatboxTextInputProvider = chatboxTextInputProvider; - } - - public void close() - { - clientThread.invokeLater(this::unsafeCloseInput); - } - - private void unsafeCloseInput() - { - client.runScript( - ScriptID.RESET_CHATBOX_INPUT, - 0, - 1 - ); - if (currentInput != null) - { - killCurrentPanel(); - } - } - - private void unsafeOpenInput(ChatboxInput input) - { - client.runScript(ScriptID.CLEAR_CHATBOX_PANEL); - - eventBus.register(input); - if (input instanceof KeyListener) - { - keyManager.registerKeyListener((KeyListener) input); - } - if (input instanceof MouseListener) - { - mouseManager.registerMouseListener((MouseListener) input); - } - if (input instanceof MouseWheelListener) - { - mouseManager.registerMouseWheelListener((MouseWheelListener) input); - } - - if (currentInput != null) - { - killCurrentPanel(); - } - - currentInput = input; - client.setVar(VarClientInt.INPUT_TYPE, InputType.RUNELITE_CHATBOX_PANEL.getType()); - client.getWidget(WidgetInfo.CHATBOX_TITLE).setHidden(true); - client.getWidget(WidgetInfo.CHATBOX_FULL_INPUT).setHidden(true); - - Widget c = getContainerWidget(); - c.deleteAllChildren(); - c.setOnDialogAbortListener((JavaScriptCallback) ev -> this.unsafeCloseInput()); - input.open(); - } - - public void openInput(ChatboxInput input) - { - clientThread.invokeLater(() -> unsafeOpenInput(input)); - } - - public ChatboxTextMenuInput openTextMenuInput(String title) - { - return chatboxTextMenuInputProvider.get() - .title(title); - } - - public ChatboxTextInput openTextInput(String prompt) - { - return chatboxTextInputProvider.get() - .prompt(prompt); - } - - @Subscribe - public void onScriptCallbackEvent(ScriptCallbackEvent ev) - { - if (currentInput != null && "resetChatboxInput".equals(ev.getEventName())) - { - killCurrentPanel(); - } - } - - @Subscribe - private void onGameStateChanged(GameStateChanged ev) - { - if (currentInput != null && ev.getGameState() == GameState.LOGIN_SCREEN) - { - killCurrentPanel(); - } - } - - private void killCurrentPanel() - { - try - { - currentInput.close(); - } - catch (Exception e) - { - log.warn("Exception closing {}", currentInput.getClass(), e); - } - - eventBus.unregister(currentInput); - if (currentInput instanceof KeyListener) - { - keyManager.unregisterKeyListener((KeyListener) currentInput); - } - if (currentInput instanceof MouseListener) - { - mouseManager.unregisterMouseListener((MouseListener) currentInput); - } - if (currentInput instanceof MouseWheelListener) - { - mouseManager.unregisterMouseWheelListener((MouseWheelListener) currentInput); - } - currentInput = null; - } - - public Widget getContainerWidget() - { - return client.getWidget(WidgetInfo.CHATBOX_CONTAINER); - } -} +/* + * Copyright (c) 2018 Abex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.game.chatbox; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.Singleton; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.ScriptID; +import net.runelite.api.VarClientInt; +import net.runelite.api.events.GameStateChanged; +import net.runelite.api.events.ScriptCallbackEvent; +import net.runelite.api.vars.InputType; +import net.runelite.api.widgets.JavaScriptCallback; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.callback.ClientThread; +import net.runelite.client.eventbus.EventBus; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.input.KeyListener; +import net.runelite.client.input.KeyManager; +import net.runelite.client.input.MouseListener; +import net.runelite.client.input.MouseManager; +import net.runelite.client.input.MouseWheelListener; + +@Singleton +@Slf4j +public class ChatboxPanelManager +{ + private final Client client; + private final ClientThread clientThread; + private final EventBus eventBus; + + private final KeyManager keyManager; + private final MouseManager mouseManager; + + private final Provider chatboxTextMenuInputProvider; + private final Provider chatboxTextInputProvider; + + @Getter + private ChatboxInput currentInput = null; + + @Inject + private ChatboxPanelManager(EventBus eventBus, Client client, ClientThread clientThread, + KeyManager keyManager, MouseManager mouseManager, + Provider chatboxTextMenuInputProvider, Provider chatboxTextInputProvider) + { + this.client = client; + this.clientThread = clientThread; + this.eventBus = eventBus; + + this.keyManager = keyManager; + this.mouseManager = mouseManager; + + this.chatboxTextMenuInputProvider = chatboxTextMenuInputProvider; + this.chatboxTextInputProvider = chatboxTextInputProvider; + } + + public void close() + { + clientThread.invokeLater(this::unsafeCloseInput); + } + + private void unsafeCloseInput() + { + client.runScript( + ScriptID.RESET_CHATBOX_INPUT, + 0, + 1 + ); + if (currentInput != null) + { + killCurrentPanel(); + } + } + + private void unsafeOpenInput(ChatboxInput input) + { + client.runScript(ScriptID.CLEAR_CHATBOX_PANEL); + + eventBus.register(input); + if (input instanceof KeyListener) + { + keyManager.registerKeyListener((KeyListener) input); + } + if (input instanceof MouseListener) + { + mouseManager.registerMouseListener((MouseListener) input); + } + if (input instanceof MouseWheelListener) + { + mouseManager.registerMouseWheelListener((MouseWheelListener) input); + } + + if (currentInput != null) + { + killCurrentPanel(); + } + + currentInput = input; + client.setVar(VarClientInt.INPUT_TYPE, InputType.RUNELITE_CHATBOX_PANEL.getType()); + client.getWidget(WidgetInfo.CHATBOX_TITLE).setHidden(true); + client.getWidget(WidgetInfo.CHATBOX_FULL_INPUT).setHidden(true); + + Widget c = getContainerWidget(); + c.deleteAllChildren(); + c.setOnDialogAbortListener((JavaScriptCallback) ev -> this.unsafeCloseInput()); + input.open(); + } + + public void openInput(ChatboxInput input) + { + clientThread.invokeLater(() -> unsafeOpenInput(input)); + } + + public ChatboxTextMenuInput openTextMenuInput(String title) + { + return chatboxTextMenuInputProvider.get() + .title(title); + } + + public ChatboxTextInput openTextInput(String prompt) + { + return chatboxTextInputProvider.get() + .prompt(prompt); + } + + @Subscribe + public void onScriptCallbackEvent(ScriptCallbackEvent ev) + { + if (currentInput != null && "resetChatboxInput".equals(ev.getEventName())) + { + killCurrentPanel(); + } + } + + @Subscribe + private void onGameStateChanged(GameStateChanged ev) + { + if (currentInput != null && ev.getGameState() == GameState.LOGIN_SCREEN) + { + killCurrentPanel(); + } + } + + private void killCurrentPanel() + { + try + { + currentInput.close(); + } + catch (Exception e) + { + log.warn("Exception closing {}", currentInput.getClass(), e); + } + + eventBus.unregister(currentInput); + if (currentInput instanceof KeyListener) + { + keyManager.unregisterKeyListener((KeyListener) currentInput); + } + if (currentInput instanceof MouseListener) + { + mouseManager.unregisterMouseListener((MouseListener) currentInput); + } + if (currentInput instanceof MouseWheelListener) + { + mouseManager.unregisterMouseWheelListener((MouseWheelListener) currentInput); + } + currentInput = null; + } + + public Widget getContainerWidget() + { + return client.getWidget(WidgetInfo.CHATBOX_CONTAINER); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextMenuInput.java b/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextMenuInput.java index 51e5e7dfde..c634c0fa2b 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextMenuInput.java +++ b/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextMenuInput.java @@ -1,213 +1,213 @@ -/* - * Copyright (c) 2018 Abex - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.game.chatbox; - -import com.google.inject.Inject; -import java.awt.event.KeyEvent; -import java.util.ArrayList; -import java.util.List; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.FontID; -import net.runelite.api.widgets.WidgetType; -import net.runelite.api.widgets.JavaScriptCallback; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetPositionMode; -import net.runelite.api.widgets.WidgetSizeMode; -import net.runelite.api.widgets.WidgetTextAlignment; -import net.runelite.client.input.KeyListener; - -@Slf4j -public class ChatboxTextMenuInput extends ChatboxInput implements KeyListener -{ - @Data - @AllArgsConstructor - private static final class Entry - { - private String text; - private Runnable callback; - } - - private final ChatboxPanelManager chatboxPanelManager; - - @Getter - private String title; - - @Getter - private List options = new ArrayList<>(); - - @Getter - private Runnable onClose; - - @Inject - protected ChatboxTextMenuInput(ChatboxPanelManager chatboxPanelManager) - { - this.chatboxPanelManager = chatboxPanelManager; - } - - public ChatboxTextMenuInput title(String title) - { - this.title = title; - return this; - } - - public ChatboxTextMenuInput option(String text, Runnable callback) - { - options.add(new Entry(text, callback)); - return this; - } - - public ChatboxTextMenuInput onClose(Runnable onClose) - { - this.onClose = onClose; - return this; - } - - public ChatboxTextMenuInput build() - { - if (title == null) - { - throw new IllegalStateException("Title must be set"); - } - - if (options.size() < 1) - { - throw new IllegalStateException("You must have atleast 1 option"); - } - - chatboxPanelManager.openInput(this); - return this; - } - - @Override - protected void open() - { - Widget container = chatboxPanelManager.getContainerWidget(); - - Widget prompt = container.createChild(-1, WidgetType.TEXT); - prompt.setText(title); - prompt.setTextColor(0x800000); - prompt.setFontId(FontID.QUILL_8); - prompt.setXPositionMode(WidgetPositionMode.ABSOLUTE_CENTER); - prompt.setOriginalX(0); - prompt.setYPositionMode(WidgetPositionMode.ABSOLUTE_TOP); - prompt.setOriginalY(8); - prompt.setOriginalHeight(24); - prompt.setXTextAlignment(WidgetTextAlignment.CENTER); - prompt.setYTextAlignment(WidgetTextAlignment.CENTER); - prompt.setWidthMode(WidgetSizeMode.MINUS); - prompt.revalidate(); - - int y = prompt.getRelativeX() + prompt.getHeight() + 6; - int height = container.getHeight() - y - 8; - int step = height / options.size(); - int maxStep = options.size() >= 3 ? 25 : 30; - if (step > maxStep) - { - int ds = step - maxStep; - step = maxStep; - y += (ds * options.size()) / 2; - } - - for (Entry option : options) - { - Widget optWidget = container.createChild(-1, WidgetType.TEXT); - optWidget.setText(option.text); - optWidget.setFontId(FontID.QUILL_8); - optWidget.setXPositionMode(WidgetPositionMode.ABSOLUTE_CENTER); - optWidget.setOriginalX(0); - optWidget.setYPositionMode(WidgetPositionMode.ABSOLUTE_TOP); - optWidget.setOriginalY(y); - optWidget.setOriginalHeight(24); - optWidget.setXTextAlignment(WidgetTextAlignment.CENTER); - optWidget.setYTextAlignment(WidgetTextAlignment.CENTER); - optWidget.setWidthMode(WidgetSizeMode.MINUS); - optWidget.setAction(0, "Continue"); - optWidget.setOnOpListener((JavaScriptCallback) ev -> callback(option)); - optWidget.setOnMouseOverListener((JavaScriptCallback) ev -> optWidget.setTextColor(0xFFFFFF)); - optWidget.setOnMouseLeaveListener((JavaScriptCallback) ev -> optWidget.setTextColor(0)); - optWidget.setHasListener(true); - optWidget.revalidate(); - - y += step; - } - } - - private void callback(Entry entry) - { - Widget container = chatboxPanelManager.getContainerWidget(); - container.setOnKeyListener((Object[]) null); - - chatboxPanelManager.close(); - - entry.callback.run(); - } - - @Override - protected void close() - { - if (onClose != null) - { - onClose.run(); - } - } - - - @Override - public void keyTyped(KeyEvent e) - { - char c = e.getKeyChar(); - - if (c == '\033') - { - chatboxPanelManager.close(); - e.consume(); - return; - } - - int n = c - '1'; - if (n >= 0 && n < options.size()) - { - callback(options.get(n)); - e.consume(); - } - } - - @Override - public void keyPressed(KeyEvent e) - { - if (e.getKeyCode() == KeyEvent.VK_ESCAPE) - { - e.consume(); - } - } - - @Override - public void keyReleased(KeyEvent e) - { - } -} +/* + * Copyright (c) 2018 Abex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.game.chatbox; + +import com.google.inject.Inject; +import java.awt.event.KeyEvent; +import java.util.ArrayList; +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.FontID; +import net.runelite.api.widgets.JavaScriptCallback; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetPositionMode; +import net.runelite.api.widgets.WidgetSizeMode; +import net.runelite.api.widgets.WidgetTextAlignment; +import net.runelite.api.widgets.WidgetType; +import net.runelite.client.input.KeyListener; + +@Slf4j +public class ChatboxTextMenuInput extends ChatboxInput implements KeyListener +{ + @Data + @AllArgsConstructor + private static final class Entry + { + private String text; + private Runnable callback; + } + + private final ChatboxPanelManager chatboxPanelManager; + + @Getter + private String title; + + @Getter + private List options = new ArrayList<>(); + + @Getter + private Runnable onClose; + + @Inject + protected ChatboxTextMenuInput(ChatboxPanelManager chatboxPanelManager) + { + this.chatboxPanelManager = chatboxPanelManager; + } + + public ChatboxTextMenuInput title(String title) + { + this.title = title; + return this; + } + + public ChatboxTextMenuInput option(String text, Runnable callback) + { + options.add(new Entry(text, callback)); + return this; + } + + public ChatboxTextMenuInput onClose(Runnable onClose) + { + this.onClose = onClose; + return this; + } + + public ChatboxTextMenuInput build() + { + if (title == null) + { + throw new IllegalStateException("Title must be set"); + } + + if (options.size() < 1) + { + throw new IllegalStateException("You must have atleast 1 option"); + } + + chatboxPanelManager.openInput(this); + return this; + } + + @Override + protected void open() + { + Widget container = chatboxPanelManager.getContainerWidget(); + + Widget prompt = container.createChild(-1, WidgetType.TEXT); + prompt.setText(title); + prompt.setTextColor(0x800000); + prompt.setFontId(FontID.QUILL_8); + prompt.setXPositionMode(WidgetPositionMode.ABSOLUTE_CENTER); + prompt.setOriginalX(0); + prompt.setYPositionMode(WidgetPositionMode.ABSOLUTE_TOP); + prompt.setOriginalY(8); + prompt.setOriginalHeight(24); + prompt.setXTextAlignment(WidgetTextAlignment.CENTER); + prompt.setYTextAlignment(WidgetTextAlignment.CENTER); + prompt.setWidthMode(WidgetSizeMode.MINUS); + prompt.revalidate(); + + int y = prompt.getRelativeX() + prompt.getHeight() + 6; + int height = container.getHeight() - y - 8; + int step = height / options.size(); + int maxStep = options.size() >= 3 ? 25 : 30; + if (step > maxStep) + { + int ds = step - maxStep; + step = maxStep; + y += (ds * options.size()) / 2; + } + + for (Entry option : options) + { + Widget optWidget = container.createChild(-1, WidgetType.TEXT); + optWidget.setText(option.text); + optWidget.setFontId(FontID.QUILL_8); + optWidget.setXPositionMode(WidgetPositionMode.ABSOLUTE_CENTER); + optWidget.setOriginalX(0); + optWidget.setYPositionMode(WidgetPositionMode.ABSOLUTE_TOP); + optWidget.setOriginalY(y); + optWidget.setOriginalHeight(24); + optWidget.setXTextAlignment(WidgetTextAlignment.CENTER); + optWidget.setYTextAlignment(WidgetTextAlignment.CENTER); + optWidget.setWidthMode(WidgetSizeMode.MINUS); + optWidget.setAction(0, "Continue"); + optWidget.setOnOpListener((JavaScriptCallback) ev -> callback(option)); + optWidget.setOnMouseOverListener((JavaScriptCallback) ev -> optWidget.setTextColor(0xFFFFFF)); + optWidget.setOnMouseLeaveListener((JavaScriptCallback) ev -> optWidget.setTextColor(0)); + optWidget.setHasListener(true); + optWidget.revalidate(); + + y += step; + } + } + + private void callback(Entry entry) + { + Widget container = chatboxPanelManager.getContainerWidget(); + container.setOnKeyListener((Object[]) null); + + chatboxPanelManager.close(); + + entry.callback.run(); + } + + @Override + protected void close() + { + if (onClose != null) + { + onClose.run(); + } + } + + + @Override + public void keyTyped(KeyEvent e) + { + char c = e.getKeyChar(); + + if (c == '\033') + { + chatboxPanelManager.close(); + e.consume(); + return; + } + + int n = c - '1'; + if (n >= 0 && n < options.size()) + { + callback(options.get(n)); + e.consume(); + } + } + + @Override + public void keyPressed(KeyEvent e) + { + if (e.getKeyCode() == KeyEvent.VK_ESCAPE) + { + e.consume(); + } + } + + @Override + public void keyReleased(KeyEvent e) + { + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/graphics/ModelOutlineRenderer.java b/runelite-client/src/main/java/net/runelite/client/graphics/ModelOutlineRenderer.java index a1a0cb0c99..e4d80fbb64 100644 --- a/runelite-client/src/main/java/net/runelite/client/graphics/ModelOutlineRenderer.java +++ b/runelite-client/src/main/java/net/runelite/client/graphics/ModelOutlineRenderer.java @@ -743,7 +743,7 @@ public class ModelOutlineRenderer * @param outerColor The color of the pixels of the outline furthest away from the model */ private void renderOutline(BufferedImage image, int outlineWidth, - Color innerColor, Color outerColor) + Color innerColor, Color outerColor) { int[] imageData = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); List ps = getPriorityList(outlineWidth); @@ -887,8 +887,8 @@ public class ModelOutlineRenderer * @param outerColor The color of the pixels of the outline furthest away from the model */ private void drawModelOutline(Model model, - int localX, int localY, int localZ, int orientation, - int outlineWidth, Color innerColor, Color outerColor) + int localX, int localY, int localZ, int orientation, + int outlineWidth, Color innerColor, Color outerColor) { if (outlineWidth <= 0) { diff --git a/runelite-client/src/main/java/net/runelite/client/menus/WidgetMenuOption.java b/runelite-client/src/main/java/net/runelite/client/menus/WidgetMenuOption.java index 307551542c..1737486363 100644 --- a/runelite-client/src/main/java/net/runelite/client/menus/WidgetMenuOption.java +++ b/runelite-client/src/main/java/net/runelite/client/menus/WidgetMenuOption.java @@ -1,106 +1,105 @@ -/* - * Copyright (c) 2017, Robin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.menus; - -import net.runelite.api.widgets.WidgetInfo; - -import java.awt.Color; -import net.runelite.client.ui.JagexColors; -import net.runelite.client.util.ColorUtil; - -public final class WidgetMenuOption -{ - /** - * The left hand text to be displayed on the menu option. Ex. the menuOption of "Drop Bones" is "Drop" - */ - private String menuOption; - /** - * The right hand text to be displayed on the menu option Ex. the menuTarget of "Drop Bones" is "Bones" - */ - private String menuTarget; - /** - * The color that the menuTarget should be. Defaults to the brownish color that most menu options have. - */ - private Color color = JagexColors.MENU_TARGET; - - /** - * The widget to add the option to - */ - private final WidgetInfo widget; - - /** - * Creates a menu to be added to right click menus. The menu will only be added if match is found within the menu options - * - * @param menuOption Option text of this right click option - * @param menuTarget Target text of this right click option - * @param widget The widget to attach this option to - */ - public WidgetMenuOption(String menuOption, String menuTarget, WidgetInfo widget) - { - this.menuOption = menuOption; - setMenuTarget(menuTarget); - this.widget = widget; - } - - public void setMenuOption(String option) - { - menuOption = option; - } - - /** - * Sets the target of the menu option. Color code will be added on to target - * - * @param target The target text without color code. - */ - public void setMenuTarget(String target) - { - menuTarget = ColorUtil.wrapWithColorTag(target, color); - } - - public String getMenuOption() - { - return menuOption; - } - - public String getMenuTarget() - { - return menuTarget; - } - - public WidgetInfo getWidget() - { - return widget; - } - - public Color getColor() - { - return color; - } - - public void setColor(Color col) - { - color = col; - } -} +/* + * Copyright (c) 2017, Robin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.menus; + +import java.awt.Color; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.ui.JagexColors; +import net.runelite.client.util.ColorUtil; + +public final class WidgetMenuOption +{ + /** + * The left hand text to be displayed on the menu option. Ex. the menuOption of "Drop Bones" is "Drop" + */ + private String menuOption; + /** + * The right hand text to be displayed on the menu option Ex. the menuTarget of "Drop Bones" is "Bones" + */ + private String menuTarget; + /** + * The color that the menuTarget should be. Defaults to the brownish color that most menu options have. + */ + private Color color = JagexColors.MENU_TARGET; + + /** + * The widget to add the option to + */ + private final WidgetInfo widget; + + /** + * Creates a menu to be added to right click menus. The menu will only be added if match is found within the menu options + * + * @param menuOption Option text of this right click option + * @param menuTarget Target text of this right click option + * @param widget The widget to attach this option to + */ + public WidgetMenuOption(String menuOption, String menuTarget, WidgetInfo widget) + { + this.menuOption = menuOption; + setMenuTarget(menuTarget); + this.widget = widget; + } + + public void setMenuOption(String option) + { + menuOption = option; + } + + /** + * Sets the target of the menu option. Color code will be added on to target + * + * @param target The target text without color code. + */ + public void setMenuTarget(String target) + { + menuTarget = ColorUtil.wrapWithColorTag(target, color); + } + + public String getMenuOption() + { + return menuOption; + } + + public String getMenuTarget() + { + return menuTarget; + } + + public WidgetInfo getWidget() + { + return widget; + } + + public Color getColor() + { + return color; + } + + public void setColor(Color col) + { + color = col; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/blackjack/BlackjackPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/blackjack/BlackjackPlugin.java index c3a8a0876b..0bbac48f60 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/blackjack/BlackjackPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/blackjack/BlackjackPlugin.java @@ -59,11 +59,11 @@ public class BlackjackPlugin extends Plugin @Inject Client client; - private static long timeSinceKnockout; - private static long timeSinceAggro; + private long timeSinceKnockout; + private long timeSinceAggro; @Getter - private static long currentGameTick; + private long currentGameTick; @Override public void configure(Binder binder) @@ -109,7 +109,7 @@ public class BlackjackPlugin extends Plugin public void onMenuEntryAdded(MenuEntryAdded menuEntryAdded) { String target = menuEntryAdded.getTarget().toLowerCase(); - if ((target.contains("bandit") | target.contains("menaphite thug"))) + if ((target.contains("bandit") || target.contains("menaphite thug"))) { Quest quest = Quest.THE_FEUD; if (quest.getState(client) == QuestState.FINISHED) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/combatlevel/CombatLevelOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/combatlevel/CombatLevelOverlay.java index 3e811a60d2..95bc61fbb8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/combatlevel/CombatLevelOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/combatlevel/CombatLevelOverlay.java @@ -99,7 +99,7 @@ class CombatLevelOverlay extends Overlay int prayerLevel = client.getRealSkillLevel(Skill.PRAYER); // calculate initial required numbers - double base = DEF_HP_MULT * (defenceLevel + hitpointsLevel + Math.floor(prayerLevel / 2)); + double base = DEF_HP_MULT * (defenceLevel + hitpointsLevel + Math.floor(prayerLevel / 2D)); double melee = ATT_STR_MULT * (attackLevel + strengthLevel); double range = RANGE_MAGIC_MULT * Math.floor(rangedLevel * RANGE_MAGIC_LEVEL_MULT); double mage = RANGE_MAGIC_MULT * Math.floor(magicLevel * RANGE_MAGIC_LEVEL_MULT); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginListItem.java b/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginListItem.java index 9481a9f1f6..c52d85a575 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginListItem.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginListItem.java @@ -123,7 +123,7 @@ public class PluginListItem extends JPanel * if there is no configuration associated with the plugin. */ PluginListItem(ConfigPanel configPanel, ConfigManager configManager, Plugin plugin, PluginDescriptor descriptor, - @Nullable Config config, @Nullable ConfigDescriptor configDescriptor) + @Nullable Config config, @Nullable ConfigDescriptor configDescriptor) { this(configPanel, configManager, plugin, config, configDescriptor, descriptor.name(), descriptor.description(), descriptor.tags()); @@ -133,13 +133,13 @@ public class PluginListItem extends JPanel * Creates a new {@code PluginListItem} for a core configuration. */ PluginListItem(ConfigPanel configPanel, ConfigManager configManager, Config config, ConfigDescriptor configDescriptor, - String name, String description, String... tags) + String name, String description, String... tags) { this(configPanel, configManager, null, config, configDescriptor, name, description, tags); } private PluginListItem(ConfigPanel configPanel, ConfigManager configManager, @Nullable Plugin plugin, @Nullable Config config, - @Nullable ConfigDescriptor configDescriptor, String name, String description, String... tags) + @Nullable ConfigDescriptor configDescriptor, String name, String description, String... tags) { this.configPanel = configPanel; this.configManager = configManager; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/DemonicGorillaPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/DemonicGorillaPlugin.java index e0bc04dfad..c9424703d7 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/DemonicGorillaPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/demonicgorilla/DemonicGorillaPlugin.java @@ -156,7 +156,7 @@ public class DemonicGorillaPlugin extends Plugin } private void checkGorillaAttackStyleSwitch(DemonicGorilla gorilla, - final DemonicGorilla.AttackStyle... protectedStyles) + final DemonicGorilla.AttackStyle... protectedStyles) { if (gorilla.getAttacksUntilSwitch() <= 0 || gorilla.getNextPosibleAttackStyles().isEmpty()) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java index 6ad12ca97a..35e942382c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/easyscape/EasyscapePlugin.java @@ -357,11 +357,11 @@ public class EasyscapePlugin extends Plugin } } - if (config.getGlory()) - { - if (target.toLowerCase().contains("amulet of glory") || target.toLowerCase().contains("amulet of eternal glory")) - { - switch (config.getGloryMode()) + if (config.getGlory()) + { + if (target.toLowerCase().contains("amulet of glory") || target.toLowerCase().contains("amulet of eternal glory")) + { + switch (config.getGloryMode()) { case EDGEVILLE: swap(client, GloryMode.EDGEVILLE.toString(), option, target); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/PrayerTracker.java b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/PrayerTracker.java index 13228de07b..dacc526a19 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/PrayerTracker.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimers/PrayerTracker.java @@ -66,10 +66,7 @@ public class PrayerTracker } if (actor instanceof Player) { - if (actor instanceof Player) - { - newTick.get(actor).put("PrayerIcon", ((Player) actor).getOverheadIcon() == null ? -1 : ((Player) actor).getOverheadIcon().ordinal()); - } + newTick.get(actor).put("PrayerIcon", ((Player) actor).getOverheadIcon() == null ? -1 : ((Player) actor).getOverheadIcon().ordinal()); } newTick.get(actor).put("SpotAnim", actor.getGraphic()); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/friendtagging/FriendTaggingPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/friendtagging/FriendTaggingPlugin.java index 896363e681..ea0f90d53a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/friendtagging/FriendTaggingPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/friendtagging/FriendTaggingPlugin.java @@ -53,7 +53,7 @@ import org.apache.commons.lang3.ArrayUtils; ) public class FriendTaggingPlugin extends Plugin { - public static ConcurrentHashMap taggedFriends = new ConcurrentHashMap<>(); + public static final ConcurrentHashMap taggedFriends = new ConcurrentHashMap<>(); private static final String CONFIG_GROUP = "friendtagging"; private static final int CHARACTER_LIMIT = 30; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java index 449f1b5441..f16275a13f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java @@ -718,8 +718,8 @@ public class GpuPlugin extends Plugin implements DrawCallbacks } public void drawScenePaint(int orientation, int pitchSin, int pitchCos, int yawSin, int yawCos, int x, int y, int z, - SceneTilePaint paint, int tileZ, int tileX, int tileY, - int zoom, int centerX, int centerY) + SceneTilePaint paint, int tileZ, int tileX, int tileY, + int zoom, int centerX, int centerY) { if (paint.getBufferLen() > 0) { @@ -744,8 +744,8 @@ public class GpuPlugin extends Plugin implements DrawCallbacks } public void drawSceneModel(int orientation, int pitchSin, int pitchCos, int yawSin, int yawCos, int x, int y, int z, - SceneTileModel model, int tileZ, int tileX, int tileY, - int zoom, int centerX, int centerY) + SceneTileModel model, int tileZ, int tileX, int tileY, + int zoom, int centerX, int centerY) { if (model.getBufferLen() > 0) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/InstanceMapOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/InstanceMapOverlay.java index c25ecf6771..df475162d7 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/InstanceMapOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/InstanceMapOverlay.java @@ -214,7 +214,7 @@ class InstanceMapOverlay extends Overlay * @param graphics graphics to be drawn to */ private void drawPlayerDot(Graphics2D graphics, Player player, - Color dotColor, Color outlineColor) + Color dotColor, Color outlineColor) { LocalPoint playerLoc = player.getLocalLocation(); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupContainerPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupContainerPanel.java index 2db6e0de45..c2f1db70b8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupContainerPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupContainerPanel.java @@ -1,130 +1,130 @@ -/* - * Copyright (c) 2018, https://runelitepl.us - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.plugins.inventorysetups.ui; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.util.ArrayList; -import javax.swing.JLabel; -import javax.swing.JPanel; -import net.runelite.client.game.AsyncBufferedImage; -import net.runelite.client.game.ItemManager; -import net.runelite.client.game.ItemVariationMapping; -import net.runelite.client.plugins.inventorysetups.InventorySetupConfig; -import net.runelite.client.plugins.inventorysetups.InventorySetupItem; -import net.runelite.client.plugins.inventorysetups.InventorySetupPlugin; -import net.runelite.client.ui.ColorScheme; - -public abstract class InventorySetupContainerPanel extends JPanel -{ - protected ItemManager itemManager; - - private final InventorySetupPlugin plugin; - - InventorySetupContainerPanel(final ItemManager itemManager, final InventorySetupPlugin plugin, String captionText) - { - this.itemManager = itemManager; - this.plugin = plugin; - JPanel containerPanel = new JPanel(); - - final JPanel containerSlotsPanel = new JPanel(); - - setupContainerPanel(containerSlotsPanel); - - // caption - final JLabel caption = new JLabel(captionText); - caption.setHorizontalAlignment(JLabel.CENTER); - caption.setVerticalAlignment(JLabel.CENTER); - - // panel that holds the caption and any other graphics - final JPanel captionPanel = new JPanel(); - captionPanel.add(caption); - - containerPanel.setLayout(new BorderLayout()); - containerPanel.add(captionPanel, BorderLayout.NORTH); - containerPanel.add(containerSlotsPanel, BorderLayout.CENTER); - - add(containerPanel); - } - - void setContainerSlot(int index, - final InventorySetupSlot containerSlot, - final ArrayList items) - { - if (index >= items.size() || items.get(index).getId() == -1) - { - containerSlot.setImageLabel(null, null); - return; - } - - int itemId = items.get(index).getId(); - int quantity = items.get(index).getQuantity(); - final String itemName = items.get(index).getName(); - AsyncBufferedImage itemImg = itemManager.getImage(itemId, quantity, quantity > 1); - String toolTip = itemName; - if (quantity > 1) - { - toolTip += " (" + quantity + ")"; - } - containerSlot.setImageLabel(toolTip, itemImg); - } - - void highlightDifferentSlotColor(InventorySetupItem savedItem, - InventorySetupItem currItem, - final InventorySetupSlot containerSlot) - { - // important note: do not use item names for comparisons - // they are all empty to avoid clientThread usage when highlighting - - final InventorySetupConfig config = plugin.getConfig(); - final Color highlightColor = config.getHighlightColor(); - - if (config.getStackDifference() && currItem.getQuantity() != savedItem.getQuantity()) - { - containerSlot.setBackground(highlightColor); - return; - } - - int currId = currItem.getId(); - int checkId = savedItem.getId(); - - if (!config.getVariationDifference()) - { - currId = ItemVariationMapping.map(currId); - checkId = ItemVariationMapping.map(checkId); - } - - if (currId != checkId) - { - containerSlot.setBackground(highlightColor); - return; - } - - // set the color back to the original, because they match - containerSlot.setBackground(ColorScheme.DARKER_GRAY_COLOR); - } - - abstract public void setupContainerPanel(final JPanel containerSlotsPanel); +/* + * Copyright (c) 2018, https://runelitepl.us + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.plugins.inventorysetups.ui; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.util.ArrayList; +import javax.swing.JLabel; +import javax.swing.JPanel; +import net.runelite.client.game.AsyncBufferedImage; +import net.runelite.client.game.ItemManager; +import net.runelite.client.game.ItemVariationMapping; +import net.runelite.client.plugins.inventorysetups.InventorySetupConfig; +import net.runelite.client.plugins.inventorysetups.InventorySetupItem; +import net.runelite.client.plugins.inventorysetups.InventorySetupPlugin; +import net.runelite.client.ui.ColorScheme; + +public abstract class InventorySetupContainerPanel extends JPanel +{ + protected ItemManager itemManager; + + private final InventorySetupPlugin plugin; + + InventorySetupContainerPanel(final ItemManager itemManager, final InventorySetupPlugin plugin, String captionText) + { + this.itemManager = itemManager; + this.plugin = plugin; + JPanel containerPanel = new JPanel(); + + final JPanel containerSlotsPanel = new JPanel(); + + setupContainerPanel(containerSlotsPanel); + + // caption + final JLabel caption = new JLabel(captionText); + caption.setHorizontalAlignment(JLabel.CENTER); + caption.setVerticalAlignment(JLabel.CENTER); + + // panel that holds the caption and any other graphics + final JPanel captionPanel = new JPanel(); + captionPanel.add(caption); + + containerPanel.setLayout(new BorderLayout()); + containerPanel.add(captionPanel, BorderLayout.NORTH); + containerPanel.add(containerSlotsPanel, BorderLayout.CENTER); + + add(containerPanel); + } + + void setContainerSlot(int index, + final InventorySetupSlot containerSlot, + final ArrayList items) + { + if (index >= items.size() || items.get(index).getId() == -1) + { + containerSlot.setImageLabel(null, null); + return; + } + + int itemId = items.get(index).getId(); + int quantity = items.get(index).getQuantity(); + final String itemName = items.get(index).getName(); + AsyncBufferedImage itemImg = itemManager.getImage(itemId, quantity, quantity > 1); + String toolTip = itemName; + if (quantity > 1) + { + toolTip += " (" + quantity + ")"; + } + containerSlot.setImageLabel(toolTip, itemImg); + } + + void highlightDifferentSlotColor(InventorySetupItem savedItem, + InventorySetupItem currItem, + final InventorySetupSlot containerSlot) + { + // important note: do not use item names for comparisons + // they are all empty to avoid clientThread usage when highlighting + + final InventorySetupConfig config = plugin.getConfig(); + final Color highlightColor = config.getHighlightColor(); + + if (config.getStackDifference() && currItem.getQuantity() != savedItem.getQuantity()) + { + containerSlot.setBackground(highlightColor); + return; + } + + int currId = currItem.getId(); + int checkId = savedItem.getId(); + + if (!config.getVariationDifference()) + { + currId = ItemVariationMapping.map(currId); + checkId = ItemVariationMapping.map(checkId); + } + + if (currId != checkId) + { + containerSlot.setBackground(highlightColor); + return; + } + + // set the color back to the original, because they match + containerSlot.setBackground(ColorScheme.DARKER_GRAY_COLOR); + } + + abstract public void setupContainerPanel(final JPanel containerSlotsPanel); } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupPluginPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupPluginPanel.java index d81a29ece8..67f2504c32 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupPluginPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/inventorysetups/ui/InventorySetupPluginPanel.java @@ -1,307 +1,307 @@ -/* - * Copyright (c) 2018, https://runelitepl.us - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.plugins.inventorysetups.ui; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.FlowLayout; -import java.awt.event.ItemEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.image.BufferedImage; -import java.util.ArrayList; -import javax.swing.Box; -import javax.swing.BoxLayout; -import javax.swing.ImageIcon; -import javax.swing.JComboBox; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.border.EmptyBorder; -import net.runelite.api.InventoryID; -import net.runelite.client.game.ItemManager; -import net.runelite.client.plugins.inventorysetups.InventorySetup; -import net.runelite.client.plugins.inventorysetups.InventorySetupItem; -import net.runelite.client.plugins.inventorysetups.InventorySetupPlugin; -import net.runelite.client.ui.PluginPanel; -import net.runelite.client.ui.components.PluginErrorPanel; -import net.runelite.client.util.ImageUtil; - -public class InventorySetupPluginPanel extends PluginPanel -{ - private static ImageIcon ADD_ICON; - private static ImageIcon ADD_HOVER_ICON; - private static ImageIcon REMOVE_ICON; - private static ImageIcon REMOVE_HOVER_ICON; - - private final JPanel noSetupsPanel; - private final JPanel invEqPanel; - - private final InventorySetupInventoryPanel invPanel; - private final InventorySetupEquipmentPanel eqpPanel; - - private final JComboBox setupComboBox; - - private final JLabel removeMarker; - - private final InventorySetupPlugin plugin; - - static - { - final BufferedImage addIcon = ImageUtil.getResourceStreamFromClass(InventorySetupPlugin.class, "add_icon.png"); - ADD_ICON = new ImageIcon(addIcon); - ADD_HOVER_ICON = new ImageIcon(ImageUtil.alphaOffset(addIcon, 0.53f)); - - final BufferedImage removeIcon = ImageUtil.getResourceStreamFromClass(InventorySetupPlugin.class, "remove_icon.png"); - REMOVE_ICON = new ImageIcon(removeIcon); - REMOVE_HOVER_ICON = new ImageIcon(ImageUtil.alphaOffset(removeIcon, 0.53f)); - } - - public InventorySetupPluginPanel(final InventorySetupPlugin plugin, final ItemManager itemManager) - { - super(false); - this.plugin = plugin; - this.removeMarker = new JLabel(REMOVE_ICON); - this.invPanel = new InventorySetupInventoryPanel(itemManager, plugin); - this.eqpPanel = new InventorySetupEquipmentPanel(itemManager, plugin); - this.noSetupsPanel = new JPanel(); - this.invEqPanel = new JPanel(); - this.setupComboBox = new JComboBox<>(); - - // setup the title - final JLabel addMarker = new JLabel(ADD_ICON); - final JLabel title = new JLabel(); - title.setText("Inventory Setups"); - title.setForeground(Color.WHITE); - - // setup the add marker (+ sign in the top right) - addMarker.setToolTipText("Add a new inventory setup"); - addMarker.addMouseListener(new MouseAdapter() - { - @Override - public void mouseClicked(MouseEvent e) - { - plugin.addInventorySetup(); - } - - @Override - public void mouseEntered(MouseEvent e) - { - addMarker.setIcon(ADD_HOVER_ICON); - } - - @Override - public void mouseExited(MouseEvent e) - { - addMarker.setIcon(ADD_ICON); - } - }); - - // setup the remove marker (X sign in the top right) - removeMarker.setToolTipText("Remove the current inventory setup"); - removeMarker.addMouseListener(new MouseAdapter() - { - @Override - public void mouseClicked(MouseEvent e) - { - final String name = (String) setupComboBox.getSelectedItem(); - plugin.removeInventorySetup(name, true); - } - - @Override - public void mouseEntered(MouseEvent e) - { - if (removeMarker.isEnabled()) - { - removeMarker.setIcon(REMOVE_HOVER_ICON); - } - } - - @Override - public void mouseExited(MouseEvent e) - { - removeMarker.setIcon(REMOVE_ICON); - } - }); - - // setup the combo box for selection switching - // add empty to indicate the empty position - setupComboBox.addItem(""); - setupComboBox.setSelectedIndex(0); - setupComboBox.addItemListener(e -> - { - if (e.getStateChange() == ItemEvent.SELECTED) - { - String selection = (String) e.getItem(); - setCurrentInventorySetup(selection); - } - }); - - // the panel on the top right that holds the add and delete buttons - final JPanel markersPanel = new JPanel(); - markersPanel.setLayout(new FlowLayout(FlowLayout.RIGHT, 10, 0)); - markersPanel.add(removeMarker); - markersPanel.add(addMarker); - - // the top panel that has the title and the buttons - final JPanel titleAndMarkersPanel = new JPanel(); - titleAndMarkersPanel.setLayout(new BorderLayout()); - titleAndMarkersPanel.add(title, BorderLayout.WEST); - titleAndMarkersPanel.add(markersPanel, BorderLayout.EAST); - - // the panel that stays at the top and doesn't scroll - // contains the title, buttons, and the combo box - final JPanel northAnchoredPanel = new JPanel(); - northAnchoredPanel.setLayout(new BoxLayout(northAnchoredPanel, BoxLayout.Y_AXIS)); - northAnchoredPanel.setBorder(new EmptyBorder(0, 0, 10, 0)); - northAnchoredPanel.add(titleAndMarkersPanel); - northAnchoredPanel.add(Box.createRigidArea(new Dimension(0, 10))); - northAnchoredPanel.add(setupComboBox); - - // the panel that holds the inventory and equipment panels - final BoxLayout invEqLayout = new BoxLayout(invEqPanel, BoxLayout.Y_AXIS); - invEqPanel.setLayout(invEqLayout); - invEqPanel.add(invPanel); - invEqPanel.add(Box.createRigidArea(new Dimension(0, 10))); - invEqPanel.add(eqpPanel); - - // setup the error panel. It's wrapped around a normal panel - // so it doesn't stretch to fill the parent panel - final PluginErrorPanel errorPanel = new PluginErrorPanel(); - errorPanel.setContent("Inventory Setups", "Select or create an inventory setup."); - noSetupsPanel.add(errorPanel); - - // the panel that holds the inventory panels, and the error panel - final JPanel contentPanel = new JPanel(); - final BoxLayout contentLayout = new BoxLayout(contentPanel, BoxLayout.Y_AXIS); - contentPanel.setLayout(contentLayout); - contentPanel.add(invEqPanel); - contentPanel.add(noSetupsPanel); - - // wrapper for the main content panel to keep it from stretching - final JPanel contentWrapper = new JPanel(new BorderLayout()); - contentWrapper.add(Box.createGlue(), BorderLayout.CENTER); - contentWrapper.add(contentPanel, BorderLayout.NORTH); - final JScrollPane contentWrapperPane = new JScrollPane(contentWrapper); - contentWrapperPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); - - setLayout(new BorderLayout()); - setBorder(new EmptyBorder(10, 10, 10, 10)); - add(northAnchoredPanel, BorderLayout.NORTH); - add(contentWrapperPane, BorderLayout.CENTER); - - // show the no setups panel on startup - showNoSetupsPanel(); - - } - - public void showNoSetupsPanel() - { - setupComboBox.setSelectedIndex(0); - removeMarker.setEnabled(false); - noSetupsPanel.setVisible(true); - invEqPanel.setVisible(false); - } - - private void showHasSetupPanel(final String name) - { - setupComboBox.setSelectedItem(name); - removeMarker.setEnabled(true); - noSetupsPanel.setVisible(false); - invEqPanel.setVisible(true); - } - - public void setCurrentInventorySetup(final String name) - { - if (name.isEmpty()) - { - showNoSetupsPanel(); - return; - } - - showHasSetupPanel(name); - - final InventorySetup inventorySetup = plugin.getInventorySetup(name); - - invPanel.setInventorySetupSlots(inventorySetup); - eqpPanel.setEquipmentSetupSlots(inventorySetup); - - if (plugin.getHighlightDifference()) - { - final ArrayList normInv = plugin.getNormalizedContainer(InventoryID.INVENTORY); - final ArrayList normEqp = plugin.getNormalizedContainer(InventoryID.EQUIPMENT); - - highlightDifferences(normInv, inventorySetup, InventoryID.INVENTORY); - highlightDifferences(normEqp, inventorySetup, InventoryID.EQUIPMENT); - } - else - { - invPanel.resetInventorySlotsColor(); - eqpPanel.resetEquipmentSlotsColor(); - } - - validate(); - repaint(); - } - - public void addInventorySetup(final String name) - { - setupComboBox.addItem(name); - } - - public void removeInventorySetup(final String name) - { - setupComboBox.removeItem(name); - showNoSetupsPanel(); - - invPanel.resetInventorySlotsColor(); - eqpPanel.resetEquipmentSlotsColor(); - - validate(); - repaint(); - } - - public void highlightDifferences(final ArrayList container, - final InventorySetup setupToCheck, - final InventoryID type) - { - switch (type) - { - case INVENTORY: - invPanel.highlightDifferentSlots(container, setupToCheck); - break; - - case EQUIPMENT: - eqpPanel.highlightDifferences(container, setupToCheck); - break; - } - } - - public final String getSelectedInventorySetup() - { - return (String) setupComboBox.getSelectedItem(); - } +/* + * Copyright (c) 2018, https://runelitepl.us + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.plugins.inventorysetups.ui; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.event.ItemEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.image.BufferedImage; +import java.util.ArrayList; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.ImageIcon; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.border.EmptyBorder; +import net.runelite.api.InventoryID; +import net.runelite.client.game.ItemManager; +import net.runelite.client.plugins.inventorysetups.InventorySetup; +import net.runelite.client.plugins.inventorysetups.InventorySetupItem; +import net.runelite.client.plugins.inventorysetups.InventorySetupPlugin; +import net.runelite.client.ui.PluginPanel; +import net.runelite.client.ui.components.PluginErrorPanel; +import net.runelite.client.util.ImageUtil; + +public class InventorySetupPluginPanel extends PluginPanel +{ + private static ImageIcon ADD_ICON; + private static ImageIcon ADD_HOVER_ICON; + private static ImageIcon REMOVE_ICON; + private static ImageIcon REMOVE_HOVER_ICON; + + private final JPanel noSetupsPanel; + private final JPanel invEqPanel; + + private final InventorySetupInventoryPanel invPanel; + private final InventorySetupEquipmentPanel eqpPanel; + + private final JComboBox setupComboBox; + + private final JLabel removeMarker; + + private final InventorySetupPlugin plugin; + + static + { + final BufferedImage addIcon = ImageUtil.getResourceStreamFromClass(InventorySetupPlugin.class, "add_icon.png"); + ADD_ICON = new ImageIcon(addIcon); + ADD_HOVER_ICON = new ImageIcon(ImageUtil.alphaOffset(addIcon, 0.53f)); + + final BufferedImage removeIcon = ImageUtil.getResourceStreamFromClass(InventorySetupPlugin.class, "remove_icon.png"); + REMOVE_ICON = new ImageIcon(removeIcon); + REMOVE_HOVER_ICON = new ImageIcon(ImageUtil.alphaOffset(removeIcon, 0.53f)); + } + + public InventorySetupPluginPanel(final InventorySetupPlugin plugin, final ItemManager itemManager) + { + super(false); + this.plugin = plugin; + this.removeMarker = new JLabel(REMOVE_ICON); + this.invPanel = new InventorySetupInventoryPanel(itemManager, plugin); + this.eqpPanel = new InventorySetupEquipmentPanel(itemManager, plugin); + this.noSetupsPanel = new JPanel(); + this.invEqPanel = new JPanel(); + this.setupComboBox = new JComboBox<>(); + + // setup the title + final JLabel addMarker = new JLabel(ADD_ICON); + final JLabel title = new JLabel(); + title.setText("Inventory Setups"); + title.setForeground(Color.WHITE); + + // setup the add marker (+ sign in the top right) + addMarker.setToolTipText("Add a new inventory setup"); + addMarker.addMouseListener(new MouseAdapter() + { + @Override + public void mouseClicked(MouseEvent e) + { + plugin.addInventorySetup(); + } + + @Override + public void mouseEntered(MouseEvent e) + { + addMarker.setIcon(ADD_HOVER_ICON); + } + + @Override + public void mouseExited(MouseEvent e) + { + addMarker.setIcon(ADD_ICON); + } + }); + + // setup the remove marker (X sign in the top right) + removeMarker.setToolTipText("Remove the current inventory setup"); + removeMarker.addMouseListener(new MouseAdapter() + { + @Override + public void mouseClicked(MouseEvent e) + { + final String name = (String) setupComboBox.getSelectedItem(); + plugin.removeInventorySetup(name, true); + } + + @Override + public void mouseEntered(MouseEvent e) + { + if (removeMarker.isEnabled()) + { + removeMarker.setIcon(REMOVE_HOVER_ICON); + } + } + + @Override + public void mouseExited(MouseEvent e) + { + removeMarker.setIcon(REMOVE_ICON); + } + }); + + // setup the combo box for selection switching + // add empty to indicate the empty position + setupComboBox.addItem(""); + setupComboBox.setSelectedIndex(0); + setupComboBox.addItemListener(e -> + { + if (e.getStateChange() == ItemEvent.SELECTED) + { + String selection = (String) e.getItem(); + setCurrentInventorySetup(selection); + } + }); + + // the panel on the top right that holds the add and delete buttons + final JPanel markersPanel = new JPanel(); + markersPanel.setLayout(new FlowLayout(FlowLayout.RIGHT, 10, 0)); + markersPanel.add(removeMarker); + markersPanel.add(addMarker); + + // the top panel that has the title and the buttons + final JPanel titleAndMarkersPanel = new JPanel(); + titleAndMarkersPanel.setLayout(new BorderLayout()); + titleAndMarkersPanel.add(title, BorderLayout.WEST); + titleAndMarkersPanel.add(markersPanel, BorderLayout.EAST); + + // the panel that stays at the top and doesn't scroll + // contains the title, buttons, and the combo box + final JPanel northAnchoredPanel = new JPanel(); + northAnchoredPanel.setLayout(new BoxLayout(northAnchoredPanel, BoxLayout.Y_AXIS)); + northAnchoredPanel.setBorder(new EmptyBorder(0, 0, 10, 0)); + northAnchoredPanel.add(titleAndMarkersPanel); + northAnchoredPanel.add(Box.createRigidArea(new Dimension(0, 10))); + northAnchoredPanel.add(setupComboBox); + + // the panel that holds the inventory and equipment panels + final BoxLayout invEqLayout = new BoxLayout(invEqPanel, BoxLayout.Y_AXIS); + invEqPanel.setLayout(invEqLayout); + invEqPanel.add(invPanel); + invEqPanel.add(Box.createRigidArea(new Dimension(0, 10))); + invEqPanel.add(eqpPanel); + + // setup the error panel. It's wrapped around a normal panel + // so it doesn't stretch to fill the parent panel + final PluginErrorPanel errorPanel = new PluginErrorPanel(); + errorPanel.setContent("Inventory Setups", "Select or create an inventory setup."); + noSetupsPanel.add(errorPanel); + + // the panel that holds the inventory panels, and the error panel + final JPanel contentPanel = new JPanel(); + final BoxLayout contentLayout = new BoxLayout(contentPanel, BoxLayout.Y_AXIS); + contentPanel.setLayout(contentLayout); + contentPanel.add(invEqPanel); + contentPanel.add(noSetupsPanel); + + // wrapper for the main content panel to keep it from stretching + final JPanel contentWrapper = new JPanel(new BorderLayout()); + contentWrapper.add(Box.createGlue(), BorderLayout.CENTER); + contentWrapper.add(contentPanel, BorderLayout.NORTH); + final JScrollPane contentWrapperPane = new JScrollPane(contentWrapper); + contentWrapperPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + + setLayout(new BorderLayout()); + setBorder(new EmptyBorder(10, 10, 10, 10)); + add(northAnchoredPanel, BorderLayout.NORTH); + add(contentWrapperPane, BorderLayout.CENTER); + + // show the no setups panel on startup + showNoSetupsPanel(); + + } + + public void showNoSetupsPanel() + { + setupComboBox.setSelectedIndex(0); + removeMarker.setEnabled(false); + noSetupsPanel.setVisible(true); + invEqPanel.setVisible(false); + } + + private void showHasSetupPanel(final String name) + { + setupComboBox.setSelectedItem(name); + removeMarker.setEnabled(true); + noSetupsPanel.setVisible(false); + invEqPanel.setVisible(true); + } + + public void setCurrentInventorySetup(final String name) + { + if (name.isEmpty()) + { + showNoSetupsPanel(); + return; + } + + showHasSetupPanel(name); + + final InventorySetup inventorySetup = plugin.getInventorySetup(name); + + invPanel.setInventorySetupSlots(inventorySetup); + eqpPanel.setEquipmentSetupSlots(inventorySetup); + + if (plugin.getHighlightDifference()) + { + final ArrayList normInv = plugin.getNormalizedContainer(InventoryID.INVENTORY); + final ArrayList normEqp = plugin.getNormalizedContainer(InventoryID.EQUIPMENT); + + highlightDifferences(normInv, inventorySetup, InventoryID.INVENTORY); + highlightDifferences(normEqp, inventorySetup, InventoryID.EQUIPMENT); + } + else + { + invPanel.resetInventorySlotsColor(); + eqpPanel.resetEquipmentSlotsColor(); + } + + validate(); + repaint(); + } + + public void addInventorySetup(final String name) + { + setupComboBox.addItem(name); + } + + public void removeInventorySetup(final String name) + { + setupComboBox.removeItem(name); + showNoSetupsPanel(); + + invPanel.resetInventorySlotsColor(); + eqpPanel.resetEquipmentSlotsColor(); + + validate(); + repaint(); + } + + public void highlightDifferences(final ArrayList container, + final InventorySetup setupToCheck, + final InventoryID type) + { + switch (type) + { + case INVENTORY: + invPanel.highlightDifferentSlots(container, setupToCheck); + break; + + case EQUIPMENT: + eqpPanel.highlightDifferences(container, setupToCheck); + break; + } + } + + public final String getSelectedInventorySetup() + { + return (String) setupComboBox.getSelectedItem(); + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatPlugin.java index d38b28dccc..02a2ae844c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatPlugin.java @@ -214,13 +214,9 @@ public class ItemStatPlugin extends Plugin closeButton.setSpriteId(SpriteID.BOTTOM_LINE_MODE_WINDOW_CLOSE_BUTTON_SMALL); closeButton.setAction(0, "Close"); closeButton.setOnMouseOverListener((JavaScriptCallback) (ev) -> - { - closeButton.setSpriteId(SpriteID.BOTTOM_LINE_MODE_WINDOW_CLOSE_BUTTON_SMALL_HOVERED); - }); + closeButton.setSpriteId(SpriteID.BOTTOM_LINE_MODE_WINDOW_CLOSE_BUTTON_SMALL_HOVERED)); closeButton.setOnMouseLeaveListener((JavaScriptCallback) (ev) -> - { - closeButton.setSpriteId(SpriteID.BOTTOM_LINE_MODE_WINDOW_CLOSE_BUTTON_SMALL); - }); + closeButton.setSpriteId(SpriteID.BOTTOM_LINE_MODE_WINDOW_CLOSE_BUTTON_SMALL)); closeButton.setOnOpListener((JavaScriptCallback) (ev) -> resetGEInventory()); closeButton.setHasListener(true); closeButton.revalidate(); @@ -349,7 +345,7 @@ public class ItemStatPlugin extends Plugin } private static Widget createText(Widget parent, String text, int fontId, int textColor, - int x, int y, int width, int height) + int x, int y, int width, int height) { final Widget widget = parent.createChild(-1, WidgetType.TEXT); widget.setText(text); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/mta/graveyard/GraveyardRoom.java b/runelite-client/src/main/java/net/runelite/client/plugins/mta/graveyard/GraveyardRoom.java index 8d823f40e8..89956cf89c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/mta/graveyard/GraveyardRoom.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/mta/graveyard/GraveyardRoom.java @@ -60,7 +60,7 @@ public class GraveyardRoom extends MTARoom @Inject private GraveyardRoom(MTAConfig config, Client client, MTAPlugin plugin, - ItemManager itemManager, InfoBoxManager infoBoxManager) + ItemManager itemManager, InfoBoxManager infoBoxManager) { super(config); this.client = client; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsConfig.java index ffeccd7def..24ce90e561 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsConfig.java @@ -266,9 +266,9 @@ public interface PlayerIndicatorsConfig extends Config description = "The location of the skull icon for skulled players", group = "Target Indicator" ) - default PlayerIndicatorsPlugin.minimapSkullLocations skullLocation() + default PlayerIndicatorsPlugin.MinimapSkullLocations skullLocation() { - return PlayerIndicatorsPlugin.minimapSkullLocations.AFTER_NAME; + return PlayerIndicatorsPlugin.MinimapSkullLocations.AFTER_NAME; } @ConfigItem( diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsMinimapOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsMinimapOverlay.java index 32f4b3c07b..e356d9b5f2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsMinimapOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsMinimapOverlay.java @@ -97,7 +97,7 @@ public class PlayerIndicatorsMinimapOverlay extends Overlay { int width = graphics.getFontMetrics().stringWidth(name); int height = graphics.getFontMetrics().getHeight(); - if (config.skullLocation().equals(PlayerIndicatorsPlugin.minimapSkullLocations.AFTER_NAME)) + if (config.skullLocation().equals(PlayerIndicatorsPlugin.MinimapSkullLocations.AFTER_NAME)) { OverlayUtil.renderImageLocation(graphics, new Point(minimapLocation.getX() + width, minimapLocation.getY() - height), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsOverlay.java index 6f2aff1484..9876dc9647 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsOverlay.java @@ -217,7 +217,7 @@ public class PlayerIndicatorsOverlay extends Overlay { int width = graphics.getFontMetrics().stringWidth(name); int height = graphics.getFontMetrics().getHeight(); - if (config.skullLocation().equals(PlayerIndicatorsPlugin.minimapSkullLocations.AFTER_NAME)) + if (config.skullLocation().equals(PlayerIndicatorsPlugin.MinimapSkullLocations.AFTER_NAME)) { OverlayUtil.renderImageLocation(graphics, new Point(textLocation.getX() + width, textLocation.getY() - height), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java index e1c62de125..6b3dfc3d4e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsPlugin.java @@ -365,7 +365,7 @@ public class PlayerIndicatorsPlugin extends Plugin } } - public enum minimapSkullLocations + public enum MinimapSkullLocations { BEFORE_NAME, AFTER_NAME diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/playerinfo/PlayerInfoCustomIndicator.java b/runelite-client/src/main/java/net/runelite/client/plugins/playerinfo/PlayerInfoCustomIndicator.java index b76a0b9b52..e43e486112 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/playerinfo/PlayerInfoCustomIndicator.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/playerinfo/PlayerInfoCustomIndicator.java @@ -100,6 +100,7 @@ public class PlayerInfoCustomIndicator extends InfoBox break; case SPECIAL: currLvl = client.getVar(VarPlayer.SPECIAL_ATTACK_PERCENT) / 1000.0F; + break; case WORLD: currLvl = 1000; // hacky } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/solver/pathfinding/IDAStarMM.java b/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/solver/pathfinding/IDAStarMM.java index 97749e048a..7f5a30a210 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/solver/pathfinding/IDAStarMM.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/puzzlesolver/solver/pathfinding/IDAStarMM.java @@ -226,7 +226,7 @@ public class IDAStarMM extends IDAStar Point locSwap = new Point(locBlank.getX(), locBlank.getY() + 1); swap(locBlank, locSwap); } - else if (distY <= -1) + else { Point locSwap = new Point(locBlank.getX(), locBlank.getY() - 1); swap(locBlank, locSwap); @@ -252,7 +252,7 @@ public class IDAStarMM extends IDAStar Point locSwap = new Point(locBlank.getX() + 1, locBlank.getY()); swap(locBlank, locSwap); } - else if (distX <= -1) + else { Point locSwap = new Point(locBlank.getX() - 1, locBlank.getY()); swap(locBlank, locSwap); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/pyramidplunder/PyramidPlunderPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/pyramidplunder/PyramidPlunderPlugin.java index 31beb64cd8..afd2464204 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/pyramidplunder/PyramidPlunderPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/pyramidplunder/PyramidPlunderPlugin.java @@ -162,6 +162,7 @@ public class PyramidPlunderPlugin extends Plugin break; case LOADING: obstacles.clear(); + break; case LOGGED_IN: if (!isInRegion()) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java index 66becd116f..772a9b1b48 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java @@ -817,7 +817,7 @@ public class RaidsPlugin extends Plugin StringBuilder builder = new StringBuilder(); if (seconds >= 3600) { - builder.append((int) Math.floor(seconds / 3600) + ";"); + builder.append((int) Math.floor(seconds / 3600)).append(";"); } seconds %= 3600; if (builder.toString().equals("")) @@ -842,7 +842,7 @@ public class RaidsPlugin extends Plugin tooltip = null; return; } - builder.append("Upper level: " + secondsToTime(upperTime)); + builder.append("Upper level: ").append(secondsToTime(upperTime)); if (middleTime == -1) { if (lowerTime == -1) @@ -852,12 +852,12 @@ public class RaidsPlugin extends Plugin } else { - builder.append("
Lower level: " + secondsToTime(lowerTime - upperTime)); + builder.append("
Lower level: ").append(secondsToTime(lowerTime - upperTime)); } } else { - builder.append("
Middle level: " + secondsToTime(middleTime - upperTime)); + builder.append("
Middle level: ").append(secondsToTime(middleTime - upperTime)); if (lowerTime == -1) { tooltip = builder.toString(); @@ -865,7 +865,7 @@ public class RaidsPlugin extends Plugin } else { - builder.append("
Lower level: " + secondsToTime(lowerTime - middleTime)); + builder.append("
Lower level: ").append(secondsToTime(lowerTime - middleTime)); } } if (raidTime == -1) @@ -873,7 +873,7 @@ public class RaidsPlugin extends Plugin tooltip = builder.toString(); return; } - builder.append("
Olm: " + secondsToTime(raidTime - lowerTime)); + builder.append("
Olm: ").append(secondsToTime(raidTime - lowerTime)); tooltip = builder.toString(); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/ThievingRoomType.java b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/ThievingRoomType.java index f709b2d435..e81bb0c95f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/ThievingRoomType.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/BatSolver/ThievingRoomType.java @@ -1,61 +1,61 @@ -/* - * Copyright (c) 2018, Tim Lehner - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.plugins.raidsthieving.BatSolver; - -// There are three distinct Thieving rooms, distinguished by the position of the entrance relative to the exit -// e.g. If you enter the room and must turn left to get to the exit and trough, this is a LEFT_TURN - -import net.runelite.client.plugins.raidsthieving.InstancePoint; - -public enum ThievingRoomType -{ - LEFT_TURN(3271, 5389), - RIGHT_TURN(3350, 5399), - STRAIGHT(3317, 5397); - - private final int x; - private final int y; - - ThievingRoomType(int x, int y) - { - this.x = x; - this.y = y; - } - - public static ThievingRoomType IdentifyByInstancePoint(InstancePoint point) - { - for (ThievingRoomType type : ThievingRoomType.values()) - { - if (Math.abs(type.x - point.getX()) <= 1 && - Math.abs(type.y - point.getY()) <= 1) - { - return type; - } - } - - return null; - } - -} +/* + * Copyright (c) 2018, Tim Lehner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.plugins.raidsthieving.BatSolver; + +// There are three distinct Thieving rooms, distinguished by the position of the entrance relative to the exit +// e.g. If you enter the room and must turn left to get to the exit and trough, this is a LEFT_TURN + +import net.runelite.client.plugins.raidsthieving.InstancePoint; + +public enum ThievingRoomType +{ + LEFT_TURN(3271, 5389), + RIGHT_TURN(3350, 5399), + STRAIGHT(3317, 5397); + + private final int x; + private final int y; + + ThievingRoomType(int x, int y) + { + this.x = x; + this.y = y; + } + + public static ThievingRoomType identifyByInstancePoint(InstancePoint point) + { + for (ThievingRoomType type : ThievingRoomType.values()) + { + if (Math.abs(type.x - point.getX()) <= 1 && + Math.abs(type.y - point.getY()) <= 1) + { + return type; + } + } + + return null; + } + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/RaidsThievingPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/RaidsThievingPlugin.java index 3c1b19a4e5..5776597f1f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/RaidsThievingPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raidsthieving/RaidsThievingPlugin.java @@ -126,7 +126,7 @@ public class RaidsThievingPlugin extends Plugin if (obj.getId() == RaidsThievingConstants.EMPTY_TROUGH) { - ThievingRoomType type = ThievingRoomType.IdentifyByInstancePoint(absLoc); + ThievingRoomType type = ThievingRoomType.identifyByInstancePoint(absLoc); if (type != null) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterOverlay.java index 3843370e87..764401a36e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterOverlay.java @@ -1,121 +1,121 @@ -/* - * Copyright (c) 2018 Abex - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.plugins.regenmeter; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.RenderingHints; -import java.awt.Stroke; -import java.awt.geom.Arc2D; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.VarPlayer; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayLayer; -import net.runelite.client.ui.overlay.OverlayPosition; - -public class RegenMeterOverlay extends Overlay -{ - private static final Color HITPOINTS_COLOR = brighter(0x9B0703); - private static final Color SPECIAL_COLOR = brighter(0x1E95B0); - private static final Color OVERLAY_COLOR = new Color(255, 255, 255, 60); - private static final double DIAMETER = 26D; - private static final int OFFSET = 27; - - private final Client client; - private RegenMeterPlugin plugin; - private RegenMeterConfig config; - - private static Color brighter(int color) - { - float[] hsv = new float[3]; - Color.RGBtoHSB(color >>> 16, (color >> 8) & 0xFF, color & 0xFF, hsv); - return Color.getHSBColor(hsv[0], 1.f, 1.f); - } - - @Inject - public RegenMeterOverlay(Client client, RegenMeterPlugin plugin, RegenMeterConfig config) - { - setPosition(OverlayPosition.DYNAMIC); - setLayer(OverlayLayer.ABOVE_WIDGETS); - this.client = client; - this.plugin = plugin; - this.config = config; - } - - @Override - public Dimension render(Graphics2D g) - { - g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); - - if (config.showHitpoints()) - { - renderRegen(g, WidgetInfo.MINIMAP_HEALTH_ORB, plugin.getHitpointsPercentage(), HITPOINTS_COLOR); - } - - if (config.showSpecial()) - { - if (client.getVar(VarPlayer.SPECIAL_ATTACK_ENABLED) == 1) - { - final Widget widget = client.getWidget(WidgetInfo.MINIMAP_SPEC_ORB); - - if (widget != null && !widget.isHidden()) - { - final Rectangle bounds = widget.getBounds(); - g.setColor(RegenMeterOverlay.OVERLAY_COLOR); - g.fillOval( - bounds.x + OFFSET, - bounds.y + (int) (bounds.height / 2 - (DIAMETER) / 2), - (int) DIAMETER, (int) DIAMETER); - } - } - - renderRegen(g, WidgetInfo.MINIMAP_SPEC_ORB, plugin.getSpecialPercentage(), SPECIAL_COLOR); - } - - return null; - } - - private void renderRegen(Graphics2D g, WidgetInfo widgetInfo, double percent, Color color) - { - Widget widget = client.getWidget(widgetInfo); - if (widget == null || widget.isHidden()) - { - return; - } - Rectangle bounds = widget.getBounds(); - - Arc2D.Double arc = new Arc2D.Double(bounds.x + OFFSET, bounds.y + (bounds.height / 2 - DIAMETER / 2), DIAMETER, DIAMETER, 90.d, -360.d * percent, Arc2D.OPEN); - final Stroke STROKE = new BasicStroke(2f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER); - g.setStroke(STROKE); - g.setColor(color); - g.draw(arc); - } -} +/* + * Copyright (c) 2018 Abex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.plugins.regenmeter; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.Stroke; +import java.awt.geom.Arc2D; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.VarPlayer; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; + +public class RegenMeterOverlay extends Overlay +{ + private static final Color HITPOINTS_COLOR = brighter(0x9B0703); + private static final Color SPECIAL_COLOR = brighter(0x1E95B0); + private static final Color OVERLAY_COLOR = new Color(255, 255, 255, 60); + private static final double DIAMETER = 26D; + private static final int OFFSET = 27; + + private final Client client; + private RegenMeterPlugin plugin; + private RegenMeterConfig config; + + private static Color brighter(int color) + { + float[] hsv = new float[3]; + Color.RGBtoHSB(color >>> 16, (color >> 8) & 0xFF, color & 0xFF, hsv); + return Color.getHSBColor(hsv[0], 1.f, 1.f); + } + + @Inject + public RegenMeterOverlay(Client client, RegenMeterPlugin plugin, RegenMeterConfig config) + { + setPosition(OverlayPosition.DYNAMIC); + setLayer(OverlayLayer.ABOVE_WIDGETS); + this.client = client; + this.plugin = plugin; + this.config = config; + } + + @Override + public Dimension render(Graphics2D g) + { + g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); + + if (config.showHitpoints()) + { + renderRegen(g, WidgetInfo.MINIMAP_HEALTH_ORB, plugin.getHitpointsPercentage(), HITPOINTS_COLOR); + } + + if (config.showSpecial()) + { + if (client.getVar(VarPlayer.SPECIAL_ATTACK_ENABLED) == 1) + { + final Widget widget = client.getWidget(WidgetInfo.MINIMAP_SPEC_ORB); + + if (widget != null && !widget.isHidden()) + { + final Rectangle bounds = widget.getBounds(); + g.setColor(RegenMeterOverlay.OVERLAY_COLOR); + g.fillOval( + bounds.x + OFFSET, + bounds.y + (int) (bounds.height / 2D - (DIAMETER) / 2D), + (int) DIAMETER, (int) DIAMETER); + } + } + + renderRegen(g, WidgetInfo.MINIMAP_SPEC_ORB, plugin.getSpecialPercentage(), SPECIAL_COLOR); + } + + return null; + } + + private void renderRegen(Graphics2D g, WidgetInfo widgetInfo, double percent, Color color) + { + Widget widget = client.getWidget(widgetInfo); + if (widget == null || widget.isHidden()) + { + return; + } + Rectangle bounds = widget.getBounds(); + + Arc2D.Double arc = new Arc2D.Double(bounds.x + OFFSET, bounds.y + (bounds.height / 2D - DIAMETER / 2D), DIAMETER, DIAMETER, 90.d, -360.d * percent, Arc2D.OPEN); + final Stroke STROKE = new BasicStroke(2f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER); + g.setStroke(STROKE); + g.setColor(color); + g.draw(arc); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftPlugin.java index 55563b2fb9..4ff23ce802 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftPlugin.java @@ -228,11 +228,6 @@ public class RunecraftPlugin extends Plugin client.setMenuEntries(newEntries); } - private int searchIndex(MenuEntry[] entries, String option, String target) - { - return searchIndex(entries, option, target, false); - } - private int searchIndex(MenuEntry[] entries, String option, String target, boolean contains) { for (int i = entries.length - 1; i >= 0; i--) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuOverlay.java index 5cdb2908ce..6bcfe8a388 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuOverlay.java @@ -100,16 +100,16 @@ class RunedokuOverlay extends Overlay { if (!util.makeSimple(util.createTable(client)).contains(0)) { - OverlayUtil.renderPolygon(graphics, util.RectangleToPolygon(widget.getBounds()), Color.GREEN); + OverlayUtil.renderPolygon(graphics, util.rectangleToPolygon(widget.getBounds()), Color.GREEN); } else { - OverlayUtil.renderPolygon(graphics, util.RectangleToPolygon(widget.getBounds()), util.referenceColors(i)); + OverlayUtil.renderPolygon(graphics, util.rectangleToPolygon(widget.getBounds()), util.referenceColors(i)); } } else { - OverlayUtil.renderPolygon(graphics, util.RectangleToPolygon(widget.getBounds()), RED); + OverlayUtil.renderPolygon(graphics, util.rectangleToPolygon(widget.getBounds()), RED); } } @@ -134,17 +134,17 @@ class RunedokuOverlay extends Overlay { if (!util.makeSimple(util.createTable(client)).contains(0)) { - OverlayUtil.renderPolygon(graphics, util.RectangleToPolygon(squareToHighlight.getBounds()), Color.GREEN); + OverlayUtil.renderPolygon(graphics, util.rectangleToPolygon(squareToHighlight.getBounds()), Color.GREEN); } else { - OverlayUtil.renderPolygon(graphics, util.RectangleToPolygon(squareToHighlight.getBounds()), util.sudokuPieceToColor(simpleArr.get(iteration))); + OverlayUtil.renderPolygon(graphics, util.rectangleToPolygon(squareToHighlight.getBounds()), util.sudokuPieceToColor(simpleArr.get(iteration))); } iteration++; } else { - OverlayUtil.renderPolygon(graphics, util.RectangleToPolygon(squareToHighlight.getBounds()), RED); + OverlayUtil.renderPolygon(graphics, util.rectangleToPolygon(squareToHighlight.getBounds()), RED); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuUtil.java b/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuUtil.java index 2f6baf1c6b..94cae519be 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuUtil.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runedoku/RunedokuUtil.java @@ -9,7 +9,7 @@ import net.runelite.api.Client; import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.WidgetItem; -public class RunedokuUtil +class RunedokuUtil { private final RunedokuConfig config; @@ -20,7 +20,7 @@ public class RunedokuUtil this.config = config; } - protected Color sudokuPieceToColor(int i) + Color sudokuPieceToColor(int i) { switch (i) { @@ -47,7 +47,7 @@ public class RunedokuUtil } } - protected Color referenceColors(int i) + Color referenceColors(int i) { switch (i) { @@ -80,7 +80,7 @@ public class RunedokuUtil * @param board * @return */ - protected ArrayList makeSimple(int[][] board) + ArrayList makeSimple(int[][] board) { ArrayList list = new ArrayList<>(); for (int i = 0; i < 9; i++) @@ -99,7 +99,7 @@ public class RunedokuUtil * @param rect * @return */ - protected Polygon RectangleToPolygon(Rectangle rect) + public static Polygon rectangleToPolygon(Rectangle rect) { int[] xpoints = {rect.x, rect.x + rect.width, rect.x + rect.width, rect.x}; int[] ypoints = {rect.y, rect.y, rect.y + rect.height, rect.y + rect.height}; @@ -113,7 +113,7 @@ public class RunedokuUtil * @return sudoku table that the client currently sees in a 2d array * @author gazivodag */ - protected int[][] createTable(Client client) + int[][] createTable(Client client) { int[][] myArr = new int[9][9]; Widget sudokuScreen = client.getWidget(288, 131); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runeliteplus/RuneLitePlusPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/runeliteplus/RuneLitePlusPlugin.java index f7f0505f86..72c638588c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runeliteplus/RuneLitePlusPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runeliteplus/RuneLitePlusPlugin.java @@ -52,8 +52,8 @@ import net.runelite.client.ui.ClientUI; public class RuneLitePlusPlugin extends Plugin { public static boolean customPresenceEnabled = false; - public static String rlPlusDiscordApp = "560644885250572289"; - public static String rlDiscordApp = "409416265891971072"; + public static final String rlPlusDiscordApp = "560644885250572289"; + public static final String rlDiscordApp = "409416265891971072"; @Inject public RuneLitePlusConfig config; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerTaskPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerTaskPanel.java index d40f7955b5..ea3fbf0712 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerTaskPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerTaskPanel.java @@ -301,7 +301,8 @@ public class SlayerTaskPanel extends PluginPanel if (tasks.isEmpty() || isNewAssignment) { // new task so append it to the front of the list - SwingUtilities.invokeLater(() -> { + SwingUtilities.invokeLater(() -> + { TaskBox newBox = buildBox(slayerPlugin, tasksContainer, newData); newBox.update(true, newData.isPaused(), newData); }); @@ -322,7 +323,8 @@ public class SlayerTaskPanel extends PluginPanel // so this previous task is invalid so delete it then add in the new actually // correct task - SwingUtilities.invokeLater(() -> { + SwingUtilities.invokeLater(() -> + { tasksContainer.remove(tasks.get(0)); tasks.remove(0); TaskBox newBox = buildBox(slayerPlugin, tasksContainer, newData); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TargetClickboxOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TargetClickboxOverlay.java index 004c33c52f..ed6e0582d4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TargetClickboxOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TargetClickboxOverlay.java @@ -58,7 +58,7 @@ public class TargetClickboxOverlay extends Overlay @Inject TargetClickboxOverlay(Client client, SlayerConfig config, SlayerPlugin plugin, - ModelOutlineRenderer modelOutlineRenderer) + ModelOutlineRenderer modelOutlineRenderer) { this.client = client; this.config = config; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TaskBox.java b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TaskBox.java index c50d359de7..ff3b509898 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TaskBox.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TaskBox.java @@ -80,7 +80,8 @@ class TaskBox extends JPanel container.setLayout(new BorderLayout()); container.setBackground(ColorScheme.DARKER_GRAY_COLOR); - SwingUtilities.invokeLater(() -> { + SwingUtilities.invokeLater(() -> + { BufferedImage taskImg = slayerPlugin.getImageForTask(Task.getTask(taskData.getTaskName())); JLabel taskIcon = new JLabel(new ImageIcon(taskImg)); taskIcon.setHorizontalAlignment(SwingConstants.CENTER); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/tickcounter/TickCounterOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/tickcounter/TickCounterOverlay.java index d33084be37..397392ad8c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/tickcounter/TickCounterOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/tickcounter/TickCounterOverlay.java @@ -42,7 +42,8 @@ public class TickCounterOverlay extends Overlay panelComponent.setBackgroundColor(config.bgColor()); elems.add(TitleComponent.builder().text("Combat counter").color(config.titleColor()).build()); List> list = new ArrayList<>(plugin.activity.entrySet()); - list.sort((o1, o2) -> { + list.sort((o1, o2) -> + { int value = -Integer.compare(o1.getValue(), o2.getValue()); if (value == 0) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/OverviewTabPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/OverviewTabPanel.java index 633d548750..de2154185c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/OverviewTabPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/OverviewTabPanel.java @@ -50,7 +50,7 @@ class OverviewTabPanel extends TabContentPanel private final OverviewItemPanel birdHouseOverview; OverviewTabPanel(ItemManager itemManager, TimeTrackingConfig config, TimeTrackingPanel pluginPanel, - FarmingTracker farmingTracker, BirdHouseTracker birdHouseTracker, ClockManager clockManager) + FarmingTracker farmingTracker, BirdHouseTracker birdHouseTracker, ClockManager clockManager) { this.config = config; this.farmingTracker = farmingTracker; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingPanel.java index 54b863f4b0..0962af3acd 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeTrackingPanel.java @@ -64,7 +64,7 @@ class TimeTrackingPanel extends PluginPanel private TabContentPanel activeTabPanel = null; TimeTrackingPanel(ItemManager itemManager, TimeTrackingConfig config, - FarmingTracker farmingTracker, BirdHouseTracker birdHouseTracker, ClockManager clockManager) + FarmingTracker farmingTracker, BirdHouseTracker birdHouseTracker, ClockManager clockManager) { super(false); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingTracker.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingTracker.java index 3d6d926126..f4e73622b0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingTracker.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingTracker.java @@ -60,7 +60,7 @@ public class FarmingTracker @Inject private FarmingTracker(Client client, ItemManager itemManager, ConfigManager configManager, - TimeTrackingConfig config, FarmingWorld farmingWorld) + TimeTrackingConfig config, FarmingWorld farmingWorld) { this.client = client; this.itemManager = itemManager; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/hunter/BirdHouseTracker.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/hunter/BirdHouseTracker.java index bef011cea4..f3838998f0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/hunter/BirdHouseTracker.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/hunter/BirdHouseTracker.java @@ -73,7 +73,7 @@ public class BirdHouseTracker @Inject private BirdHouseTracker(Client client, ItemManager itemManager, ConfigManager configManager, - TimeTrackingConfig config, Notifier notifier) + TimeTrackingConfig config, Notifier notifier) { this.client = client; this.itemManager = itemManager; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersPlugin.java index 0ed7fe4e0b..47c56fe3d0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/whalewatchers/WhaleWatchersPlugin.java @@ -121,7 +121,7 @@ public class WhaleWatchersPlugin extends Plugin { if (config.showDamageCounter()) { - if (!(event.getActor() == client.getLocalPlayer() | + if (!(event.getActor() == client.getLocalPlayer() || event.getActor() == client.getLocalPlayer().getInteracting())) { return; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiSearchChatboxTextInput.java b/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiSearchChatboxTextInput.java index 37814ade62..f0085288a2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiSearchChatboxTextInput.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiSearchChatboxTextInput.java @@ -76,7 +76,7 @@ public class WikiSearchChatboxTextInput extends ChatboxTextInput @Inject public WikiSearchChatboxTextInput(ChatboxPanelManager chatboxPanelManager, ClientThread clientThread, - ScheduledExecutorService scheduledExecutorService, @Named("developerMode") final boolean developerMode) + ScheduledExecutorService scheduledExecutorService, @Named("developerMode") final boolean developerMode) { super(chatboxPanelManager, clientThread); this.chatboxPanelManager = chatboxPanelManager; 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 7f0f1009f7..8c5c8a14e7 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 @@ -32,17 +32,14 @@ import com.google.common.reflect.TypeToken; import com.google.gson.Gson; import io.sigpipe.jbsdiff.InvalidHeaderException; import io.sigpipe.jbsdiff.Patch; - import java.applet.Applet; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.lang.reflect.InvocationTargetException; import java.net.URL; -import java.nio.file.Files; import java.util.HashMap; import java.util.Map; import java.util.jar.Attributes; @@ -53,13 +50,10 @@ import java.util.jar.Manifest; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; - import lombok.extern.slf4j.Slf4j; - import static net.runelite.client.rs.ClientUpdateCheckMode.AUTO; import static net.runelite.client.rs.ClientUpdateCheckMode.NONE; import static net.runelite.client.rs.ClientUpdateCheckMode.VANILLA; - import net.runelite.client.rs.mixins.MixinRunner; import net.runelite.http.api.RuneLiteAPI; import okhttp3.Request; @@ -72,41 +66,42 @@ public class ClientLoader { private final ClientConfigLoader clientConfigLoader; private ClientUpdateCheckMode updateCheckMode; + @Inject private ClientLoader( - @Named("updateCheckMode") final ClientUpdateCheckMode updateCheckMode, - final ClientConfigLoader clientConfigLoader) + @Named("updateCheckMode") final ClientUpdateCheckMode updateCheckMode, + final ClientConfigLoader clientConfigLoader) { this.updateCheckMode = updateCheckMode; this.clientConfigLoader = clientConfigLoader; } - + public Applet load() { if (updateCheckMode == NONE) { return null; } - + try { Manifest manifest = new Manifest(); manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); RSConfig config = clientConfigLoader.fetch(); - + Map zipFile = new HashMap<>(); { String codebase = config.getCodeBase(); String initialJar = config.getInitialJar(); URL url = new URL(codebase + initialJar); Request request = new Request.Builder() - .url(url) - .build(); - + .url(url) + .build(); + try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute()) { JarInputStream jis; - + jis = new JarInputStream(response.body().byteStream()); byte[] tmp = new byte[4096]; ByteArrayOutputStream buffer = new ByteArrayOutputStream(756 * 1024); @@ -117,7 +112,7 @@ public class ClientLoader { break; } - + buffer.reset(); for (; ; ) { @@ -128,12 +123,12 @@ public class ClientLoader } buffer.write(tmp, 0, n); } - + zipFile.put(metadata.getName(), buffer.toByteArray()); } } } - + if (updateCheckMode == AUTO) { Map hashes; @@ -143,33 +138,33 @@ public class ClientLoader { }.getType()); } - + for (Map.Entry file : hashes.entrySet()) { byte[] bytes = zipFile.get(file.getKey()); - + String ourHash = null; if (bytes != null) { ourHash = Hashing.sha512().hashBytes(bytes).toString(); } - + if (!file.getValue().equals(ourHash)) { log.info("{} had a hash mismatch; falling back to vanilla. {} != {}", file.getKey(), - file.getValue(), ourHash); + file.getValue(), ourHash); log.info("Client is outdated!"); updateCheckMode = VANILLA; break; } } } - + if (updateCheckMode == AUTO) { ByteArrayOutputStream patchOs = new ByteArrayOutputStream(756 * 1024); int patchCount = 0; - + for (Map.Entry file : zipFile.entrySet()) { byte[] bytes; @@ -179,27 +174,27 @@ public class ClientLoader { continue; } - + bytes = ByteStreams.toByteArray(is); } - + patchOs.reset(); Patch.patch(file.getValue(), bytes, patchOs); file.setValue(patchOs.toByteArray()); - + ++patchCount; } - + log.info("Patched {} classes", patchCount); } - + log.info("Patching for RuneLitePlus"); - + if (updateCheckMode == AUTO) { - + HashMap patches = new HashMap<>(); - + for (Map.Entry file : zipFile.entrySet()) { byte[] patchClass; @@ -209,20 +204,20 @@ public class ClientLoader { continue; } - + patchClass = ByteStreams.toByteArray(is); } - + patches.put(file.getKey(), patchClass); - + } - + new MixinRunner(zipFile, patches).run(); - + } - + String initialClass = config.getInitialClass(); - + ClassLoader rsClassLoader = new ClassLoader(ClientLoader.class.getClassLoader()) { @Override @@ -234,13 +229,13 @@ public class ClientLoader { throw new ClassNotFoundException(name); } - + return defineClass(name, data, 0, data.length); } }; - + Class clientClass = rsClassLoader.loadClass(initialClass); - + Applet rs = (Applet) clientClass.newInstance(); rs.setStub(new RSAppletStub(config)); return rs; @@ -250,15 +245,15 @@ public class ClientLoader if (e instanceof ClassNotFoundException) { log.error("Unable to load client - class not found. This means you" - + " are not running RuneLite with Maven as the client patch" - + " is not in your classpath."); + + " are not running RuneLite with Maven as the client patch" + + " is not in your classpath."); } - + log.error("Error loading RS!", e); return null; } } - + private void add(byte[] bytes, String entryName, JarOutputStream target) throws IOException { BufferedInputStream in = null; diff --git a/runelite-client/src/main/java/net/runelite/client/rs/mixins/MixinRunner.java b/runelite-client/src/main/java/net/runelite/client/rs/mixins/MixinRunner.java index e745e06190..cde7fac215 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/mixins/MixinRunner.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/mixins/MixinRunner.java @@ -25,8 +25,18 @@ package net.runelite.client.rs.mixins; +import java.lang.reflect.InvocationTargetException; +import java.util.Map; import lombok.RequiredArgsConstructor; -import net.runelite.client.rs.mixins.transformers.*; +import net.runelite.client.rs.mixins.transformers.AppendTransformer; +import net.runelite.client.rs.mixins.transformers.DoNothingTransformer; +import net.runelite.client.rs.mixins.transformers.InjectTransformer; +import net.runelite.client.rs.mixins.transformers.InterfaceTransformer; +import net.runelite.client.rs.mixins.transformers.OverwriteSanityCheck; +import net.runelite.client.rs.mixins.transformers.OverwriteTransformer; +import net.runelite.client.rs.mixins.transformers.PrependTransformer; +import net.runelite.client.rs.mixins.transformers.ProtectTransformer; +import net.runelite.client.rs.mixins.transformers.SanityChecker; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassWriter; @@ -34,18 +44,15 @@ import org.objectweb.asm.commons.ClassRemapper; import org.objectweb.asm.commons.Remapper; import org.objectweb.asm.tree.ClassNode; -import java.lang.reflect.InvocationTargetException; -import java.util.Map; - @RequiredArgsConstructor public class MixinRunner { - + private final Map classes; private final Map patches; - + public Map run() - throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException + throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { runVisitor(InterfaceTransformer.class); runVisitor(OverwriteTransformer.class); @@ -55,11 +62,11 @@ public class MixinRunner // (test method: Projectile.rl$$init()V ) runVisitor(PrependTransformer.class); runRemapper(ProtectTransformer.class); - + recalcMaxes(); return classes; } - + private void runRemapper(Class clazz) throws IllegalAccessException, InstantiationException { for (Map.Entry entry : classes.entrySet()) @@ -72,19 +79,19 @@ public class MixinRunner ClassReader cr = new ClassReader(entry.getValue()); ClassWriter cw = new ClassWriter(cr, 1); cr.accept(new ClassRemapper(cw, inst), 0); - + entry.setValue(cw.toByteArray()); } } - + private void runVisitor(Class clazz) - throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException + throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException { runVisitor(clazz, 1); } - + private void runVisitor(Class clazz, int flags) - throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException + throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException { for (Map.Entry entry : classes.entrySet()) { @@ -98,21 +105,21 @@ public class MixinRunner ClassNode node = new ClassNode(); cr.accept(node, 0); ClassVisitor inst = clazz.getConstructor(ClassVisitor.class, byte[].class, ClassNode.class).newInstance(cw, - patch, node); + patch, node); cr.accept(inst, 0); - + entry.setValue(cw.toByteArray()); } } - + private void runSanityChecker(Class clazz) - throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException + throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException { runSanityChecker(clazz, 1); } - + private void runSanityChecker(Class clazz, int flags) - throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException + throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException { for (Map.Entry entry : patches.entrySet()) { @@ -124,11 +131,11 @@ public class MixinRunner cr.accept(inst, 0); } } - + private void recalcMaxes() - throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException + throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException { runVisitor(DoNothingTransformer.class, 3); } - + } diff --git a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/AppendTransformer.java b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/AppendTransformer.java index 340c93e08b..5ee15c84c8 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/AppendTransformer.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/AppendTransformer.java @@ -40,25 +40,25 @@ import org.objectweb.asm.tree.MethodNode; @Slf4j public class AppendTransformer extends ClassVisitor implements Opcodes { - + private final byte[] patch; private String className; private ClassNode classNode; - + public AppendTransformer(ClassVisitor classVisitor, byte[] patch, ClassNode node) { super(Opcodes.ASM6, classVisitor); this.patch = patch; this.classNode = node; } - + @Override public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { className = name; super.visit(version, access, name, signature, superName, interfaces); } - + @Override public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { @@ -73,44 +73,44 @@ public class AppendTransformer extends ClassVisitor implements Opcodes { MethodNode patchMethod = (MethodNode) obj; if ((patchMethod.access == access && patchMethod.name.equals("append$" + name) && - patchMethod.desc.equals(descriptor)) && - RefUtils.checkAnnotation(patchMethod, "Append")) + patchMethod.desc.equals(descriptor)) && + RefUtils.checkAnnotation(patchMethod, "Append")) { MethodVisitor mv = - new MethodVisitor(Opcodes.ASM6, super.visitMethod(access, name, descriptor, signature, - exceptions)) - { - }; + new MethodVisitor(Opcodes.ASM6, super.visitMethod(access, name, descriptor, signature, + exceptions)) + { + }; mv.visitCode(); - + for (Object obj2 : classNode.methods) { MethodNode classMethod = (MethodNode) obj2; if (classMethod.access == access && classMethod.name.equals(name) && - classMethod.desc.equals(descriptor)) + classMethod.desc.equals(descriptor)) { AbstractInsnNode inode = classMethod.instructions.getLast(); - - while(inode instanceof LabelNode || inode instanceof LineNumberNode) + + while (inode instanceof LabelNode || inode instanceof LineNumberNode) { inode = inode.getPrevious(); } - - if(RefUtils.isReturn(inode.getOpcode(), true)) + + if (RefUtils.isReturn(inode.getOpcode(), true)) { log.error("[Append] Can't append to {}.{}, requires typed return opcode", className, name); return super.visitMethod(access, name, descriptor, signature, exceptions); } - + classMethod.instructions.remove(inode); - + classMethod.accept(new MethodReflector(mv)); break; } } - + patchMethod.accept(new MethodReflector(mv)); - + mv.visitEnd(); return mv; } diff --git a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/InjectTransformer.java b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/InjectTransformer.java index 283d6d4208..29fb2bf554 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/InjectTransformer.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/InjectTransformer.java @@ -36,26 +36,26 @@ import org.objectweb.asm.tree.MethodNode; public class InjectTransformer extends ClassVisitor { - + private final byte[] patch; private ClassNode node; private String className; private boolean patching = false; - + public InjectTransformer(ClassVisitor classVisitor, byte[] patch, ClassNode node) { super(Opcodes.ASM6, classVisitor); this.patch = patch; this.node = node; } - + @Override public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { className = name; super.visit(version, access, name, signature, superName, interfaces); } - + @Override public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { @@ -63,8 +63,8 @@ public class InjectTransformer extends ClassVisitor { return super.visitMethod(access, name, descriptor, signature, exceptions); } - if (name.startsWith("prepend$") || name.startsWith("append$")|| - (patching && name.startsWith("<"))) + if (name.startsWith("prepend$") || name.startsWith("append$") || + (patching && name.startsWith("<"))) { return null; } @@ -76,7 +76,7 @@ public class InjectTransformer extends ClassVisitor { MethodNode node = (MethodNode) obj; if ((node.access == access && node.name.equals(name) && node.desc.equals(descriptor)) && - RefUtils.checkAnnotation(node, "Inject")) + RefUtils.checkAnnotation(node, "Inject")) { mv.visitCode(); node.accept(new MethodReflector(mv)); @@ -85,17 +85,17 @@ public class InjectTransformer extends ClassVisitor } return mv; } - + @Override public void visitEnd() { - + if (patch == null) { super.visitEnd(); return; } - + ClassReader cr = new ClassReader(patch); ClassNode patchNode = new ClassNode(Opcodes.ASM6); cr.accept(patchNode, 0); @@ -106,10 +106,10 @@ public class InjectTransformer extends ClassVisitor if (RefUtils.checkAnnotation(node, "Inject")) { visitMethod(node.access, node.name, node.desc, node.signature, - (String[]) node.exceptions.toArray(new String[0])); + (String[]) node.exceptions.toArray(new String[0])); } } - + for (Object obj : patchNode.fields) { FieldNode node = (FieldNode) obj; @@ -121,5 +121,5 @@ public class InjectTransformer extends ClassVisitor patching = false; super.visitEnd(); } - + } diff --git a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/InterfaceTransformer.java b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/InterfaceTransformer.java index 633b45409b..850e3be921 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/InterfaceTransformer.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/InterfaceTransformer.java @@ -25,42 +25,41 @@ package net.runelite.client.rs.mixins.transformers; +import java.util.ArrayList; +import java.util.Arrays; import lombok.extern.slf4j.Slf4j; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.ClassNode; -import java.util.ArrayList; -import java.util.Arrays; - @Slf4j public class InterfaceTransformer extends ClassVisitor implements Opcodes { - + private final byte[] patch; private ClassNode node; private String className; - + public InterfaceTransformer(ClassVisitor classVisitor, byte[] patch, ClassNode node) { super(Opcodes.ASM6, classVisitor); this.patch = patch; this.node = node; } - + @Override public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { className = name; - if(patch != null) + if (patch != null) { ClassReader reader = new ClassReader(patch); ClassNode pNode = new ClassNode(); reader.accept(pNode, 0); - if(pNode.interfaces != null && pNode.interfaces.size() != 0) + if (pNode.interfaces != null && pNode.interfaces.size() != 0) { - if(interfaces == null) + if (interfaces == null) { interfaces = (String[]) pNode.interfaces.toArray(new String[0]); } @@ -74,5 +73,5 @@ public class InterfaceTransformer extends ClassVisitor implements Opcodes } super.visit(version, access, name, signature, superName, interfaces); } - + } diff --git a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/MethodReflector.java b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/MethodReflector.java index 775b791f5b..a6f6813c49 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/MethodReflector.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/MethodReflector.java @@ -35,15 +35,15 @@ import org.objectweb.asm.TypePath; public class MethodReflector extends MethodVisitor { - + private MethodVisitor target; - + public MethodReflector(MethodVisitor target) { super(Opcodes.ASM6); this.target = target; } - + public void visitParameter(String var1, int var2) { if (target != null) @@ -52,27 +52,27 @@ public class MethodReflector extends MethodVisitor } super.visitParameter(var1, var2); } - + public AnnotationVisitor visitAnnotationDefault() { return super.visitAnnotationDefault(); } - + public AnnotationVisitor visitAnnotation(String var1, boolean var2) { return super.visitAnnotation(var1, var2); } - + public AnnotationVisitor visitTypeAnnotation(int var1, TypePath var2, String var3, boolean var4) { return super.visitTypeAnnotation(var1, var2, var3, var4); } - + public AnnotationVisitor visitParameterAnnotation(int var1, String var2, boolean var3) { return super.visitParameterAnnotation(var1, var2, var3); } - + public void visitAttribute(Attribute var1) { if (target != null) @@ -81,7 +81,7 @@ public class MethodReflector extends MethodVisitor } super.visitAttribute(var1); } - + public void visitFrame(int var1, int var2, Object[] var3, int var4, Object[] var5) { if (target != null) @@ -90,7 +90,7 @@ public class MethodReflector extends MethodVisitor } super.visitFrame(var1, var2, var3, var4, var5); } - + public void visitInsn(int var1) { if (target != null) @@ -99,7 +99,7 @@ public class MethodReflector extends MethodVisitor } super.visitInsn(var1); } - + public void visitIntInsn(int var1, int var2) { if (target != null) @@ -108,7 +108,7 @@ public class MethodReflector extends MethodVisitor } super.visitIntInsn(var1, var2); } - + public void visitVarInsn(int var1, int var2) { if (target != null) @@ -117,7 +117,7 @@ public class MethodReflector extends MethodVisitor } super.visitVarInsn(var1, var2); } - + public void visitTypeInsn(int var1, String var2) { if (target != null) @@ -126,7 +126,7 @@ public class MethodReflector extends MethodVisitor } super.visitTypeInsn(var1, var2); } - + public void visitFieldInsn(int var1, String var2, String var3, String var4) { if (target != null) @@ -135,7 +135,7 @@ public class MethodReflector extends MethodVisitor } super.visitFieldInsn(var1, var2, var3, var4); } - + /** * @deprecated */ @@ -147,7 +147,7 @@ public class MethodReflector extends MethodVisitor } super.visitMethodInsn(var1, var2, var3, var4); } - + public void visitMethodInsn(int var1, String var2, String var3, String var4, boolean var5) { if (target != null) @@ -156,7 +156,7 @@ public class MethodReflector extends MethodVisitor } super.visitMethodInsn(var1, var2, var3, var4, var5); } - + public void visitInvokeDynamicInsn(String var1, String var2, Handle var3, Object... var4) { if (target != null) @@ -165,7 +165,7 @@ public class MethodReflector extends MethodVisitor } super.visitInvokeDynamicInsn(var1, var2, var3, var4); } - + public void visitJumpInsn(int var1, Label var2) { if (target != null) @@ -174,7 +174,7 @@ public class MethodReflector extends MethodVisitor } super.visitJumpInsn(var1, var2); } - + public void visitLabel(Label var1) { if (target != null) @@ -183,7 +183,7 @@ public class MethodReflector extends MethodVisitor } super.visitLabel(var1); } - + public void visitLdcInsn(Object var1) { if (target != null) @@ -192,7 +192,7 @@ public class MethodReflector extends MethodVisitor } super.visitLdcInsn(var1); } - + public void visitIincInsn(int var1, int var2) { if (target != null) @@ -201,7 +201,7 @@ public class MethodReflector extends MethodVisitor } super.visitIincInsn(var1, var2); } - + public void visitTableSwitchInsn(int var1, int var2, Label var3, Label... var4) { if (target != null) @@ -210,7 +210,7 @@ public class MethodReflector extends MethodVisitor } super.visitTableSwitchInsn(var1, var2, var3, var4); } - + public void visitLookupSwitchInsn(Label var1, int[] var2, Label[] var3) { if (target != null) @@ -219,7 +219,7 @@ public class MethodReflector extends MethodVisitor } super.visitLookupSwitchInsn(var1, var2, var3); } - + public void visitMultiANewArrayInsn(String var1, int var2) { if (target != null) @@ -228,7 +228,7 @@ public class MethodReflector extends MethodVisitor } super.visitMultiANewArrayInsn(var1, var2); } - + public AnnotationVisitor visitInsnAnnotation(int var1, TypePath var2, String var3, boolean var4) { if (target != null) @@ -237,7 +237,7 @@ public class MethodReflector extends MethodVisitor } return super.visitInsnAnnotation(var1, var2, var3, var4); } - + public void visitTryCatchBlock(Label var1, Label var2, Label var3, String var4) { if (target != null) @@ -246,7 +246,7 @@ public class MethodReflector extends MethodVisitor } super.visitTryCatchBlock(var1, var2, var3, var4); } - + public AnnotationVisitor visitTryCatchAnnotation(int var1, TypePath var2, String var3, boolean var4) { if (target != null) @@ -255,7 +255,7 @@ public class MethodReflector extends MethodVisitor } return super.visitTryCatchAnnotation(var1, var2, var3, var4); } - + public void visitLocalVariable(String var1, String var2, String var3, Label var4, Label var5, int var6) { if (target != null) @@ -264,7 +264,7 @@ public class MethodReflector extends MethodVisitor } super.visitLocalVariable(var1, var2, var3, var4, var5, var6); } - + public AnnotationVisitor visitLocalVariableAnnotation(int var1, TypePath var2, Label[] var3, Label[] var4, int[] var5, String var6, boolean var7) { if (target != null) @@ -273,7 +273,7 @@ public class MethodReflector extends MethodVisitor } return super.visitLocalVariableAnnotation(var1, var2, var3, var4, var5, var6, var7); } - + public void visitLineNumber(int var1, Label var2) { if (target != null) @@ -282,7 +282,7 @@ public class MethodReflector extends MethodVisitor } super.visitLineNumber(var1, var2); } - + public void visitMaxs(int var1, int var2) { if (target != null) @@ -291,5 +291,5 @@ public class MethodReflector extends MethodVisitor } super.visitMaxs(var1, var2); } - + } diff --git a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/OverwriteSanityCheck.java b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/OverwriteSanityCheck.java index ff619753de..37c0ca9d65 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/OverwriteSanityCheck.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/OverwriteSanityCheck.java @@ -25,6 +25,7 @@ package net.runelite.client.rs.mixins.transformers; +import java.util.ArrayList; import lombok.extern.slf4j.Slf4j; import net.runelite.client.util.RefUtils; import org.objectweb.asm.ClassVisitor; @@ -33,51 +34,49 @@ import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.MethodNode; -import java.util.ArrayList; - @Slf4j public class OverwriteSanityCheck extends SanityChecker implements Opcodes { - + private String className; private ClassNode patchNode; public static final ArrayList methodsUsed = new ArrayList<>(); - + public OverwriteSanityCheck(ClassVisitor classVisitor, ClassNode node) { super(ASM6, classVisitor); this.className = node.name; this.patchNode = node; } - + @Override public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { String check = String.format("%s %s %s %s", className, name, - descriptor, access); - + descriptor, access); + MethodNode methodNode = null; for (Object obj2 : patchNode.methods) { MethodNode classMethod = (MethodNode) obj2; if (classMethod.access == access && classMethod.name.equals(name) && - classMethod.desc.equals(descriptor)) + classMethod.desc.equals(descriptor)) { methodNode = classMethod; } } - - if(methodNode == null) + + if (methodNode == null) { log.error("[OverwriteSanity] Failed to find original patch method for {}", check); return super.visitMethod(access, name, descriptor, signature, exceptions); } - + if (!RefUtils.checkAnnotation(methodNode, "Overwrite")) { return super.visitMethod(access, name, descriptor, signature, exceptions); } - + if (!methodsUsed.contains(check)) { throw new RuntimeException("[OverwriteSanity] Overwrite target not found: " + check); diff --git a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/OverwriteTransformer.java b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/OverwriteTransformer.java index f7c8c09bef..9decd259bd 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/OverwriteTransformer.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/OverwriteTransformer.java @@ -37,11 +37,11 @@ import org.objectweb.asm.tree.MethodNode; @Slf4j public class OverwriteTransformer extends ClassVisitor { - + private final byte[] patch; private ClassNode node; private String className; - + public OverwriteTransformer(ClassVisitor classVisitor, byte[] patch, ClassNode node) { super(Opcodes.ASM6, classVisitor); @@ -49,14 +49,14 @@ public class OverwriteTransformer extends ClassVisitor this.node = node; this.className = node.name; } - + @Override public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { className = name; super.visit(version, access, name, signature, superName, interfaces); } - + @Override public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { @@ -64,34 +64,34 @@ public class OverwriteTransformer extends ClassVisitor { return super.visitMethod(access, name, descriptor, signature, exceptions); } - + if (name.startsWith("prepend$") || name.startsWith("append$")) { return null; } - + ClassReader cr = new ClassReader(patch); ClassNode patchNode = new ClassNode(Opcodes.ASM6); cr.accept(patchNode, 0); - + for (Object obj : patchNode.methods) { MethodNode patchMethod = (MethodNode) obj; - + if (patchMethod.access == access && patchMethod.name.equals(name) && patchMethod.desc.equals(descriptor)) { if (RefUtils.checkAnnotation(patchMethod, "Overwrite")) { MethodVisitor mv = - new MethodVisitor(Opcodes.ASM6, super.visitMethod(access, name, descriptor, signature, - exceptions)) - { - }; + new MethodVisitor(Opcodes.ASM6, super.visitMethod(access, name, descriptor, signature, + exceptions)) + { + }; mv.visitCode(); patchMethod.accept(new MethodReflector(mv)); mv.visitEnd(); String s = String.format("%s %s %s %s", className, patchMethod.name, - patchMethod.desc, patchMethod.access); + patchMethod.desc, patchMethod.access); OverwriteSanityCheck.methodsUsed.add(s); return mv; } diff --git a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/PrependTransformer.java b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/PrependTransformer.java index 6aedbab699..e06c4703ea 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/PrependTransformer.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/PrependTransformer.java @@ -37,25 +37,25 @@ import org.objectweb.asm.tree.MethodNode; public class PrependTransformer extends ClassVisitor { - + private final byte[] patch; private String className; private ClassNode classNode; - + public PrependTransformer(ClassVisitor classVisitor, byte[] patch, ClassNode node) { super(Opcodes.ASM6, classVisitor); this.patch = patch; this.classNode = node; } - + @Override public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { className = name; super.visit(version, access, name, signature, superName, interfaces); } - + @Override public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { @@ -70,47 +70,47 @@ public class PrependTransformer extends ClassVisitor { MethodNode patchMethod = (MethodNode) obj; if ((patchMethod.access == access && patchMethod.name.equals("prepend$" + name) && - patchMethod.desc.equals(descriptor)) && - RefUtils.checkAnnotation(patchMethod, "Prepend")) + patchMethod.desc.equals(descriptor)) && + RefUtils.checkAnnotation(patchMethod, "Prepend")) { MethodVisitor mv = - new MethodVisitor(Opcodes.ASM6, super.visitMethod(access, name, descriptor, signature, - exceptions)) - { - }; + new MethodVisitor(Opcodes.ASM6, super.visitMethod(access, name, descriptor, signature, + exceptions)) + { + }; mv.visitCode(); - + AbstractInsnNode node = patchMethod.instructions.getLast(); while (!(node instanceof InsnNode)) { node = node.getPrevious(); } - + if (RefUtils.isReturn(node.getOpcode())) { patchMethod.instructions.remove(node); } - + patchMethod.accept(new MethodReflector(mv)); - + for (Object obj2 : classNode.methods) { MethodNode classMethod = (MethodNode) obj2; if (classMethod.access == access && classMethod.name.equals(name) && - classMethod.desc.equals(descriptor)) + classMethod.desc.equals(descriptor)) { classMethod.accept(new MethodReflector(mv)); break; } } - + mv.visitEnd(); return mv; } } return super.visitMethod(access, name, descriptor, signature, exceptions); } - + @Override public void visitEnd() { @@ -121,5 +121,5 @@ public class PrependTransformer extends ClassVisitor } super.visitEnd(); } - + } diff --git a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/ProtectTransformer.java b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/ProtectTransformer.java index b3c52b5783..51a96cfc14 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/ProtectTransformer.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/ProtectTransformer.java @@ -29,7 +29,7 @@ import org.objectweb.asm.commons.Remapper; public class ProtectTransformer extends Remapper { - + public String mapFieldName(String owner, String name, String descriptor) { if (name.startsWith("1protect$")) @@ -38,7 +38,7 @@ public class ProtectTransformer extends Remapper } return super.mapFieldName(owner, name, descriptor); } - + public String mapMethodName(String owner, String name, String descriptor) { if (name.startsWith("1protect$")) @@ -47,5 +47,5 @@ public class ProtectTransformer extends Remapper } return super.mapMethodName(owner, name, descriptor); } - + } diff --git a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/SanityChecker.java b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/SanityChecker.java index f7a5cf1915..4581b00c59 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/SanityChecker.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/mixins/transformers/SanityChecker.java @@ -34,5 +34,5 @@ public abstract class SanityChecker extends ClassVisitor implements Opcodes { super(i, classVisitor); } - + } diff --git a/runelite-client/src/main/java/net/runelite/client/ui/ClientPanel.java b/runelite-client/src/main/java/net/runelite/client/ui/ClientPanel.java index c7ccb1a3ed..01ab643939 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/ClientPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/ClientPanel.java @@ -1,66 +1,66 @@ -/* - * Copyright (c) 2016-2017, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.ui; - -import java.applet.Applet; -import java.awt.BorderLayout; -import java.awt.Color; -import javax.annotation.Nullable; -import javax.swing.JPanel; -import net.runelite.api.Client; -import net.runelite.api.Constants; - -final class ClientPanel extends JPanel -{ - public ClientPanel(@Nullable Applet client) - { - setSize(Constants.GAME_FIXED_SIZE); - setMinimumSize(Constants.GAME_FIXED_SIZE); - setPreferredSize(Constants.GAME_FIXED_SIZE); - setLayout(new BorderLayout()); - setBackground(Color.black); - - if (client == null) - { - return; - } - - client.setLayout(null); - client.setSize(Constants.GAME_FIXED_SIZE); - - client.init(); - client.start(); - - add(client, BorderLayout.CENTER); - - // This causes the whole game frame to be redrawn each frame instead - // of only the viewport, so we can hook to MainBufferProvider#draw - // and draw anywhere without it leaving artifacts - if (client instanceof Client) - { - ((Client)client).setGameDrawingMode(2); - } - } +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.ui; + +import java.applet.Applet; +import java.awt.BorderLayout; +import java.awt.Color; +import javax.annotation.Nullable; +import javax.swing.JPanel; +import net.runelite.api.Client; +import net.runelite.api.Constants; + +final class ClientPanel extends JPanel +{ + public ClientPanel(@Nullable Applet client) + { + setSize(Constants.GAME_FIXED_SIZE); + setMinimumSize(Constants.GAME_FIXED_SIZE); + setPreferredSize(Constants.GAME_FIXED_SIZE); + setLayout(new BorderLayout()); + setBackground(Color.black); + + if (client == null) + { + return; + } + + client.setLayout(null); + client.setSize(Constants.GAME_FIXED_SIZE); + + client.init(); + client.start(); + + add(client, BorderLayout.CENTER); + + // This causes the whole game frame to be redrawn each frame instead + // of only the viewport, so we can hook to MainBufferProvider#draw + // and draw anywhere without it leaving artifacts + if (client instanceof Client) + { + ((Client) client).setGameDrawingMode(2); + } + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java b/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java index 9c73179105..8b3fc96130 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java @@ -174,8 +174,8 @@ public class ClientUI { if (!event.getGroup().equals(CONFIG_GROUP) && !(event.getGroup().equals(PLUS_CONFIG_GROUP) - && event.getKey().equals(CONFIG_OPACITY) || - event.getKey().equals(CONFIG_OPACITY_AMOUNT)) || + && event.getKey().equals(CONFIG_OPACITY) || + event.getKey().equals(CONFIG_OPACITY_AMOUNT)) || event.getKey().equals(CONFIG_CLIENT_MAXIMIZED) || event.getKey().equals(CONFIG_CLIENT_BOUNDS)) { @@ -278,7 +278,7 @@ public class ClientUI return; } - final Client client = (Client)this.client; + final Client client = (Client) this.client; final ClientThread clientThread = clientThreadProvider.get(); // Keep scheduling event until we get our name @@ -615,8 +615,9 @@ public class ClientUI /** * Changes cursor for client window. Requires ${@link ClientUI#open(RuneLite)} to be called first. * FIXME: This is working properly only on Windows, Linux and Mac are displaying cursor incorrectly + * * @param image cursor image - * @param name cursor name + * @param name cursor name */ public void setCursor(final BufferedImage image, final String name) { @@ -632,6 +633,7 @@ public class ClientUI /** * Resets client window cursor to default one. + * * @see ClientUI#setCursor(BufferedImage, String) */ public void resetCursor() @@ -666,6 +668,7 @@ public class ClientUI /** * Paint UI related overlays to target graphics + * * @param graphics target graphics */ public void paintOverlays(final Graphics2D graphics) @@ -845,7 +848,7 @@ public class ClientUI if (config.usernameInTitle() && (client instanceof Client)) { - final Player player = ((Client)client).getLocalPlayer(); + final Player player = ((Client) client).getLocalPlayer(); if (player != null && player.getName() != null) { diff --git a/runelite-client/src/main/java/net/runelite/client/ui/ContainableFrame.java b/runelite-client/src/main/java/net/runelite/client/ui/ContainableFrame.java index 0748731c9a..32436a23a3 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/ContainableFrame.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/ContainableFrame.java @@ -1,200 +1,202 @@ -/* - * Copyright (c) 2018, Woox - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.ui; - -import java.awt.Frame; -import java.awt.Rectangle; -import javax.swing.JFrame; -import lombok.Setter; -import net.runelite.client.config.ExpandResizeType; - -public class ContainableFrame extends JFrame -{ - private static final int SCREEN_EDGE_CLOSE_DISTANCE = 40; - - @Setter - private ExpandResizeType expandResizeType; - private boolean containedInScreen; - private boolean expandedClientOppositeDirection; - - public void setContainedInScreen(boolean value) - { - this.containedInScreen = value; - - if (value) - { - // Reposition the frame if it is intersecting with the bounds - this.setLocation(this.getX(), this.getY()); - this.setBounds(this.getX(), this.getY(), this.getWidth(), this.getHeight()); - } - } - - @Override - public void setLocation(int x, int y) - { - if (containedInScreen) - { - Rectangle bounds = this.getGraphicsConfiguration().getBounds(); - x = Math.max(x, (int)bounds.getX()); - x = Math.min(x, (int)(bounds.getX() + bounds.getWidth() - this.getWidth())); - y = Math.max(y, (int)bounds.getY()); - y = Math.min(y, (int)(bounds.getY() + bounds.getHeight() - this.getHeight())); - } - - super.setLocation(x, y); - } - - @Override - public void setBounds(int x, int y, int width, int height) - { - if (containedInScreen) - { - Rectangle bounds = this.getGraphicsConfiguration().getBounds(); - width = Math.min(width, width - (int)bounds.getX() + x); - x = Math.max(x, (int)bounds.getX()); - height = Math.min(height, height - (int)bounds.getY() + y); - y = Math.max(y, (int)bounds.getY()); - width = Math.min(width, (int)(bounds.getX() + bounds.getWidth()) - x); - height = Math.min(height, (int)(bounds.getY() + bounds.getHeight()) - y); - } - - super.setBounds(x, y, width, height); - } - - /** - * Expand frame by specified value. If the frame is going to be expanded outside of screen push the frame to - * the side. - * @param value size to expand frame by - */ - public void expandBy(final int value) - { - if (isFullScreen()) - { - return; - } - - int increment = value; - boolean forcedWidthIncrease = false; - - if (expandResizeType == ExpandResizeType.KEEP_WINDOW_SIZE) - { - final int minimumWidth = getLayout().minimumLayoutSize(this).width; - final int currentWidth = getWidth(); - - if (minimumWidth > currentWidth) - { - forcedWidthIncrease = true; - increment = minimumWidth - currentWidth; - } - } - - if (forcedWidthIncrease || expandResizeType == ExpandResizeType.KEEP_GAME_SIZE) - { - final int newWindowWidth = getWidth() + increment; - final Rectangle screenBounds = getGraphicsConfiguration().getBounds(); - final boolean wouldExpandThroughEdge = getX() + newWindowWidth > screenBounds.getX() + screenBounds.getWidth(); - int newWindowX = getX(); - - if (wouldExpandThroughEdge) - { - if (!isFrameCloseToRightEdge() || isFrameCloseToLeftEdge()) - { - // Move the window to the edge - newWindowX = (int)(screenBounds.getX() + screenBounds.getWidth()) - getWidth(); - } - - // Expand the window to the left as the user probably don't want the - // window to go through the screen - newWindowX -= increment; - - expandedClientOppositeDirection = true; - } - - setBounds(newWindowX, getY(), newWindowWidth, getHeight()); - } - - revalidateMinimumSize(); - } - - /** - * Contract frame by specified value. If new frame size is less than it's minimum size, force the minimum size. - * If the frame was pushed from side before, restore it's original position. - * @param value value to contract frame by - */ - public void contractBy(final int value) - { - if (isFullScreen()) - { - return; - } - - revalidateMinimumSize(); - final Rectangle screenBounds = getGraphicsConfiguration().getBounds(); - final boolean wasCloseToLeftEdge = Math.abs(getX() - screenBounds.getX()) <= SCREEN_EDGE_CLOSE_DISTANCE; - int newWindowX = getX(); - int newWindowWidth = getWidth() - value; - - if (isFrameCloseToRightEdge() && (expandedClientOppositeDirection || !wasCloseToLeftEdge)) - { - // Keep the distance to the right edge - newWindowX += value; - } - - if (expandResizeType == ExpandResizeType.KEEP_WINDOW_SIZE && newWindowWidth > getMinimumSize().width) - { - // The sidebar fits inside the window, do not resize and move - newWindowWidth = getWidth(); - newWindowX = getX(); - } - - setBounds(newWindowX, getY(), newWindowWidth, getHeight()); - expandedClientOppositeDirection = false; - } - - /** - * Force minimum size of frame to be it's layout manager's minimum size - */ - public void revalidateMinimumSize() - { - setMinimumSize(getLayout().minimumLayoutSize(this)); - } - - private boolean isFullScreen() - { - return (getExtendedState() & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH; - } - - private boolean isFrameCloseToLeftEdge() - { - Rectangle screenBounds = getGraphicsConfiguration().getBounds(); - return Math.abs(getX() - screenBounds.getX()) <= SCREEN_EDGE_CLOSE_DISTANCE; - } - - private boolean isFrameCloseToRightEdge() - { - Rectangle screenBounds = getGraphicsConfiguration().getBounds(); - return Math.abs((getX() + getWidth()) - (screenBounds.getX() + screenBounds.getWidth())) <= SCREEN_EDGE_CLOSE_DISTANCE; - } -} +/* + * Copyright (c) 2018, Woox + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.ui; + +import java.awt.Frame; +import java.awt.Rectangle; +import javax.swing.JFrame; +import lombok.Setter; +import net.runelite.client.config.ExpandResizeType; + +public class ContainableFrame extends JFrame +{ + private static final int SCREEN_EDGE_CLOSE_DISTANCE = 40; + + @Setter + private ExpandResizeType expandResizeType; + private boolean containedInScreen; + private boolean expandedClientOppositeDirection; + + public void setContainedInScreen(boolean value) + { + this.containedInScreen = value; + + if (value) + { + // Reposition the frame if it is intersecting with the bounds + this.setLocation(this.getX(), this.getY()); + this.setBounds(this.getX(), this.getY(), this.getWidth(), this.getHeight()); + } + } + + @Override + public void setLocation(int x, int y) + { + if (containedInScreen) + { + Rectangle bounds = this.getGraphicsConfiguration().getBounds(); + x = Math.max(x, (int) bounds.getX()); + x = Math.min(x, (int) (bounds.getX() + bounds.getWidth() - this.getWidth())); + y = Math.max(y, (int) bounds.getY()); + y = Math.min(y, (int) (bounds.getY() + bounds.getHeight() - this.getHeight())); + } + + super.setLocation(x, y); + } + + @Override + public void setBounds(int x, int y, int width, int height) + { + if (containedInScreen) + { + Rectangle bounds = this.getGraphicsConfiguration().getBounds(); + width = Math.min(width, width - (int) bounds.getX() + x); + x = Math.max(x, (int) bounds.getX()); + height = Math.min(height, height - (int) bounds.getY() + y); + y = Math.max(y, (int) bounds.getY()); + width = Math.min(width, (int) (bounds.getX() + bounds.getWidth()) - x); + height = Math.min(height, (int) (bounds.getY() + bounds.getHeight()) - y); + } + + super.setBounds(x, y, width, height); + } + + /** + * Expand frame by specified value. If the frame is going to be expanded outside of screen push the frame to + * the side. + * + * @param value size to expand frame by + */ + public void expandBy(final int value) + { + if (isFullScreen()) + { + return; + } + + int increment = value; + boolean forcedWidthIncrease = false; + + if (expandResizeType == ExpandResizeType.KEEP_WINDOW_SIZE) + { + final int minimumWidth = getLayout().minimumLayoutSize(this).width; + final int currentWidth = getWidth(); + + if (minimumWidth > currentWidth) + { + forcedWidthIncrease = true; + increment = minimumWidth - currentWidth; + } + } + + if (forcedWidthIncrease || expandResizeType == ExpandResizeType.KEEP_GAME_SIZE) + { + final int newWindowWidth = getWidth() + increment; + final Rectangle screenBounds = getGraphicsConfiguration().getBounds(); + final boolean wouldExpandThroughEdge = getX() + newWindowWidth > screenBounds.getX() + screenBounds.getWidth(); + int newWindowX = getX(); + + if (wouldExpandThroughEdge) + { + if (!isFrameCloseToRightEdge() || isFrameCloseToLeftEdge()) + { + // Move the window to the edge + newWindowX = (int) (screenBounds.getX() + screenBounds.getWidth()) - getWidth(); + } + + // Expand the window to the left as the user probably don't want the + // window to go through the screen + newWindowX -= increment; + + expandedClientOppositeDirection = true; + } + + setBounds(newWindowX, getY(), newWindowWidth, getHeight()); + } + + revalidateMinimumSize(); + } + + /** + * Contract frame by specified value. If new frame size is less than it's minimum size, force the minimum size. + * If the frame was pushed from side before, restore it's original position. + * + * @param value value to contract frame by + */ + public void contractBy(final int value) + { + if (isFullScreen()) + { + return; + } + + revalidateMinimumSize(); + final Rectangle screenBounds = getGraphicsConfiguration().getBounds(); + final boolean wasCloseToLeftEdge = Math.abs(getX() - screenBounds.getX()) <= SCREEN_EDGE_CLOSE_DISTANCE; + int newWindowX = getX(); + int newWindowWidth = getWidth() - value; + + if (isFrameCloseToRightEdge() && (expandedClientOppositeDirection || !wasCloseToLeftEdge)) + { + // Keep the distance to the right edge + newWindowX += value; + } + + if (expandResizeType == ExpandResizeType.KEEP_WINDOW_SIZE && newWindowWidth > getMinimumSize().width) + { + // The sidebar fits inside the window, do not resize and move + newWindowWidth = getWidth(); + newWindowX = getX(); + } + + setBounds(newWindowX, getY(), newWindowWidth, getHeight()); + expandedClientOppositeDirection = false; + } + + /** + * Force minimum size of frame to be it's layout manager's minimum size + */ + public void revalidateMinimumSize() + { + setMinimumSize(getLayout().minimumLayoutSize(this)); + } + + private boolean isFullScreen() + { + return (getExtendedState() & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH; + } + + private boolean isFrameCloseToLeftEdge() + { + Rectangle screenBounds = getGraphicsConfiguration().getBounds(); + return Math.abs(getX() - screenBounds.getX()) <= SCREEN_EDGE_CLOSE_DISTANCE; + } + + private boolean isFrameCloseToRightEdge() + { + Rectangle screenBounds = getGraphicsConfiguration().getBounds(); + return Math.abs((getX() + getWidth()) - (screenBounds.getX() + screenBounds.getWidth())) <= SCREEN_EDGE_CLOSE_DISTANCE; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/ui/DynamicGridLayout.java b/runelite-client/src/main/java/net/runelite/client/ui/DynamicGridLayout.java index 8be06a706c..291b181063 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/DynamicGridLayout.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/DynamicGridLayout.java @@ -1,215 +1,216 @@ -/* - * Copyright (c) 2018, Tomas Slusny - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.ui; - -import java.awt.Component; -import java.awt.Container; -import java.awt.Dimension; -import java.awt.GridLayout; -import java.awt.Insets; -import java.util.function.Function; - -/** - * Grid layout implementation with support for cells with unequal size. - * - * See https://www.javaworld.com/article/2077486/core-java/java-tip-121--flex-your-grid-layout.html - */ -public class DynamicGridLayout extends GridLayout -{ - public DynamicGridLayout() - { - this(1, 0, 0, 0); - } - - public DynamicGridLayout(int rows, int cols) - { - this(rows, cols, 0, 0); - } - - public DynamicGridLayout(int rows, int cols, int hgap, int vgap) - { - super(rows, cols, hgap, vgap); - } - - @Override - public Dimension preferredLayoutSize(Container parent) - { - synchronized (parent.getTreeLock()) - { - return calculateSize(parent, Component::getPreferredSize); - } - } - - @Override - public Dimension minimumLayoutSize(Container parent) - { - synchronized (parent.getTreeLock()) - { - return calculateSize(parent, Component::getMinimumSize); - } - } - - @Override - public void layoutContainer(Container parent) - { - synchronized (parent.getTreeLock()) - { - final Insets insets = parent.getInsets(); - final int ncomponents = parent.getComponentCount(); - int nrows = getRows(); - int ncols = getColumns(); - - if (ncomponents == 0) - { - return; - } - - if (nrows > 0) - { - ncols = (ncomponents + nrows - 1) / nrows; - } - else - { - nrows = (ncomponents + ncols - 1) / ncols; - } - - final int hgap = getHgap(); - final int vgap = getVgap(); - - // scaling factors - final Dimension pd = preferredLayoutSize(parent); - final double sw = (1.0 * parent.getWidth()) / pd.width; - final double sh = (1.0 * parent.getHeight()) / pd.height; - - final int[] w = new int[ncols]; - final int[] h = new int[nrows]; - - // calculate dimensions for all components + apply scaling - for (int i = 0; i < ncomponents; i++) - { - final int r = i / ncols; - final int c = i % ncols; - final Component comp = parent.getComponent(i); - final Dimension d = comp.getPreferredSize(); - d.width = (int) (sw * d.width); - d.height = (int) (sh * d.height); - - if (w[c] < d.width) - { - w[c] = d.width; - } - - if (h[r] < d.height) - { - h[r] = d.height; - } - } - - // Apply new bounds to all child components - for (int c = 0, x = insets.left; c < ncols; c++) - { - for (int r = 0, y = insets.top; r < nrows; r++) - { - int i = r * ncols + c; - - if (i < ncomponents) - { - parent.getComponent(i).setBounds(x, y, w[c], h[r]); - } - - y += h[r] + vgap; - } - - x += w[c] + hgap; - } - } - } - - /** - * Calculate outer size of the layout based on it's children and sizer - * @param parent parent component - * @param sizer functioning returning dimension of the child component - * @return outer size - */ - private Dimension calculateSize(final Container parent, final Function sizer) - { - final int ncomponents = parent.getComponentCount(); - int nrows = getRows(); - int ncols = getColumns(); - - if (nrows > 0) - { - ncols = (ncomponents + nrows - 1) / nrows; - } - else - { - nrows = (ncomponents + ncols - 1) / ncols; - } - - final int[] w = new int[ncols]; - final int[] h = new int[nrows]; - - // Calculate dimensions for all components - for (int i = 0; i < ncomponents; i++) - { - final int r = i / ncols; - final int c = i % ncols; - final Component comp = parent.getComponent(i); - final Dimension d = sizer.apply(comp); - - if (w[c] < d.width) - { - w[c] = d.width; - } - - if (h[r] < d.height) - { - h[r] = d.height; - } - } - - // Calculate total width and height of the layout - int nw = 0; - - for (int j = 0; j < ncols; j++) - { - nw += w[j]; - } - - int nh = 0; - - for (int i = 0; i < nrows; i++) - { - nh += h[i]; - } - - final Insets insets = parent.getInsets(); - - // Apply insets and horizontal and vertical gap to layout - return new Dimension( - insets.left + insets.right + nw + (ncols - 1) * getHgap(), - insets.top + insets.bottom + nh + (nrows - 1) * getVgap()); - } +/* + * Copyright (c) 2018, Tomas Slusny + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.ui; + +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.Insets; +import java.util.function.Function; + +/** + * Grid layout implementation with support for cells with unequal size. + *

+ * See https://www.javaworld.com/article/2077486/core-java/java-tip-121--flex-your-grid-layout.html + */ +public class DynamicGridLayout extends GridLayout +{ + public DynamicGridLayout() + { + this(1, 0, 0, 0); + } + + public DynamicGridLayout(int rows, int cols) + { + this(rows, cols, 0, 0); + } + + public DynamicGridLayout(int rows, int cols, int hgap, int vgap) + { + super(rows, cols, hgap, vgap); + } + + @Override + public Dimension preferredLayoutSize(Container parent) + { + synchronized (parent.getTreeLock()) + { + return calculateSize(parent, Component::getPreferredSize); + } + } + + @Override + public Dimension minimumLayoutSize(Container parent) + { + synchronized (parent.getTreeLock()) + { + return calculateSize(parent, Component::getMinimumSize); + } + } + + @Override + public void layoutContainer(Container parent) + { + synchronized (parent.getTreeLock()) + { + final Insets insets = parent.getInsets(); + final int ncomponents = parent.getComponentCount(); + int nrows = getRows(); + int ncols = getColumns(); + + if (ncomponents == 0) + { + return; + } + + if (nrows > 0) + { + ncols = (ncomponents + nrows - 1) / nrows; + } + else + { + nrows = (ncomponents + ncols - 1) / ncols; + } + + final int hgap = getHgap(); + final int vgap = getVgap(); + + // scaling factors + final Dimension pd = preferredLayoutSize(parent); + final double sw = (1.0 * parent.getWidth()) / pd.width; + final double sh = (1.0 * parent.getHeight()) / pd.height; + + final int[] w = new int[ncols]; + final int[] h = new int[nrows]; + + // calculate dimensions for all components + apply scaling + for (int i = 0; i < ncomponents; i++) + { + final int r = i / ncols; + final int c = i % ncols; + final Component comp = parent.getComponent(i); + final Dimension d = comp.getPreferredSize(); + d.width = (int) (sw * d.width); + d.height = (int) (sh * d.height); + + if (w[c] < d.width) + { + w[c] = d.width; + } + + if (h[r] < d.height) + { + h[r] = d.height; + } + } + + // Apply new bounds to all child components + for (int c = 0, x = insets.left; c < ncols; c++) + { + for (int r = 0, y = insets.top; r < nrows; r++) + { + int i = r * ncols + c; + + if (i < ncomponents) + { + parent.getComponent(i).setBounds(x, y, w[c], h[r]); + } + + y += h[r] + vgap; + } + + x += w[c] + hgap; + } + } + } + + /** + * Calculate outer size of the layout based on it's children and sizer + * + * @param parent parent component + * @param sizer functioning returning dimension of the child component + * @return outer size + */ + private Dimension calculateSize(final Container parent, final Function sizer) + { + final int ncomponents = parent.getComponentCount(); + int nrows = getRows(); + int ncols = getColumns(); + + if (nrows > 0) + { + ncols = (ncomponents + nrows - 1) / nrows; + } + else + { + nrows = (ncomponents + ncols - 1) / ncols; + } + + final int[] w = new int[ncols]; + final int[] h = new int[nrows]; + + // Calculate dimensions for all components + for (int i = 0; i < ncomponents; i++) + { + final int r = i / ncols; + final int c = i % ncols; + final Component comp = parent.getComponent(i); + final Dimension d = sizer.apply(comp); + + if (w[c] < d.width) + { + w[c] = d.width; + } + + if (h[r] < d.height) + { + h[r] = d.height; + } + } + + // Calculate total width and height of the layout + int nw = 0; + + for (int j = 0; j < ncols; j++) + { + nw += w[j]; + } + + int nh = 0; + + for (int i = 0; i < nrows; i++) + { + nh += h[i]; + } + + final Insets insets = parent.getInsets(); + + // Apply insets and horizontal and vertical gap to layout + return new Dimension( + insets.left + insets.right + nw + (ncols - 1) * getHgap(), + insets.top + insets.bottom + nh + (nrows - 1) * getVgap()); + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/ui/FontManager.java b/runelite-client/src/main/java/net/runelite/client/ui/FontManager.java index b6fdac5172..9bff6fe9f9 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/FontManager.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/FontManager.java @@ -1,96 +1,96 @@ -/* - * Copyright (c) 2017, Tyler - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.ui; - -import javax.swing.text.StyleContext; -import java.awt.Font; -import java.awt.FontFormatException; -import java.awt.GraphicsEnvironment; -import java.io.IOException; - -public class FontManager -{ - private static final Font runescapeFont; - private static final Font runescapeSmallFont; - private static final Font runescapeBoldFont; - - static - { - GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); - - try - { - Font font = Font.createFont(Font.TRUETYPE_FONT, - FontManager.class.getResourceAsStream("runescape.ttf")) - .deriveFont(Font.PLAIN, 16); - ge.registerFont(font); - - runescapeFont = StyleContext.getDefaultStyleContext() - .getFont(font.getName(), Font.PLAIN, 16); - ge.registerFont(runescapeFont); - - Font smallFont = Font.createFont(Font.TRUETYPE_FONT, - FontManager.class.getResourceAsStream("runescape_small.ttf")) - .deriveFont(Font.PLAIN, 16); - ge.registerFont(smallFont); - - runescapeSmallFont = StyleContext.getDefaultStyleContext() - .getFont(smallFont.getName(), Font.PLAIN, 16); - ge.registerFont(runescapeSmallFont); - - Font boldFont = Font.createFont(Font.TRUETYPE_FONT, - FontManager.class.getResourceAsStream("runescape_bold.ttf")) - .deriveFont(Font.PLAIN, 16); - ge.registerFont(boldFont); - - runescapeBoldFont = StyleContext.getDefaultStyleContext() - .getFont(boldFont.getName(), Font.PLAIN, 16); - ge.registerFont(runescapeBoldFont); - } - catch (FontFormatException ex) - { - throw new RuntimeException("Font loaded, but format incorrect.", ex); - } - catch (IOException ex) - { - throw new RuntimeException("Font file not found.", ex); - } - } - - public static Font getRunescapeFont() - { - return runescapeFont; - } - - public static Font getRunescapeSmallFont() - { - return runescapeSmallFont; - } - - public static Font getRunescapeBoldFont() - { - return runescapeBoldFont; - } -} +/* + * Copyright (c) 2017, Tyler + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.ui; + +import java.awt.Font; +import java.awt.FontFormatException; +import java.awt.GraphicsEnvironment; +import java.io.IOException; +import javax.swing.text.StyleContext; + +public class FontManager +{ + private static final Font runescapeFont; + private static final Font runescapeSmallFont; + private static final Font runescapeBoldFont; + + static + { + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + + try + { + Font font = Font.createFont(Font.TRUETYPE_FONT, + FontManager.class.getResourceAsStream("runescape.ttf")) + .deriveFont(Font.PLAIN, 16); + ge.registerFont(font); + + runescapeFont = StyleContext.getDefaultStyleContext() + .getFont(font.getName(), Font.PLAIN, 16); + ge.registerFont(runescapeFont); + + Font smallFont = Font.createFont(Font.TRUETYPE_FONT, + FontManager.class.getResourceAsStream("runescape_small.ttf")) + .deriveFont(Font.PLAIN, 16); + ge.registerFont(smallFont); + + runescapeSmallFont = StyleContext.getDefaultStyleContext() + .getFont(smallFont.getName(), Font.PLAIN, 16); + ge.registerFont(runescapeSmallFont); + + Font boldFont = Font.createFont(Font.TRUETYPE_FONT, + FontManager.class.getResourceAsStream("runescape_bold.ttf")) + .deriveFont(Font.PLAIN, 16); + ge.registerFont(boldFont); + + runescapeBoldFont = StyleContext.getDefaultStyleContext() + .getFont(boldFont.getName(), Font.PLAIN, 16); + ge.registerFont(runescapeBoldFont); + } + catch (FontFormatException ex) + { + throw new RuntimeException("Font loaded, but format incorrect.", ex); + } + catch (IOException ex) + { + throw new RuntimeException("Font file not found.", ex); + } + } + + public static Font getRunescapeFont() + { + return runescapeFont; + } + + public static Font getRunescapeSmallFont() + { + return runescapeSmallFont; + } + + public static Font getRunescapeBoldFont() + { + return runescapeBoldFont; + } +} 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 9bbf474cf0..d5b998b0f8 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 @@ -1,243 +1,248 @@ -/* - * Copyright (c) 2016-2017, Jeremy Plsek - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.ui; - -import java.awt.*; -import java.awt.image.BufferedImage; -import java.io.IOException; -import javax.imageio.ImageIO; -import javax.inject.Singleton; -import javax.swing.ImageIcon; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JProgressBar; -import javax.swing.SwingUtilities; -import javax.swing.plaf.basic.BasicProgressBarUI; - -import lombok.extern.slf4j.Slf4j; -import net.runelite.client.RuneLite; -import net.runelite.client.RuneLiteProperties; -import net.runelite.client.util.SwingUtil; -import org.pushingpixels.substance.internal.SubstanceSynapse; - -/** - * This is a custom Splash Screen and does not use Java's SplashScreen class. This has helper methods to update the - * status while loading RuneLite. All public methods run non-blocking passed to the swing thread. - */ -@Slf4j -@Singleton -public class RuneLiteSplashScreen -{ - private RuneLiteProperties runeLiteProperties = new RuneLiteProperties(); - - public JFrame frame; - public JPanel panel = new JPanel(); - public JLabel messageLabel; - public JLabel subMessageLabel; - public JProgressBar progressBar = new JProgressBar(); - - private int currentStep; - - /** - * This is not done in the constructor in order to avoid processing in case the user chooses to not load - * the splash screen. - * @param estimatedSteps steps until completion, used for the progress bar - */ - private void initLayout(final int estimatedSteps) - { - SwingUtil.setupRuneLiteLookAndFeel(); - - // init fields with updated swing look and feel - frame = new JFrame("RuneLitePlus Loading"); - messageLabel = new JLabel("Loading..."); - subMessageLabel = new JLabel(); - progressBar.setUI(new BasicProgressBarUI()); - progressBar.setMinimum(0); - progressBar.setMaximum(estimatedSteps); - - // frame setup - frame.setSize(220, 290); - frame.setLocationRelativeTo(null); - frame.setUndecorated(true); - - // main panel setup - // To reduce substance's colorization (tinting) - panel.putClientProperty(SubstanceSynapse.COLORIZATION_FACTOR, 1.0); - panel.setBackground(ColorScheme.DARKER_GRAY_COLOR); - final GridBagLayout layout = new GridBagLayout(); - layout.columnWeights = new double[]{1}; - layout.rowWeights = new double[]{1, 0, 0, 1, 0, 1}; - panel.setLayout(layout); - - // logo - synchronized (ImageIO.class) - { - try - { - final BufferedImage logo = ImageIO.read(RuneLiteSplashScreen.class.getResourceAsStream("/runeliteplus.png")); - frame.setIconImage(logo); - - final BufferedImage logoTransparent = ImageIO.read(RuneLiteSplashScreen.class.getResourceAsStream("/runeliteplus_transparent.png")); - final GridBagConstraints logoConstraints = new GridBagConstraints(); - logoConstraints.anchor = GridBagConstraints.SOUTH; - panel.add(new JLabel(new ImageIcon(logoTransparent.getScaledInstance(96, 96, Image.SCALE_SMOOTH))), logoConstraints); - } - catch (IOException e) - { - log.warn("Error loading logo", e); - } - } - - // runelite title - final JLabel title = new JLabel("RuneLitePlus"); - final GridBagConstraints titleConstraints = new GridBagConstraints(); - titleConstraints.gridy = 1; - panel.add(title, titleConstraints); - - // version - final JLabel version = new JLabel("RuneLite Version : " + runeLiteProperties.getVersion()); - version.setForeground(Color.GREEN); - version.setFont(FontManager.getRunescapeSmallFont()); - version.setForeground(version.getForeground().darker()); - final GridBagConstraints versionConstraints = new GridBagConstraints(); - versionConstraints.gridy = 2; - panel.add(version, versionConstraints); - - // version - final JLabel litVersion = new JLabel("Plus Version : PRE-" + RuneLite.RUNELIT_VERSION); - litVersion.setForeground(Color.GREEN); - litVersion.setFont(FontManager.getRunescapeSmallFont()); - litVersion.setForeground(litVersion.getForeground().darker()); - final GridBagConstraints litVersionConstraints = new GridBagConstraints(); - litVersionConstraints.gridy = 3; - litVersionConstraints.weightx = 4; - panel.add(litVersion, litVersionConstraints); - - - // progressbar - final GridBagConstraints progressConstraints = new GridBagConstraints(); - progressConstraints.fill = GridBagConstraints.HORIZONTAL; - progressConstraints.anchor = GridBagConstraints.SOUTH; - progressConstraints.gridy = 4; - panel.add(progressBar, progressConstraints); - - // main message - messageLabel.setFont(FontManager.getRunescapeSmallFont()); - final GridBagConstraints messageConstraints = new GridBagConstraints(); - messageConstraints.gridy = 5; - panel.add(messageLabel, messageConstraints); - - // alternate message - final GridBagConstraints subMessageConstraints = new GridBagConstraints(); - subMessageLabel.setForeground(subMessageLabel.getForeground().darker()); - subMessageLabel.setFont(FontManager.getRunescapeSmallFont()); - subMessageConstraints.gridy = 6; - panel.add(subMessageLabel, subMessageConstraints); - - frame.setContentPane(panel); - } - - private boolean notActive() - { - return frame == null || !frame.isDisplayable(); - } - - /** - * Close/dispose of the splash screen - */ - public void close() - { - SwingUtilities.invokeLater(() -> - { - if (notActive()) - { - return; - } - - frame.dispose(); - }); - } - - /** - * Set the splash screen to be visible. - * @param estimatedSteps steps until completion, used for the progress bar - */ - public void open(final int estimatedSteps) - { - SwingUtilities.invokeLater(() -> - { - initLayout(estimatedSteps); - frame.setVisible(true); - }); - } - - public void setMessage(final String message) - { - SwingUtilities.invokeLater(() -> - { - if (notActive()) - { - return; - } - messageLabel.setText(message); - }); - } - - public void setSubMessage(final String subMessage) - { - SwingUtilities.invokeLater(() -> - { - if (notActive()) - { - return; - } - subMessageLabel.setText(subMessage); - }); - } - - public void setProgress(int currentProgress, int progressGoal) - { - SwingUtilities.invokeLater(() -> - { - if (notActive()) - { - return; - } - if (progressGoal!=progressBar.getMaximum()) { - panel.remove(progressBar); - panel.validate(); - final GridBagConstraints progressConstraints = new GridBagConstraints(); - progressConstraints.fill = GridBagConstraints.HORIZONTAL; - progressConstraints.anchor = GridBagConstraints.SOUTH; - progressConstraints.gridy = 4; - panel.add(progressBar, progressConstraints); - panel.validate(); - } - progressBar.setMaximum(progressGoal); - progressBar.setValue(currentProgress); - }); - } -} +/* + * Copyright (c) 2016-2017, Jeremy Plsek + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.ui; + +import java.awt.Color; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Image; +import java.awt.image.BufferedImage; +import java.io.IOException; +import javax.imageio.ImageIO; +import javax.inject.Singleton; +import javax.swing.ImageIcon; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JProgressBar; +import javax.swing.SwingUtilities; +import javax.swing.plaf.basic.BasicProgressBarUI; +import lombok.extern.slf4j.Slf4j; +import net.runelite.client.RuneLite; +import net.runelite.client.RuneLiteProperties; +import net.runelite.client.util.SwingUtil; +import org.pushingpixels.substance.internal.SubstanceSynapse; + +/** + * This is a custom Splash Screen and does not use Java's SplashScreen class. This has helper methods to update the + * status while loading RuneLite. All public methods run non-blocking passed to the swing thread. + */ +@Slf4j +@Singleton +public class RuneLiteSplashScreen +{ + private RuneLiteProperties runeLiteProperties = new RuneLiteProperties(); + + public JFrame frame; + public JPanel panel = new JPanel(); + public JLabel messageLabel; + public JLabel subMessageLabel; + public JProgressBar progressBar = new JProgressBar(); + + private int currentStep; + + /** + * This is not done in the constructor in order to avoid processing in case the user chooses to not load + * the splash screen. + * + * @param estimatedSteps steps until completion, used for the progress bar + */ + private void initLayout(final int estimatedSteps) + { + SwingUtil.setupRuneLiteLookAndFeel(); + + // init fields with updated swing look and feel + frame = new JFrame("RuneLitePlus Loading"); + messageLabel = new JLabel("Loading..."); + subMessageLabel = new JLabel(); + progressBar.setUI(new BasicProgressBarUI()); + progressBar.setMinimum(0); + progressBar.setMaximum(estimatedSteps); + + // frame setup + frame.setSize(220, 290); + frame.setLocationRelativeTo(null); + frame.setUndecorated(true); + + // main panel setup + // To reduce substance's colorization (tinting) + panel.putClientProperty(SubstanceSynapse.COLORIZATION_FACTOR, 1.0); + panel.setBackground(ColorScheme.DARKER_GRAY_COLOR); + final GridBagLayout layout = new GridBagLayout(); + layout.columnWeights = new double[]{1}; + layout.rowWeights = new double[]{1, 0, 0, 1, 0, 1}; + panel.setLayout(layout); + + // logo + synchronized (ImageIO.class) + { + try + { + final BufferedImage logo = ImageIO.read(RuneLiteSplashScreen.class.getResourceAsStream("/runeliteplus.png")); + frame.setIconImage(logo); + + final BufferedImage logoTransparent = ImageIO.read(RuneLiteSplashScreen.class.getResourceAsStream("/runeliteplus_transparent.png")); + final GridBagConstraints logoConstraints = new GridBagConstraints(); + logoConstraints.anchor = GridBagConstraints.SOUTH; + panel.add(new JLabel(new ImageIcon(logoTransparent.getScaledInstance(96, 96, Image.SCALE_SMOOTH))), logoConstraints); + } + catch (IOException e) + { + log.warn("Error loading logo", e); + } + } + + // runelite title + final JLabel title = new JLabel("RuneLitePlus"); + final GridBagConstraints titleConstraints = new GridBagConstraints(); + titleConstraints.gridy = 1; + panel.add(title, titleConstraints); + + // version + final JLabel version = new JLabel("RuneLite Version : " + runeLiteProperties.getVersion()); + version.setForeground(Color.GREEN); + version.setFont(FontManager.getRunescapeSmallFont()); + version.setForeground(version.getForeground().darker()); + final GridBagConstraints versionConstraints = new GridBagConstraints(); + versionConstraints.gridy = 2; + panel.add(version, versionConstraints); + + // version + final JLabel litVersion = new JLabel("Plus Version : PRE-" + RuneLite.RUNELIT_VERSION); + litVersion.setForeground(Color.GREEN); + litVersion.setFont(FontManager.getRunescapeSmallFont()); + litVersion.setForeground(litVersion.getForeground().darker()); + final GridBagConstraints litVersionConstraints = new GridBagConstraints(); + litVersionConstraints.gridy = 3; + litVersionConstraints.weightx = 4; + panel.add(litVersion, litVersionConstraints); + + + // progressbar + final GridBagConstraints progressConstraints = new GridBagConstraints(); + progressConstraints.fill = GridBagConstraints.HORIZONTAL; + progressConstraints.anchor = GridBagConstraints.SOUTH; + progressConstraints.gridy = 4; + panel.add(progressBar, progressConstraints); + + // main message + messageLabel.setFont(FontManager.getRunescapeSmallFont()); + final GridBagConstraints messageConstraints = new GridBagConstraints(); + messageConstraints.gridy = 5; + panel.add(messageLabel, messageConstraints); + + // alternate message + final GridBagConstraints subMessageConstraints = new GridBagConstraints(); + subMessageLabel.setForeground(subMessageLabel.getForeground().darker()); + subMessageLabel.setFont(FontManager.getRunescapeSmallFont()); + subMessageConstraints.gridy = 6; + panel.add(subMessageLabel, subMessageConstraints); + + frame.setContentPane(panel); + } + + private boolean notActive() + { + return frame == null || !frame.isDisplayable(); + } + + /** + * Close/dispose of the splash screen + */ + public void close() + { + SwingUtilities.invokeLater(() -> + { + if (notActive()) + { + return; + } + + frame.dispose(); + }); + } + + /** + * Set the splash screen to be visible. + * + * @param estimatedSteps steps until completion, used for the progress bar + */ + public void open(final int estimatedSteps) + { + SwingUtilities.invokeLater(() -> + { + initLayout(estimatedSteps); + frame.setVisible(true); + }); + } + + public void setMessage(final String message) + { + SwingUtilities.invokeLater(() -> + { + if (notActive()) + { + return; + } + messageLabel.setText(message); + }); + } + + public void setSubMessage(final String subMessage) + { + SwingUtilities.invokeLater(() -> + { + if (notActive()) + { + return; + } + subMessageLabel.setText(subMessage); + }); + } + + public void setProgress(int currentProgress, int progressGoal) + { + SwingUtilities.invokeLater(() -> + { + if (notActive()) + { + return; + } + if (progressGoal != progressBar.getMaximum()) + { + panel.remove(progressBar); + panel.validate(); + final GridBagConstraints progressConstraints = new GridBagConstraints(); + progressConstraints.fill = GridBagConstraints.HORIZONTAL; + progressConstraints.anchor = GridBagConstraints.SOUTH; + progressConstraints.gridy = 4; + panel.add(progressBar, progressConstraints); + panel.validate(); + } + progressBar.setMaximum(progressGoal); + progressBar.setValue(currentProgress); + }); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/ui/components/DimmableJPanel.java b/runelite-client/src/main/java/net/runelite/client/ui/components/DimmableJPanel.java index c36dd72abe..11131a8413 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/components/DimmableJPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/components/DimmableJPanel.java @@ -1,90 +1,91 @@ -/* - * Copyright (c) 2018, Levi - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.ui.components; - -import java.awt.Color; -import javax.swing.JPanel; -import lombok.Getter; - -public class DimmableJPanel extends JPanel -{ - // Dimming state, allows for restoring original colors before dimming - @Getter - private boolean dimmed = false; - private Color dimmedForeground = null; - private Color dimmedBackground = null; - private Color undimmedForeground = null; - private Color undimmedBackground = null; - - @Override - public void setForeground(Color color) - { - undimmedForeground = color; - dimmedForeground = color.darker(); - super.setForeground(color); - } - - @Override - public void setBackground(Color color) - { - undimmedBackground = color; - dimmedBackground = color.darker(); - super.setBackground(color); - } - - @Override - public Color getForeground() - { - return dimmed ? dimmedForeground : undimmedForeground; - } - - @Override - public Color getBackground() - { - return dimmed ? dimmedBackground : undimmedBackground; - } - - /** - * Dimming sets all parts of this component with darker colors except for the central label - * This is useful for showing that progress is paused - * Setting dim to false will restore the original colors from before the component was dimmed. - * @param dimmed - */ - public void setDimmed(boolean dimmed) - { - this.dimmed = dimmed; - - if (dimmed) - { - super.setBackground(dimmedBackground); - super.setForeground(dimmedForeground); - } - else - { - super.setBackground(undimmedBackground); - super.setForeground(undimmedForeground); - } - } -} +/* + * Copyright (c) 2018, Levi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.ui.components; + +import java.awt.Color; +import javax.swing.JPanel; +import lombok.Getter; + +public class DimmableJPanel extends JPanel +{ + // Dimming state, allows for restoring original colors before dimming + @Getter + private boolean dimmed = false; + private Color dimmedForeground = null; + private Color dimmedBackground = null; + private Color undimmedForeground = null; + private Color undimmedBackground = null; + + @Override + public void setForeground(Color color) + { + undimmedForeground = color; + dimmedForeground = color.darker(); + super.setForeground(color); + } + + @Override + public void setBackground(Color color) + { + undimmedBackground = color; + dimmedBackground = color.darker(); + super.setBackground(color); + } + + @Override + public Color getForeground() + { + return dimmed ? dimmedForeground : undimmedForeground; + } + + @Override + public Color getBackground() + { + return dimmed ? dimmedBackground : undimmedBackground; + } + + /** + * Dimming sets all parts of this component with darker colors except for the central label + * This is useful for showing that progress is paused + * Setting dim to false will restore the original colors from before the component was dimmed. + * + * @param dimmed + */ + public void setDimmed(boolean dimmed) + { + this.dimmed = dimmed; + + if (dimmed) + { + super.setBackground(dimmedBackground); + super.setForeground(dimmedForeground); + } + else + { + super.setBackground(undimmedBackground); + super.setForeground(undimmedForeground); + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/ui/components/ThinProgressBar.java b/runelite-client/src/main/java/net/runelite/client/ui/components/ThinProgressBar.java index f80ff5b740..7a658cade6 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/components/ThinProgressBar.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/components/ThinProgressBar.java @@ -1,95 +1,95 @@ -/* - * Copyright (c) 2018, Psikoi - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.ui.components; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics; -import javax.swing.JPanel; -import lombok.Getter; - -/** - * A progress bar to be displayed underneath the GE offer item panels - */ -public class ThinProgressBar extends JPanel -{ - @Getter - private int maximumValue = 1; - - @Getter - private int value; - - public ThinProgressBar() - { - setForeground(Color.GREEN); - setMaximumSize(new Dimension(Integer.MAX_VALUE, 4)); - setMinimumSize(new Dimension(0, 4)); - setPreferredSize(new Dimension(0, 4)); - setSize(new Dimension(0, 4)); - setOpaque(true); - } - - public double getPercentage() - { - return (value * 100) / maximumValue; - } - - @Override - public void setForeground(Color color) - { - super.setForeground(color); - setBackground(color.darker()); - } - - public void setMaximumValue(int maximumValue) - { - if (maximumValue < 1) - { - maximumValue = 1; - } - this.maximumValue = maximumValue; - repaint(); - } - - public void setValue(int value) - { - this.value = value; - repaint(); - } - - @Override - public void paintComponent(Graphics g) - { - super.paintComponent(g); - int w = getWidth(); - int h = getHeight(); - int div = (value * w) / maximumValue; - g.setColor(getBackground()); - g.fillRect(div, 0, w, h); - g.setColor(getForeground()); - g.fillRect(0, 0, div, h); - } +/* + * Copyright (c) 2018, Psikoi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.ui.components; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import javax.swing.JPanel; +import lombok.Getter; + +/** + * A progress bar to be displayed underneath the GE offer item panels + */ +public class ThinProgressBar extends JPanel +{ + @Getter + private int maximumValue = 1; + + @Getter + private int value; + + public ThinProgressBar() + { + setForeground(Color.GREEN); + setMaximumSize(new Dimension(Integer.MAX_VALUE, 4)); + setMinimumSize(new Dimension(0, 4)); + setPreferredSize(new Dimension(0, 4)); + setSize(new Dimension(0, 4)); + setOpaque(true); + } + + public double getPercentage() + { + return (value * 100) / (double) maximumValue; + } + + @Override + public void setForeground(Color color) + { + super.setForeground(color); + setBackground(color.darker()); + } + + public void setMaximumValue(int maximumValue) + { + if (maximumValue < 1) + { + maximumValue = 1; + } + this.maximumValue = maximumValue; + repaint(); + } + + public void setValue(int value) + { + this.value = value; + repaint(); + } + + @Override + public void paintComponent(Graphics g) + { + super.paintComponent(g); + int w = getWidth(); + int h = getHeight(); + int div = (value * w) / maximumValue; + g.setColor(getBackground()); + g.fillRect(div, 0, w, h); + g.setColor(getForeground()); + g.fillRect(0, 0, div, h); + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/Overlay.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/Overlay.java index 07b9518be3..207d909d8a 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/Overlay.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/Overlay.java @@ -1,71 +1,72 @@ -/* - * Copyright (c) 2016-2017, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.ui.overlay; - -import java.awt.Dimension; -import java.awt.Point; -import java.awt.Rectangle; -import java.util.ArrayList; -import java.util.List; -import javax.annotation.Nullable; -import lombok.Getter; -import lombok.Setter; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.ui.overlay.components.LayoutableRenderableEntity; - -@Getter -@Setter -public abstract class Overlay implements LayoutableRenderableEntity -{ - @Nullable - private final Plugin plugin; - private Point preferredLocation; - private Dimension preferredSize; - private OverlayPosition preferredPosition; - private Rectangle bounds = new Rectangle(); - private OverlayPosition position = OverlayPosition.TOP_LEFT; - private OverlayPriority priority = OverlayPriority.NONE; - private OverlayLayer layer = OverlayLayer.UNDER_WIDGETS; - private final List menuEntries = new ArrayList<>(); - - protected Overlay() - { - plugin = null; - } - - protected Overlay(Plugin plugin) - { - this.plugin = plugin; - } - - /** - * Overlay name, used for saving the overlay, needs to be unique - * @return overlay name - */ - public String getName() - { - return this.getClass().getSimpleName(); - } -} +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.ui.overlay; + +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Rectangle; +import java.util.ArrayList; +import java.util.List; +import javax.annotation.Nullable; +import lombok.Getter; +import lombok.Setter; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.ui.overlay.components.LayoutableRenderableEntity; + +@Getter +@Setter +public abstract class Overlay implements LayoutableRenderableEntity +{ + @Nullable + private final Plugin plugin; + private Point preferredLocation; + private Dimension preferredSize; + private OverlayPosition preferredPosition; + private Rectangle bounds = new Rectangle(); + private OverlayPosition position = OverlayPosition.TOP_LEFT; + private OverlayPriority priority = OverlayPriority.NONE; + private OverlayLayer layer = OverlayLayer.UNDER_WIDGETS; + private final List menuEntries = new ArrayList<>(); + + protected Overlay() + { + plugin = null; + } + + protected Overlay(Plugin plugin) + { + this.plugin = plugin; + } + + /** + * Overlay name, used for saving the overlay, needs to be unique + * + * @return overlay name + */ + public String getName() + { + return this.getClass().getSimpleName(); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayManager.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayManager.java index bb21e1e3f3..fb5d3bfaf7 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayManager.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayManager.java @@ -1,385 +1,385 @@ -/* - * Copyright (c) 2018, Tomas Slusny - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.ui.overlay; - -import com.google.common.annotations.VisibleForTesting; -import java.awt.Dimension; -import java.awt.Point; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.EnumMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.function.Predicate; -import javax.inject.Inject; -import javax.inject.Singleton; -import lombok.AccessLevel; -import lombok.Getter; -import net.runelite.api.MenuAction; -import net.runelite.api.events.MenuOptionClicked; -import net.runelite.api.widgets.WidgetItem; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.client.config.ConfigGroup; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.config.RuneLiteConfig; -import net.runelite.client.eventbus.EventBus; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.events.OverlayMenuClicked; -import net.runelite.client.events.PluginChanged; - -/** - * Manages state of all game overlays - */ -@Singleton -public class OverlayManager -{ - public static final String OPTION_CONFIGURE = "Configure"; - - private static final String OVERLAY_CONFIG_PREFERRED_LOCATION = "_preferredLocation"; - private static final String OVERLAY_CONFIG_PREFERRED_POSITION = "_preferredPosition"; - private static final String OVERLAY_CONFIG_PREFERRED_SIZE = "_preferredSize"; - private static final String RUNELITE_CONFIG_GROUP_NAME = RuneLiteConfig.class.getAnnotation(ConfigGroup.class).value(); - - @VisibleForTesting - static final Comparator OVERLAY_COMPARATOR = (a, b) -> - { - final OverlayPosition aPos = a.getPreferredPosition() != null - ? a.getPreferredPosition() - : a.getPosition(); - - final OverlayPosition bPos = b.getPreferredPosition() != null - ? b.getPreferredPosition() - : b.getPosition(); - - if (aPos != bPos) - { - // This is so non-dynamic overlays render after dynamic - // overlays, which are generally in the scene - return aPos.compareTo(bPos); - } - - // For dynamic overlays, higher priority means to - // draw *later* so it is on top. - // For non-dynamic overlays, higher priority means - // draw *first* so that they are closer to their - // defined position. - return aPos == OverlayPosition.DYNAMIC - ? a.getPriority().compareTo(b.getPriority()) - : b.getPriority().compareTo(a.getPriority()); - }; - - /** - * Insertion-order sorted set of overlays - * All access to this must be guarded by a lock on this OverlayManager - */ - @Getter(AccessLevel.PACKAGE) - private final List overlays = new ArrayList<>(); - @Getter - private final List itemWidgets = new ArrayList<>(); - - private final Map> overlayLayers = new EnumMap<>(OverlayLayer.class); - - private final ConfigManager configManager; - private final EventBus eventBus; - - @Inject - private OverlayManager(final ConfigManager configManager, final EventBus eventBus) - { - this.configManager = configManager; - this.eventBus = eventBus; - } - - @Subscribe - public void onPluginChanged(final PluginChanged event) - { - overlays.forEach(this::loadOverlay); - rebuildOverlayLayers(); - } - - @Subscribe - public void onMenuOptionClicked(MenuOptionClicked event) - { - if (event.getMenuAction() != MenuAction.RUNELITE_OVERLAY) - { - return; - } - - event.consume(); - - Optional optionalOverlay = overlays.stream().filter(o -> overlays.indexOf(o) == event.getId()).findAny(); - if (optionalOverlay.isPresent()) - { - Overlay overlay = optionalOverlay.get(); - List menuEntries = overlay.getMenuEntries(); - Optional optionalOverlayMenuEntry = menuEntries.stream() - .filter(me -> me.getOption().equals(event.getMenuOption())) - .findAny(); - if (optionalOverlayMenuEntry.isPresent()) - { - eventBus.post(new OverlayMenuClicked(optionalOverlayMenuEntry.get(), overlay)); - } - } - } - - /** - * Gets all of the overlays on a layer sorted by priority and position - * - * @param layer the layer - * @return An immutable list of all of the overlays on that layer - */ - synchronized List getLayer(OverlayLayer layer) - { - return overlayLayers.get(layer); - } - - /** - * Add overlay. - * - * @param overlay the overlay - * @return true if overlay was added - */ - public synchronized boolean add(final Overlay overlay) - { - if (overlays.contains(overlay)) - { - return false; - } - - // Add is always true - overlays.add(overlay); - loadOverlay(overlay); - // WidgetItemOverlays have a reference to the overlay manager in order to get the WidgetItems - // for each frame. - if (overlay instanceof WidgetItemOverlay) - { - ((WidgetItemOverlay) overlay).setOverlayManager(this); - } - rebuildOverlayLayers(); - return true; - } - - /** - * Remove overlay. - * - * @param overlay the overlay - * @return true if overlay was removed - */ - public synchronized boolean remove(final Overlay overlay) - { - final boolean remove = overlays.remove(overlay); - - if (remove) - { - rebuildOverlayLayers(); - } - - return remove; - } - - /** - * Remove if overlay matches filter - * - * @param filter the filter - * @return true if any overlay was removed - */ - public synchronized boolean removeIf(Predicate filter) - { - final boolean removeIf = overlays.removeIf(filter); - - if (removeIf) - { - rebuildOverlayLayers(); - } - - return removeIf; - } - - /** - * Clear all overlays - */ - public synchronized void clear() - { - overlays.clear(); - rebuildOverlayLayers(); - } - - /** - * Force save overlay data - * - * @param overlay overlay to save - */ - public synchronized void saveOverlay(final Overlay overlay) - { - saveOverlayPosition(overlay); - saveOverlaySize(overlay); - saveOverlayLocation(overlay); - rebuildOverlayLayers(); - } - - /** - * Resets stored overlay position data - * - * @param overlay overlay to reset - */ - public synchronized void resetOverlay(final Overlay overlay) - { - overlay.setPreferredPosition(null); - overlay.setPreferredSize(null); - overlay.setPreferredLocation(null); - saveOverlay(overlay); - } - - private synchronized void rebuildOverlayLayers() - { - for (OverlayLayer l : OverlayLayer.values()) - { - overlayLayers.put(l, new ArrayList<>()); - } - - for (final Overlay overlay : overlays) - { - OverlayLayer layer = overlay.getLayer(); - - if (overlay.getPreferredLocation() != null && overlay.getPreferredPosition() == null) - { - // When UNDER_WIDGET overlays are in preferred locations, move to - // ABOVE_WIDGETS so that it can draw over interfaces - if (layer == OverlayLayer.UNDER_WIDGETS && !(overlay instanceof WidgetOverlay)) - { - layer = OverlayLayer.ABOVE_WIDGETS; - } - } - - overlayLayers.get(layer).add(overlay); - } - - overlayLayers.forEach((layer, value) -> - { - value.sort(OVERLAY_COMPARATOR); - overlayLayers.put(layer, Collections.unmodifiableList(value)); - }); - } - - private void loadOverlay(final Overlay overlay) - { - final Point location = loadOverlayLocation(overlay); - overlay.setPreferredLocation(location); - final Dimension size = loadOverlaySize(overlay); - overlay.setPreferredSize(size); - final OverlayPosition position = loadOverlayPosition(overlay); - overlay.setPreferredPosition(position); - } - - private void saveOverlayLocation(final Overlay overlay) - { - final String key = overlay.getName() + OVERLAY_CONFIG_PREFERRED_LOCATION; - if (overlay.getPreferredLocation() != null) - { - configManager.setConfiguration( - RUNELITE_CONFIG_GROUP_NAME, - key, - overlay.getPreferredLocation()); - } - else - { - configManager.unsetConfiguration( - RUNELITE_CONFIG_GROUP_NAME, - key); - } - } - - private void saveOverlaySize(final Overlay overlay) - { - final String key = overlay.getName() + OVERLAY_CONFIG_PREFERRED_SIZE; - if (overlay.getPreferredSize() != null) - { - configManager.setConfiguration( - RUNELITE_CONFIG_GROUP_NAME, - key, - overlay.getPreferredSize()); - } - else - { - configManager.unsetConfiguration( - RUNELITE_CONFIG_GROUP_NAME, - key); - } - } - - private void saveOverlayPosition(final Overlay overlay) - { - final String key = overlay.getName() + OVERLAY_CONFIG_PREFERRED_POSITION; - if (overlay.getPreferredPosition() != null) - { - configManager.setConfiguration( - RUNELITE_CONFIG_GROUP_NAME, - key, - overlay.getPreferredPosition()); - } - else - { - configManager.unsetConfiguration( - RUNELITE_CONFIG_GROUP_NAME, - key); - } - } - - private Point loadOverlayLocation(final Overlay overlay) - { - final String key = overlay.getName() + OVERLAY_CONFIG_PREFERRED_LOCATION; - return configManager.getConfiguration(RUNELITE_CONFIG_GROUP_NAME, key, Point.class); - } - - private Dimension loadOverlaySize(final Overlay overlay) - { - final String key = overlay.getName() + OVERLAY_CONFIG_PREFERRED_SIZE; - return configManager.getConfiguration(RUNELITE_CONFIG_GROUP_NAME, key, Dimension.class); - } - - private OverlayPosition loadOverlayPosition(final Overlay overlay) - { - final String locationKey = overlay.getName() + OVERLAY_CONFIG_PREFERRED_POSITION; - return configManager.getConfiguration(RUNELITE_CONFIG_GROUP_NAME, locationKey, OverlayPosition.class); - } - - public WidgetOverlay getWidgetOverlay(final WidgetInfo info) - { - for (Overlay o : overlays) - { - if (o instanceof WidgetOverlay) - { - WidgetOverlay overlay = (WidgetOverlay) o; - if (overlay.getWidgetInfo().equals(info)) - { - return overlay; - } - } - } - - return null; - } +/* + * Copyright (c) 2018, Tomas Slusny + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.ui.overlay; + +import com.google.common.annotations.VisibleForTesting; +import java.awt.Dimension; +import java.awt.Point; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Predicate; +import javax.inject.Inject; +import javax.inject.Singleton; +import lombok.AccessLevel; +import lombok.Getter; +import net.runelite.api.MenuAction; +import net.runelite.api.events.MenuOptionClicked; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.api.widgets.WidgetItem; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.config.RuneLiteConfig; +import net.runelite.client.eventbus.EventBus; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.events.OverlayMenuClicked; +import net.runelite.client.events.PluginChanged; + +/** + * Manages state of all game overlays + */ +@Singleton +public class OverlayManager +{ + public static final String OPTION_CONFIGURE = "Configure"; + + private static final String OVERLAY_CONFIG_PREFERRED_LOCATION = "_preferredLocation"; + private static final String OVERLAY_CONFIG_PREFERRED_POSITION = "_preferredPosition"; + private static final String OVERLAY_CONFIG_PREFERRED_SIZE = "_preferredSize"; + private static final String RUNELITE_CONFIG_GROUP_NAME = RuneLiteConfig.class.getAnnotation(ConfigGroup.class).value(); + + @VisibleForTesting + static final Comparator OVERLAY_COMPARATOR = (a, b) -> + { + final OverlayPosition aPos = a.getPreferredPosition() != null + ? a.getPreferredPosition() + : a.getPosition(); + + final OverlayPosition bPos = b.getPreferredPosition() != null + ? b.getPreferredPosition() + : b.getPosition(); + + if (aPos != bPos) + { + // This is so non-dynamic overlays render after dynamic + // overlays, which are generally in the scene + return aPos.compareTo(bPos); + } + + // For dynamic overlays, higher priority means to + // draw *later* so it is on top. + // For non-dynamic overlays, higher priority means + // draw *first* so that they are closer to their + // defined position. + return aPos == OverlayPosition.DYNAMIC + ? a.getPriority().compareTo(b.getPriority()) + : b.getPriority().compareTo(a.getPriority()); + }; + + /** + * Insertion-order sorted set of overlays + * All access to this must be guarded by a lock on this OverlayManager + */ + @Getter(AccessLevel.PACKAGE) + private final List overlays = new ArrayList<>(); + @Getter + private final List itemWidgets = new ArrayList<>(); + + private final Map> overlayLayers = new EnumMap<>(OverlayLayer.class); + + private final ConfigManager configManager; + private final EventBus eventBus; + + @Inject + private OverlayManager(final ConfigManager configManager, final EventBus eventBus) + { + this.configManager = configManager; + this.eventBus = eventBus; + } + + @Subscribe + public void onPluginChanged(final PluginChanged event) + { + overlays.forEach(this::loadOverlay); + rebuildOverlayLayers(); + } + + @Subscribe + public void onMenuOptionClicked(MenuOptionClicked event) + { + if (event.getMenuAction() != MenuAction.RUNELITE_OVERLAY) + { + return; + } + + event.consume(); + + Optional optionalOverlay = overlays.stream().filter(o -> overlays.indexOf(o) == event.getId()).findAny(); + if (optionalOverlay.isPresent()) + { + Overlay overlay = optionalOverlay.get(); + List menuEntries = overlay.getMenuEntries(); + Optional optionalOverlayMenuEntry = menuEntries.stream() + .filter(me -> me.getOption().equals(event.getMenuOption())) + .findAny(); + if (optionalOverlayMenuEntry.isPresent()) + { + eventBus.post(new OverlayMenuClicked(optionalOverlayMenuEntry.get(), overlay)); + } + } + } + + /** + * Gets all of the overlays on a layer sorted by priority and position + * + * @param layer the layer + * @return An immutable list of all of the overlays on that layer + */ + synchronized List getLayer(OverlayLayer layer) + { + return overlayLayers.get(layer); + } + + /** + * Add overlay. + * + * @param overlay the overlay + * @return true if overlay was added + */ + public synchronized boolean add(final Overlay overlay) + { + if (overlays.contains(overlay)) + { + return false; + } + + // Add is always true + overlays.add(overlay); + loadOverlay(overlay); + // WidgetItemOverlays have a reference to the overlay manager in order to get the WidgetItems + // for each frame. + if (overlay instanceof WidgetItemOverlay) + { + ((WidgetItemOverlay) overlay).setOverlayManager(this); + } + rebuildOverlayLayers(); + return true; + } + + /** + * Remove overlay. + * + * @param overlay the overlay + * @return true if overlay was removed + */ + public synchronized boolean remove(final Overlay overlay) + { + final boolean remove = overlays.remove(overlay); + + if (remove) + { + rebuildOverlayLayers(); + } + + return remove; + } + + /** + * Remove if overlay matches filter + * + * @param filter the filter + * @return true if any overlay was removed + */ + public synchronized boolean removeIf(Predicate filter) + { + final boolean removeIf = overlays.removeIf(filter); + + if (removeIf) + { + rebuildOverlayLayers(); + } + + return removeIf; + } + + /** + * Clear all overlays + */ + public synchronized void clear() + { + overlays.clear(); + rebuildOverlayLayers(); + } + + /** + * Force save overlay data + * + * @param overlay overlay to save + */ + public synchronized void saveOverlay(final Overlay overlay) + { + saveOverlayPosition(overlay); + saveOverlaySize(overlay); + saveOverlayLocation(overlay); + rebuildOverlayLayers(); + } + + /** + * Resets stored overlay position data + * + * @param overlay overlay to reset + */ + public synchronized void resetOverlay(final Overlay overlay) + { + overlay.setPreferredPosition(null); + overlay.setPreferredSize(null); + overlay.setPreferredLocation(null); + saveOverlay(overlay); + } + + private synchronized void rebuildOverlayLayers() + { + for (OverlayLayer l : OverlayLayer.values()) + { + overlayLayers.put(l, new ArrayList<>()); + } + + for (final Overlay overlay : overlays) + { + OverlayLayer layer = overlay.getLayer(); + + if (overlay.getPreferredLocation() != null && overlay.getPreferredPosition() == null) + { + // When UNDER_WIDGET overlays are in preferred locations, move to + // ABOVE_WIDGETS so that it can draw over interfaces + if (layer == OverlayLayer.UNDER_WIDGETS && !(overlay instanceof WidgetOverlay)) + { + layer = OverlayLayer.ABOVE_WIDGETS; + } + } + + overlayLayers.get(layer).add(overlay); + } + + overlayLayers.forEach((layer, value) -> + { + value.sort(OVERLAY_COMPARATOR); + overlayLayers.put(layer, Collections.unmodifiableList(value)); + }); + } + + private void loadOverlay(final Overlay overlay) + { + final Point location = loadOverlayLocation(overlay); + overlay.setPreferredLocation(location); + final Dimension size = loadOverlaySize(overlay); + overlay.setPreferredSize(size); + final OverlayPosition position = loadOverlayPosition(overlay); + overlay.setPreferredPosition(position); + } + + private void saveOverlayLocation(final Overlay overlay) + { + final String key = overlay.getName() + OVERLAY_CONFIG_PREFERRED_LOCATION; + if (overlay.getPreferredLocation() != null) + { + configManager.setConfiguration( + RUNELITE_CONFIG_GROUP_NAME, + key, + overlay.getPreferredLocation()); + } + else + { + configManager.unsetConfiguration( + RUNELITE_CONFIG_GROUP_NAME, + key); + } + } + + private void saveOverlaySize(final Overlay overlay) + { + final String key = overlay.getName() + OVERLAY_CONFIG_PREFERRED_SIZE; + if (overlay.getPreferredSize() != null) + { + configManager.setConfiguration( + RUNELITE_CONFIG_GROUP_NAME, + key, + overlay.getPreferredSize()); + } + else + { + configManager.unsetConfiguration( + RUNELITE_CONFIG_GROUP_NAME, + key); + } + } + + private void saveOverlayPosition(final Overlay overlay) + { + final String key = overlay.getName() + OVERLAY_CONFIG_PREFERRED_POSITION; + if (overlay.getPreferredPosition() != null) + { + configManager.setConfiguration( + RUNELITE_CONFIG_GROUP_NAME, + key, + overlay.getPreferredPosition()); + } + else + { + configManager.unsetConfiguration( + RUNELITE_CONFIG_GROUP_NAME, + key); + } + } + + private Point loadOverlayLocation(final Overlay overlay) + { + final String key = overlay.getName() + OVERLAY_CONFIG_PREFERRED_LOCATION; + return configManager.getConfiguration(RUNELITE_CONFIG_GROUP_NAME, key, Point.class); + } + + private Dimension loadOverlaySize(final Overlay overlay) + { + final String key = overlay.getName() + OVERLAY_CONFIG_PREFERRED_SIZE; + return configManager.getConfiguration(RUNELITE_CONFIG_GROUP_NAME, key, Dimension.class); + } + + private OverlayPosition loadOverlayPosition(final Overlay overlay) + { + final String locationKey = overlay.getName() + OVERLAY_CONFIG_PREFERRED_POSITION; + return configManager.getConfiguration(RUNELITE_CONFIG_GROUP_NAME, locationKey, OverlayPosition.class); + } + + public WidgetOverlay getWidgetOverlay(final WidgetInfo info) + { + for (Overlay o : overlays) + { + if (o instanceof WidgetOverlay) + { + WidgetOverlay overlay = (WidgetOverlay) o; + if (overlay.getWidgetInfo().equals(info)) + { + return overlay; + } + } + } + + return null; + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java index a9f2e9f017..ec85807477 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java @@ -1,581 +1,581 @@ -/* - * Copyright (c) 2016-2017, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.ui.overlay; - -import com.google.common.base.MoreObjects; -import com.google.common.primitives.Ints; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.event.KeyEvent; -import java.awt.event.MouseEvent; -import java.util.List; -import javax.inject.Inject; -import javax.inject.Singleton; -import javax.swing.SwingUtilities; -import net.runelite.api.Client; -import net.runelite.api.GameState; -import net.runelite.api.MenuAction; -import net.runelite.api.MenuEntry; -import net.runelite.api.events.BeforeRender; -import net.runelite.api.events.ClientTick; -import net.runelite.api.events.FocusChanged; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.client.config.RuneLiteConfig; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.input.KeyListener; -import net.runelite.client.input.KeyManager; -import net.runelite.client.input.MouseAdapter; -import net.runelite.client.input.MouseManager; -import net.runelite.client.ui.JagexColors; -import net.runelite.client.util.ColorUtil; - -@Singleton -public class OverlayRenderer extends MouseAdapter implements KeyListener -{ - private static final int BORDER = 5; - private static final int BORDER_TOP = BORDER + 15; - private static final int PADDING = 2; - private static final Dimension SNAP_CORNER_SIZE = new Dimension(80, 80); - private static final Color SNAP_CORNER_COLOR = new Color(0, 255, 255, 50); - private static final Color SNAP_CORNER_ACTIVE_COLOR = new Color(0, 255, 0, 100); - private static final Color MOVING_OVERLAY_COLOR = new Color(255, 255, 0, 100); - private static final Color MOVING_OVERLAY_ACTIVE_COLOR = new Color(255, 255, 0, 200); - private final Client client; - private final OverlayManager overlayManager; - private final RuneLiteConfig runeLiteConfig; - - // Overlay movement variables - private final Point overlayOffset = new Point(); - private final Point mousePosition = new Point(); - private Overlay movedOverlay; - private boolean inOverlayDraggingMode; - private boolean inMenuEntryMode; - private MenuEntry[] menuEntries; - - // Overlay state validation - private Rectangle viewportBounds; - private Rectangle chatboxBounds; - private int viewportOffset; - private boolean chatboxHidden; - private boolean isResizeable; - private OverlayBounds snapCorners; - - @Inject - private OverlayRenderer( - final Client client, - final OverlayManager overlayManager, - final RuneLiteConfig runeLiteConfig, - final MouseManager mouseManager, - final KeyManager keyManager) - { - this.client = client; - this.overlayManager = overlayManager; - this.runeLiteConfig = runeLiteConfig; - keyManager.registerKeyListener(this); - mouseManager.registerMouseListener(this); - } - - @Subscribe - public void onFocusChanged(FocusChanged event) - { - if (!event.isFocused()) - { - inOverlayDraggingMode = false; - inMenuEntryMode = false; - menuEntries = null; - } - } - - @Subscribe - protected void onClientTick(ClientTick t) - { - if (menuEntries == null) - { - return; - } - - if (!inMenuEntryMode && runeLiteConfig.menuEntryShift()) - { - return; - } - - if (client.isMenuOpen()) - { - return; - } - - MenuEntry[] clientMenuEntries = client.getMenuEntries(); - MenuEntry[] newEntries = new MenuEntry[clientMenuEntries.length + menuEntries.length]; - - newEntries[0] = clientMenuEntries[0]; // Keep cancel at 0 - System.arraycopy(menuEntries, 0, newEntries, 1, menuEntries.length); // Add overlay menu entries - System.arraycopy(clientMenuEntries, 1, newEntries, menuEntries.length + 1, clientMenuEntries.length - 1); // Add remaining menu entries - client.setMenuEntries(newEntries); - } - - @Subscribe - public void onBeforeRender(BeforeRender event) - { - menuEntries = null; - } - - public void render(Graphics2D graphics, final OverlayLayer layer) - { - if (layer != OverlayLayer.ABOVE_MAP - && client.getWidget(WidgetInfo.FULLSCREEN_MAP_ROOT) != null - && !client.getWidget(WidgetInfo.FULLSCREEN_MAP_ROOT).isHidden()) - { - return; - } - - final List overlays = overlayManager.getLayer(layer); - - if (overlays == null - || overlays.isEmpty() - || client.getGameState() != GameState.LOGGED_IN - || client.getWidget(WidgetInfo.LOGIN_CLICK_TO_PLAY_SCREEN) != null - || client.getViewportWidget() == null) - { - return; - } - - if (shouldInvalidateBounds()) - { - snapCorners = buildSnapCorners(); - } - - // Create copy of snap corners because overlays will modify them - OverlayBounds snapCorners = new OverlayBounds(this.snapCorners); - OverlayUtil.setGraphicProperties(graphics); - - // Draw snap corners - if (layer == OverlayLayer.UNDER_WIDGETS && movedOverlay != null && movedOverlay.getPosition() != OverlayPosition.DETACHED) - { - final OverlayBounds translatedSnapCorners = snapCorners.translated( - -SNAP_CORNER_SIZE.width, - -SNAP_CORNER_SIZE.height); - - final Color previous = graphics.getColor(); - - for (final Rectangle corner : translatedSnapCorners.getBounds()) - { - graphics.setColor(corner.contains(mousePosition) ? SNAP_CORNER_ACTIVE_COLOR : SNAP_CORNER_COLOR); - graphics.fill(corner); - } - - graphics.setColor(previous); - } - - // Get mouse position - final net.runelite.api.Point mouseCanvasPosition = client.getMouseCanvasPosition(); - final Point mouse = new Point(mouseCanvasPosition.getX(), mouseCanvasPosition.getY()); - - for (Overlay overlay : overlays) - { - OverlayPosition overlayPosition = overlay.getPosition(); - - if (overlay.getPreferredPosition() != null) - { - overlayPosition = overlay.getPreferredPosition(); - } - - if (!isResizeable) - { - // On fixed mode, ABOVE_CHATBOX_RIGHT is in the same location as - // BOTTOM_RIGHT and CANVAST_TOP_RIGHT is same as TOP_RIGHT. - // Just use BOTTOM_RIGHT and TOP_RIGHT to prevent overlays from - // drawing over each other. - switch (overlayPosition) - { - case CANVAS_TOP_RIGHT: - overlayPosition = OverlayPosition.TOP_RIGHT; - break; - case ABOVE_CHATBOX_RIGHT: - overlayPosition = OverlayPosition.BOTTOM_RIGHT; - break; - } - } - - if (overlayPosition == OverlayPosition.DYNAMIC || overlayPosition == OverlayPosition.TOOLTIP) - { - safeRender(client, overlay, layer, graphics, new Point()); - } - else - { - final Point location = overlay.getBounds().getLocation(); - final Dimension dimension = overlay.getBounds().getSize(); - - // If the final position is not modified, layout it - if (overlayPosition != OverlayPosition.DETACHED && (overlay.getPreferredLocation() == null || overlay.getPreferredPosition() != null)) - { - final Rectangle snapCorner = snapCorners.forPosition(overlayPosition); - final Point translation = OverlayUtil.transformPosition(overlayPosition, dimension); - location.setLocation(snapCorner.getX() + translation.x, snapCorner.getY() + translation.y); - final Point padding = OverlayUtil.padPosition(overlayPosition, dimension, PADDING); - snapCorner.translate(padding.x, padding.y); - } - else - { - final Point preferredLocation = overlay.getPreferredLocation(); - - if (preferredLocation != null) - { - location.setLocation(preferredLocation); - } - - final Dimension realDimensions = client.getRealDimensions(); - location.x = Ints.constrainToRange(location.x, 0, Math.max(0, realDimensions.width - dimension.width)); - location.y = Ints.constrainToRange(location.y, 0, Math.max(0, realDimensions.height - dimension.height)); - } - - if (overlay.getPreferredSize() != null) - { - overlay.getBounds().setSize(overlay.getPreferredSize()); - } - - safeRender(client, overlay, layer, graphics, location); - final Rectangle bounds = overlay.getBounds(); - - if (bounds.isEmpty()) - { - continue; - } - - if (inOverlayDraggingMode) - { - final Color previous = graphics.getColor(); - graphics.setColor(movedOverlay == overlay ? MOVING_OVERLAY_ACTIVE_COLOR : MOVING_OVERLAY_COLOR); - graphics.draw(bounds); - graphics.setColor(previous); - } - - if (menuEntries == null && !client.isMenuOpen() && bounds.contains(mouse)) - { - menuEntries = createRightClickMenuEntries(overlay); - } - } - } - } - - @Override - public MouseEvent mousePressed(MouseEvent mouseEvent) - { - if (!inOverlayDraggingMode) - { - return mouseEvent; - } - - final Point mousePoint = mouseEvent.getPoint(); - mousePosition.setLocation(mousePoint); - - synchronized (overlayManager) - { - for (Overlay overlay : overlayManager.getOverlays()) - { - if (overlay.getBounds().contains(mousePoint)) - { - if (SwingUtilities.isRightMouseButton(mouseEvent)) - { - overlayManager.resetOverlay(overlay); - } - else - { - final Point offset = new Point(mousePoint.x, mousePoint.y); - offset.translate(-overlay.getBounds().x, -overlay.getBounds().y); - overlayOffset.setLocation(offset); - - mousePoint.translate(-offset.x, -offset.y); - movedOverlay = overlay; - movedOverlay.setPreferredPosition(null); - movedOverlay.setPreferredLocation(mousePoint); - overlayManager.saveOverlay(movedOverlay); - } - - mouseEvent.consume(); - break; - } - } - } - - return mouseEvent; - } - - @Override - public MouseEvent mouseDragged(MouseEvent mouseEvent) - { - if (!inOverlayDraggingMode) - { - return mouseEvent; - } - - final Point mousePoint = mouseEvent.getPoint(); - mousePosition.setLocation(mousePoint); - final Rectangle canvasRect = new Rectangle(client.getRealDimensions()); - - if (!canvasRect.contains(mousePoint)) - { - return mouseEvent; - } - - if (movedOverlay != null) - { - final Dimension realDimension = client.getRealDimensions(); - mousePoint.translate(-overlayOffset.x, -overlayOffset.y); - mousePoint.x = Ints.constrainToRange(mousePoint.x, 0, Math.max(0, realDimension.width - movedOverlay.getBounds().width)); - mousePoint.y = Ints.constrainToRange(mousePoint.y, 0, Math.max(0, realDimension.height - movedOverlay.getBounds().height)); - movedOverlay.setPreferredPosition(null); - movedOverlay.setPreferredLocation(mousePoint); - mouseEvent.consume(); - } - - return mouseEvent; - } - - @Override - public MouseEvent mouseReleased(MouseEvent mouseEvent) - { - if (movedOverlay != null) - { - mousePosition.setLocation(-1, -1); - - // do not snapcorner detached overlays - if (movedOverlay.getPosition() != OverlayPosition.DETACHED) - { - final OverlayBounds snapCorners = this.snapCorners.translated(-SNAP_CORNER_SIZE.width, -SNAP_CORNER_SIZE.height); - - for (Rectangle snapCorner : snapCorners.getBounds()) - { - if (snapCorner.contains(mouseEvent.getPoint())) - { - OverlayPosition position = snapCorners.fromBounds(snapCorner); - - if (position == movedOverlay.getPosition()) - { - // overlay moves back to default position - position = null; - } - - movedOverlay.setPreferredPosition(position); - movedOverlay.setPreferredLocation(null); // from dragging - break; - } - } - } - - overlayManager.saveOverlay(movedOverlay); - movedOverlay = null; - mouseEvent.consume(); - } - - return mouseEvent; - } - - @Override - public void keyTyped(KeyEvent e) - { - } - - @Override - public void keyPressed(KeyEvent e) - { - if (e.isAltDown()) - { - inOverlayDraggingMode = true; - } - - if (e.isShiftDown() && runeLiteConfig.menuEntryShift()) - { - inMenuEntryMode = true; - } - } - - @Override - public void keyReleased(KeyEvent e) - { - if (!e.isAltDown()) - { - inOverlayDraggingMode = false; - } - - if (!e.isShiftDown()) - { - inMenuEntryMode = false; - } - } - - private void safeRender(Client client, Overlay overlay, OverlayLayer layer, Graphics2D graphics, Point point) - { - final Graphics2D subGraphics = (Graphics2D) graphics.create(); - - if (!isResizeable && (layer == OverlayLayer.ABOVE_SCENE || layer == OverlayLayer.UNDER_WIDGETS)) - { - subGraphics.setClip(client.getViewportXOffset(), - client.getViewportYOffset(), - client.getViewportWidth(), - client.getViewportHeight()); - } - - final OverlayPosition position = overlay.getPosition(); - - // Set font based on configuration - if (position == OverlayPosition.DYNAMIC || position == OverlayPosition.DETACHED) - { - subGraphics.setFont(runeLiteConfig.fontType().getFont()); - } - else if (position == OverlayPosition.TOOLTIP) - { - subGraphics.setFont(runeLiteConfig.tooltipFontType().getFont()); - } - else - { - subGraphics.setFont(runeLiteConfig.interfaceFontType().getFont()); - } - - subGraphics.translate(point.x, point.y); - final Dimension dimension = MoreObjects.firstNonNull(overlay.render(subGraphics), new Dimension()); - subGraphics.dispose(); - overlay.setBounds(new Rectangle(point, dimension)); - } - - private boolean shouldInvalidateBounds() - { - final Widget chatbox = client.getWidget(WidgetInfo.CHATBOX); - final boolean resizeableChanged = isResizeable != client.isResized(); - boolean changed = false; - - if (resizeableChanged) - { - isResizeable = client.isResized(); - changed = true; - } - - final boolean chatboxBoundsChanged = chatbox == null || !chatbox.getBounds().equals(chatboxBounds); - - if (chatboxBoundsChanged) - { - chatboxBounds = chatbox != null ? chatbox.getBounds() : new Rectangle(); - changed = true; - } - - final boolean chatboxHiddenChanged = chatboxHidden != (chatbox == null || chatbox.isHidden()); - - if (chatboxHiddenChanged) - { - chatboxHidden = chatbox == null || chatbox.isHidden(); - changed = true; - } - - final boolean viewportChanged = !client.getViewportWidget().getBounds().equals(viewportBounds); - - if (viewportChanged) - { - viewportBounds = client.getViewportWidget().getBounds(); - changed = true; - } - - final boolean viewportOffsetChanged = client.getViewportXOffset() != viewportOffset; - - if (viewportOffsetChanged) - { - viewportOffset = client.getViewportXOffset(); - changed = true; - } - - return changed; - } - - private OverlayBounds buildSnapCorners() - { - final Point topLeftPoint = new Point( - viewportOffset + BORDER, - viewportOffset + BORDER_TOP); - - final Point topCenterPoint = new Point( - viewportOffset + viewportBounds.width / 2, - viewportOffset + BORDER - ); - - final Point topRightPoint = new Point( - viewportOffset + viewportBounds.width - BORDER, - topCenterPoint.y); - - final Point bottomLeftPoint = new Point( - topLeftPoint.x, - viewportOffset + viewportBounds.height - BORDER); - - final Point bottomRightPoint = new Point( - topRightPoint.x, - bottomLeftPoint.y); - - // Check to see if chat box is minimized - if (isResizeable && chatboxHidden) - { - bottomLeftPoint.y += chatboxBounds.height; - } - - final Point rightChatboxPoint = isResizeable ? new Point( - viewportOffset + chatboxBounds.width - BORDER, - bottomLeftPoint.y) : bottomRightPoint; - - final Point canvasTopRightPoint = isResizeable ? new Point( - (int)client.getRealDimensions().getWidth(), - 0) : topRightPoint; - - return new OverlayBounds( - new Rectangle(topLeftPoint, SNAP_CORNER_SIZE), - new Rectangle(topCenterPoint, SNAP_CORNER_SIZE), - new Rectangle(topRightPoint, SNAP_CORNER_SIZE), - new Rectangle(bottomLeftPoint, SNAP_CORNER_SIZE), - new Rectangle(bottomRightPoint, SNAP_CORNER_SIZE), - new Rectangle(rightChatboxPoint, SNAP_CORNER_SIZE), - new Rectangle(canvasTopRightPoint, SNAP_CORNER_SIZE)); - } - - private MenuEntry[] createRightClickMenuEntries(Overlay overlay) - { - List menuEntries = overlay.getMenuEntries(); - final MenuEntry[] entries = new MenuEntry[menuEntries.size()]; - - // Add in reverse order so they display correctly in the right-click menu - for (int i = menuEntries.size() - 1; i >= 0; --i) - { - OverlayMenuEntry overlayMenuEntry = menuEntries.get(i); - - final MenuEntry entry = new MenuEntry(); - entry.setOption(overlayMenuEntry.getOption()); - entry.setTarget(ColorUtil.wrapWithColorTag(overlayMenuEntry.getTarget(), JagexColors.MENU_TARGET)); - entry.setType(MenuAction.RUNELITE_OVERLAY.getId()); - entry.setIdentifier(overlayManager.getOverlays().indexOf(overlay)); // overlay id - - entries[i] = entry; - } - - return entries; - } -} +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.ui.overlay; + +import com.google.common.base.MoreObjects; +import com.google.common.primitives.Ints; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.util.List; +import javax.inject.Inject; +import javax.inject.Singleton; +import javax.swing.SwingUtilities; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.MenuAction; +import net.runelite.api.MenuEntry; +import net.runelite.api.events.BeforeRender; +import net.runelite.api.events.ClientTick; +import net.runelite.api.events.FocusChanged; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.config.RuneLiteConfig; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.input.KeyListener; +import net.runelite.client.input.KeyManager; +import net.runelite.client.input.MouseAdapter; +import net.runelite.client.input.MouseManager; +import net.runelite.client.ui.JagexColors; +import net.runelite.client.util.ColorUtil; + +@Singleton +public class OverlayRenderer extends MouseAdapter implements KeyListener +{ + private static final int BORDER = 5; + private static final int BORDER_TOP = BORDER + 15; + private static final int PADDING = 2; + private static final Dimension SNAP_CORNER_SIZE = new Dimension(80, 80); + private static final Color SNAP_CORNER_COLOR = new Color(0, 255, 255, 50); + private static final Color SNAP_CORNER_ACTIVE_COLOR = new Color(0, 255, 0, 100); + private static final Color MOVING_OVERLAY_COLOR = new Color(255, 255, 0, 100); + private static final Color MOVING_OVERLAY_ACTIVE_COLOR = new Color(255, 255, 0, 200); + private final Client client; + private final OverlayManager overlayManager; + private final RuneLiteConfig runeLiteConfig; + + // Overlay movement variables + private final Point overlayOffset = new Point(); + private final Point mousePosition = new Point(); + private Overlay movedOverlay; + private boolean inOverlayDraggingMode; + private boolean inMenuEntryMode; + private MenuEntry[] menuEntries; + + // Overlay state validation + private Rectangle viewportBounds; + private Rectangle chatboxBounds; + private int viewportOffset; + private boolean chatboxHidden; + private boolean isResizeable; + private OverlayBounds snapCorners; + + @Inject + private OverlayRenderer( + final Client client, + final OverlayManager overlayManager, + final RuneLiteConfig runeLiteConfig, + final MouseManager mouseManager, + final KeyManager keyManager) + { + this.client = client; + this.overlayManager = overlayManager; + this.runeLiteConfig = runeLiteConfig; + keyManager.registerKeyListener(this); + mouseManager.registerMouseListener(this); + } + + @Subscribe + public void onFocusChanged(FocusChanged event) + { + if (!event.isFocused()) + { + inOverlayDraggingMode = false; + inMenuEntryMode = false; + menuEntries = null; + } + } + + @Subscribe + protected void onClientTick(ClientTick t) + { + if (menuEntries == null) + { + return; + } + + if (!inMenuEntryMode && runeLiteConfig.menuEntryShift()) + { + return; + } + + if (client.isMenuOpen()) + { + return; + } + + MenuEntry[] clientMenuEntries = client.getMenuEntries(); + MenuEntry[] newEntries = new MenuEntry[clientMenuEntries.length + menuEntries.length]; + + newEntries[0] = clientMenuEntries[0]; // Keep cancel at 0 + System.arraycopy(menuEntries, 0, newEntries, 1, menuEntries.length); // Add overlay menu entries + System.arraycopy(clientMenuEntries, 1, newEntries, menuEntries.length + 1, clientMenuEntries.length - 1); // Add remaining menu entries + client.setMenuEntries(newEntries); + } + + @Subscribe + public void onBeforeRender(BeforeRender event) + { + menuEntries = null; + } + + public void render(Graphics2D graphics, final OverlayLayer layer) + { + if (layer != OverlayLayer.ABOVE_MAP + && client.getWidget(WidgetInfo.FULLSCREEN_MAP_ROOT) != null + && !client.getWidget(WidgetInfo.FULLSCREEN_MAP_ROOT).isHidden()) + { + return; + } + + final List overlays = overlayManager.getLayer(layer); + + if (overlays == null + || overlays.isEmpty() + || client.getGameState() != GameState.LOGGED_IN + || client.getWidget(WidgetInfo.LOGIN_CLICK_TO_PLAY_SCREEN) != null + || client.getViewportWidget() == null) + { + return; + } + + if (shouldInvalidateBounds()) + { + snapCorners = buildSnapCorners(); + } + + // Create copy of snap corners because overlays will modify them + OverlayBounds snapCorners = new OverlayBounds(this.snapCorners); + OverlayUtil.setGraphicProperties(graphics); + + // Draw snap corners + if (layer == OverlayLayer.UNDER_WIDGETS && movedOverlay != null && movedOverlay.getPosition() != OverlayPosition.DETACHED) + { + final OverlayBounds translatedSnapCorners = snapCorners.translated( + -SNAP_CORNER_SIZE.width, + -SNAP_CORNER_SIZE.height); + + final Color previous = graphics.getColor(); + + for (final Rectangle corner : translatedSnapCorners.getBounds()) + { + graphics.setColor(corner.contains(mousePosition) ? SNAP_CORNER_ACTIVE_COLOR : SNAP_CORNER_COLOR); + graphics.fill(corner); + } + + graphics.setColor(previous); + } + + // Get mouse position + final net.runelite.api.Point mouseCanvasPosition = client.getMouseCanvasPosition(); + final Point mouse = new Point(mouseCanvasPosition.getX(), mouseCanvasPosition.getY()); + + for (Overlay overlay : overlays) + { + OverlayPosition overlayPosition = overlay.getPosition(); + + if (overlay.getPreferredPosition() != null) + { + overlayPosition = overlay.getPreferredPosition(); + } + + if (!isResizeable) + { + // On fixed mode, ABOVE_CHATBOX_RIGHT is in the same location as + // BOTTOM_RIGHT and CANVAST_TOP_RIGHT is same as TOP_RIGHT. + // Just use BOTTOM_RIGHT and TOP_RIGHT to prevent overlays from + // drawing over each other. + switch (overlayPosition) + { + case CANVAS_TOP_RIGHT: + overlayPosition = OverlayPosition.TOP_RIGHT; + break; + case ABOVE_CHATBOX_RIGHT: + overlayPosition = OverlayPosition.BOTTOM_RIGHT; + break; + } + } + + if (overlayPosition == OverlayPosition.DYNAMIC || overlayPosition == OverlayPosition.TOOLTIP) + { + safeRender(client, overlay, layer, graphics, new Point()); + } + else + { + final Point location = overlay.getBounds().getLocation(); + final Dimension dimension = overlay.getBounds().getSize(); + + // If the final position is not modified, layout it + if (overlayPosition != OverlayPosition.DETACHED && (overlay.getPreferredLocation() == null || overlay.getPreferredPosition() != null)) + { + final Rectangle snapCorner = snapCorners.forPosition(overlayPosition); + final Point translation = OverlayUtil.transformPosition(overlayPosition, dimension); + location.setLocation(snapCorner.getX() + translation.x, snapCorner.getY() + translation.y); + final Point padding = OverlayUtil.padPosition(overlayPosition, dimension, PADDING); + snapCorner.translate(padding.x, padding.y); + } + else + { + final Point preferredLocation = overlay.getPreferredLocation(); + + if (preferredLocation != null) + { + location.setLocation(preferredLocation); + } + + final Dimension realDimensions = client.getRealDimensions(); + location.x = Ints.constrainToRange(location.x, 0, Math.max(0, realDimensions.width - dimension.width)); + location.y = Ints.constrainToRange(location.y, 0, Math.max(0, realDimensions.height - dimension.height)); + } + + if (overlay.getPreferredSize() != null) + { + overlay.getBounds().setSize(overlay.getPreferredSize()); + } + + safeRender(client, overlay, layer, graphics, location); + final Rectangle bounds = overlay.getBounds(); + + if (bounds.isEmpty()) + { + continue; + } + + if (inOverlayDraggingMode) + { + final Color previous = graphics.getColor(); + graphics.setColor(movedOverlay == overlay ? MOVING_OVERLAY_ACTIVE_COLOR : MOVING_OVERLAY_COLOR); + graphics.draw(bounds); + graphics.setColor(previous); + } + + if (menuEntries == null && !client.isMenuOpen() && bounds.contains(mouse)) + { + menuEntries = createRightClickMenuEntries(overlay); + } + } + } + } + + @Override + public MouseEvent mousePressed(MouseEvent mouseEvent) + { + if (!inOverlayDraggingMode) + { + return mouseEvent; + } + + final Point mousePoint = mouseEvent.getPoint(); + mousePosition.setLocation(mousePoint); + + synchronized (overlayManager) + { + for (Overlay overlay : overlayManager.getOverlays()) + { + if (overlay.getBounds().contains(mousePoint)) + { + if (SwingUtilities.isRightMouseButton(mouseEvent)) + { + overlayManager.resetOverlay(overlay); + } + else + { + final Point offset = new Point(mousePoint.x, mousePoint.y); + offset.translate(-overlay.getBounds().x, -overlay.getBounds().y); + overlayOffset.setLocation(offset); + + mousePoint.translate(-offset.x, -offset.y); + movedOverlay = overlay; + movedOverlay.setPreferredPosition(null); + movedOverlay.setPreferredLocation(mousePoint); + overlayManager.saveOverlay(movedOverlay); + } + + mouseEvent.consume(); + break; + } + } + } + + return mouseEvent; + } + + @Override + public MouseEvent mouseDragged(MouseEvent mouseEvent) + { + if (!inOverlayDraggingMode) + { + return mouseEvent; + } + + final Point mousePoint = mouseEvent.getPoint(); + mousePosition.setLocation(mousePoint); + final Rectangle canvasRect = new Rectangle(client.getRealDimensions()); + + if (!canvasRect.contains(mousePoint)) + { + return mouseEvent; + } + + if (movedOverlay != null) + { + final Dimension realDimension = client.getRealDimensions(); + mousePoint.translate(-overlayOffset.x, -overlayOffset.y); + mousePoint.x = Ints.constrainToRange(mousePoint.x, 0, Math.max(0, realDimension.width - movedOverlay.getBounds().width)); + mousePoint.y = Ints.constrainToRange(mousePoint.y, 0, Math.max(0, realDimension.height - movedOverlay.getBounds().height)); + movedOverlay.setPreferredPosition(null); + movedOverlay.setPreferredLocation(mousePoint); + mouseEvent.consume(); + } + + return mouseEvent; + } + + @Override + public MouseEvent mouseReleased(MouseEvent mouseEvent) + { + if (movedOverlay != null) + { + mousePosition.setLocation(-1, -1); + + // do not snapcorner detached overlays + if (movedOverlay.getPosition() != OverlayPosition.DETACHED) + { + final OverlayBounds snapCorners = this.snapCorners.translated(-SNAP_CORNER_SIZE.width, -SNAP_CORNER_SIZE.height); + + for (Rectangle snapCorner : snapCorners.getBounds()) + { + if (snapCorner.contains(mouseEvent.getPoint())) + { + OverlayPosition position = snapCorners.fromBounds(snapCorner); + + if (position == movedOverlay.getPosition()) + { + // overlay moves back to default position + position = null; + } + + movedOverlay.setPreferredPosition(position); + movedOverlay.setPreferredLocation(null); // from dragging + break; + } + } + } + + overlayManager.saveOverlay(movedOverlay); + movedOverlay = null; + mouseEvent.consume(); + } + + return mouseEvent; + } + + @Override + public void keyTyped(KeyEvent e) + { + } + + @Override + public void keyPressed(KeyEvent e) + { + if (e.isAltDown()) + { + inOverlayDraggingMode = true; + } + + if (e.isShiftDown() && runeLiteConfig.menuEntryShift()) + { + inMenuEntryMode = true; + } + } + + @Override + public void keyReleased(KeyEvent e) + { + if (!e.isAltDown()) + { + inOverlayDraggingMode = false; + } + + if (!e.isShiftDown()) + { + inMenuEntryMode = false; + } + } + + private void safeRender(Client client, Overlay overlay, OverlayLayer layer, Graphics2D graphics, Point point) + { + final Graphics2D subGraphics = (Graphics2D) graphics.create(); + + if (!isResizeable && (layer == OverlayLayer.ABOVE_SCENE || layer == OverlayLayer.UNDER_WIDGETS)) + { + subGraphics.setClip(client.getViewportXOffset(), + client.getViewportYOffset(), + client.getViewportWidth(), + client.getViewportHeight()); + } + + final OverlayPosition position = overlay.getPosition(); + + // Set font based on configuration + if (position == OverlayPosition.DYNAMIC || position == OverlayPosition.DETACHED) + { + subGraphics.setFont(runeLiteConfig.fontType().getFont()); + } + else if (position == OverlayPosition.TOOLTIP) + { + subGraphics.setFont(runeLiteConfig.tooltipFontType().getFont()); + } + else + { + subGraphics.setFont(runeLiteConfig.interfaceFontType().getFont()); + } + + subGraphics.translate(point.x, point.y); + final Dimension dimension = MoreObjects.firstNonNull(overlay.render(subGraphics), new Dimension()); + subGraphics.dispose(); + overlay.setBounds(new Rectangle(point, dimension)); + } + + private boolean shouldInvalidateBounds() + { + final Widget chatbox = client.getWidget(WidgetInfo.CHATBOX); + final boolean resizeableChanged = isResizeable != client.isResized(); + boolean changed = false; + + if (resizeableChanged) + { + isResizeable = client.isResized(); + changed = true; + } + + final boolean chatboxBoundsChanged = chatbox == null || !chatbox.getBounds().equals(chatboxBounds); + + if (chatboxBoundsChanged) + { + chatboxBounds = chatbox != null ? chatbox.getBounds() : new Rectangle(); + changed = true; + } + + final boolean chatboxHiddenChanged = chatboxHidden != (chatbox == null || chatbox.isHidden()); + + if (chatboxHiddenChanged) + { + chatboxHidden = chatbox == null || chatbox.isHidden(); + changed = true; + } + + final boolean viewportChanged = !client.getViewportWidget().getBounds().equals(viewportBounds); + + if (viewportChanged) + { + viewportBounds = client.getViewportWidget().getBounds(); + changed = true; + } + + final boolean viewportOffsetChanged = client.getViewportXOffset() != viewportOffset; + + if (viewportOffsetChanged) + { + viewportOffset = client.getViewportXOffset(); + changed = true; + } + + return changed; + } + + private OverlayBounds buildSnapCorners() + { + final Point topLeftPoint = new Point( + viewportOffset + BORDER, + viewportOffset + BORDER_TOP); + + final Point topCenterPoint = new Point( + viewportOffset + viewportBounds.width / 2, + viewportOffset + BORDER + ); + + final Point topRightPoint = new Point( + viewportOffset + viewportBounds.width - BORDER, + topCenterPoint.y); + + final Point bottomLeftPoint = new Point( + topLeftPoint.x, + viewportOffset + viewportBounds.height - BORDER); + + final Point bottomRightPoint = new Point( + topRightPoint.x, + bottomLeftPoint.y); + + // Check to see if chat box is minimized + if (isResizeable && chatboxHidden) + { + bottomLeftPoint.y += chatboxBounds.height; + } + + final Point rightChatboxPoint = isResizeable ? new Point( + viewportOffset + chatboxBounds.width - BORDER, + bottomLeftPoint.y) : bottomRightPoint; + + final Point canvasTopRightPoint = isResizeable ? new Point( + (int) client.getRealDimensions().getWidth(), + 0) : topRightPoint; + + return new OverlayBounds( + new Rectangle(topLeftPoint, SNAP_CORNER_SIZE), + new Rectangle(topCenterPoint, SNAP_CORNER_SIZE), + new Rectangle(topRightPoint, SNAP_CORNER_SIZE), + new Rectangle(bottomLeftPoint, SNAP_CORNER_SIZE), + new Rectangle(bottomRightPoint, SNAP_CORNER_SIZE), + new Rectangle(rightChatboxPoint, SNAP_CORNER_SIZE), + new Rectangle(canvasTopRightPoint, SNAP_CORNER_SIZE)); + } + + private MenuEntry[] createRightClickMenuEntries(Overlay overlay) + { + List menuEntries = overlay.getMenuEntries(); + final MenuEntry[] entries = new MenuEntry[menuEntries.size()]; + + // Add in reverse order so they display correctly in the right-click menu + for (int i = menuEntries.size() - 1; i >= 0; --i) + { + OverlayMenuEntry overlayMenuEntry = menuEntries.get(i); + + final MenuEntry entry = new MenuEntry(); + entry.setOption(overlayMenuEntry.getOption()); + entry.setTarget(ColorUtil.wrapWithColorTag(overlayMenuEntry.getTarget(), JagexColors.MENU_TARGET)); + entry.setType(MenuAction.RUNELITE_OVERLAY.getId()); + entry.setIdentifier(overlayManager.getOverlays().indexOf(overlay)); // overlay id + + entries[i] = entry; + } + + return entries; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayUtil.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayUtil.java index bf3d0a3bc2..581977218c 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayUtil.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayUtil.java @@ -37,7 +37,6 @@ import java.awt.image.BufferedImage; import net.runelite.api.Actor; import net.runelite.api.Client; import net.runelite.api.Perspective; -import net.runelite.api.Player; import net.runelite.api.Point; import net.runelite.api.TileObject; import net.runelite.api.coords.LocalPoint; @@ -77,7 +76,7 @@ public class OverlayUtil graphics.setColor(color); graphics.rotate(angle, center.getX(), center.getY()); graphics.drawRect(center.getX() - width / 2, center.getY() - height / 2, width, height); - graphics.rotate(-angle , center.getX(), center.getY()); + graphics.rotate(-angle, center.getX(), center.getY()); } public static void renderTextLocation(Graphics2D graphics, Point txtLoc, String text, Color color) @@ -259,13 +258,13 @@ public class OverlayUtil return result; } - + public static void renderActorTextAndImage(Graphics2D graphics, Actor actor, String text, Color color, - BufferedImage image, int yOffset, int xOffset) + BufferedImage image, int yOffset, int xOffset) { Point textLocation = new Point(actor.getConvexHull().getBounds().x + xOffset, - actor.getConvexHull().getBounds().y + yOffset); - + actor.getConvexHull().getBounds().y + yOffset); + renderImageLocation(graphics, textLocation, image); xOffset = image.getWidth() + 1; yOffset = (image.getHeight() - (int) graphics.getFontMetrics().getStringBounds(text, graphics).getHeight()); diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/WidgetOverlay.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/WidgetOverlay.java index 00f894bf58..68ece82079 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/WidgetOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/WidgetOverlay.java @@ -101,8 +101,8 @@ public class WidgetOverlay extends Overlay int y = bounds.y; x = Math.max(parent.x, x); y = Math.max(parent.y, y); - x = Math.min((int)parent.getMaxX() - bounds.width, x); - y = Math.min((int)parent.getMaxY() - bounds.height, y); + x = Math.min((int) parent.getMaxX() - bounds.width, x); + y = Math.min((int) parent.getMaxY() - bounds.height, y); bounds.setLocation(x, y); return bounds; } @@ -123,8 +123,8 @@ public class WidgetOverlay extends Overlay int y = bounds.y; x = Math.max(parent.x, x); y = Math.max(parent.y, y); - x = Math.min((int)parent.getMaxX() - bounds.width, x); - y = Math.min((int)parent.getMaxY() - bounds.height, y); + x = Math.min((int) parent.getMaxX() - bounds.width, x); + y = Math.min((int) parent.getMaxY() - bounds.height, y); bounds.setLocation(x, y); widget.setOriginalX(0); widget.setOriginalY(0); diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/arrow/ArrowMinimapOverlay.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/arrow/ArrowMinimapOverlay.java index 2dccd96dc7..3d503e5858 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/arrow/ArrowMinimapOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/arrow/ArrowMinimapOverlay.java @@ -200,10 +200,7 @@ public class ArrowMinimapOverlay extends Overlay localPoint = new LocalPoint(localPoint.getX() + 1, localPoint.getY() + 1); } } - else - { - localPoint = npc.getLocalLocation(); - } + localPoint = null; renderMinimapArrow(graphics, arrowPoint, localPoint, localPlayerPos, worldPlayerPos); } diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/arrow/ArrowPointManager.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/arrow/ArrowPointManager.java index 36e547d389..13cbf0b418 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/arrow/ArrowPointManager.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/arrow/ArrowPointManager.java @@ -1,61 +1,59 @@ -/* - * Copyright (c) 2018, Morgan Lewis - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.ui.overlay.arrow; - -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Multimap; -import javax.inject.Singleton; -import lombok.AccessLevel; -import lombok.Getter; -import net.runelite.api.events.NpcSpawned; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.plugins.Plugin; - -@Singleton -public class ArrowPointManager -{ - @Getter(AccessLevel.PACKAGE) - private final Multimap arrowPoints = HashMultimap.create(); - - public void add(Plugin plugin, ArrowPoint arrowPoint) - { - arrowPoints.put(plugin, arrowPoint); - } - - public void remove(Plugin plugin, ArrowPoint arrowPoint) - { - arrowPoints.remove(plugin, arrowPoint); - } - - public void clear(Plugin plugin) - { - arrowPoints.removeAll(plugin); - } - - public void clear() - { - arrowPoints.clear(); - } +/* + * Copyright (c) 2018, Morgan Lewis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.ui.overlay.arrow; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; +import javax.inject.Singleton; +import lombok.AccessLevel; +import lombok.Getter; +import net.runelite.client.plugins.Plugin; + +@Singleton +public class ArrowPointManager +{ + @Getter(AccessLevel.PACKAGE) + private final Multimap arrowPoints = HashMultimap.create(); + + public void add(Plugin plugin, ArrowPoint arrowPoint) + { + arrowPoints.put(plugin, arrowPoint); + } + + public void remove(Plugin plugin, ArrowPoint arrowPoint) + { + arrowPoints.remove(plugin, arrowPoint); + } + + public void clear(Plugin plugin) + { + arrowPoints.removeAll(plugin); + } + + public void clear() + { + arrowPoints.clear(); + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/BackgroundComponent.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/BackgroundComponent.java index 34a19d1469..6a6f52ce95 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/BackgroundComponent.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/BackgroundComponent.java @@ -1,98 +1,98 @@ -/* - * Copyright (c) 2017, Tomas Slusny - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.ui.overlay.components; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import lombok.AllArgsConstructor; -import lombok.NoArgsConstructor; -import lombok.Setter; -import net.runelite.client.ui.overlay.RenderableEntity; - -@NoArgsConstructor -@AllArgsConstructor -@Setter -public class BackgroundComponent implements RenderableEntity -{ - private static final int BORDER_OFFSET = 2; - - private static final int OUTSIDE_STROKE_RED_OFFSET = 14; - private static final int OUTSIDE_STROKE_GREEN_OFFSET = 13; - private static final int OUTSIDE_STROKE_BLUE_OFFSET = 15; - private static final int OUTSIDE_STROKE_ALPHA = 255; - - private static final int INSIDE_STROKE_RED_OFFSET = 20; - private static final int INSIDE_STROKE_GREEN_OFFSET = 21; - private static final int INSIDE_STROKE_BLUE_OFFSET = 19; - private static final int INSIDE_STROKE_ALPHA = 255; - - private Color backgroundColor = ComponentConstants.STANDARD_BACKGROUND_COLOR; - private Rectangle rectangle = new Rectangle(); - private boolean fill = true; - - @Override - public Dimension render(Graphics2D graphics) - { - Color outsideStrokeColor = new Color( - Math.max(0, backgroundColor.getRed() - OUTSIDE_STROKE_RED_OFFSET), - Math.max(0, backgroundColor.getGreen() - OUTSIDE_STROKE_GREEN_OFFSET), - Math.max(0, backgroundColor.getBlue() - OUTSIDE_STROKE_BLUE_OFFSET), - OUTSIDE_STROKE_ALPHA - ); - - Color insideStrokeColor = new Color( - Math.min(255, backgroundColor.getRed() + INSIDE_STROKE_RED_OFFSET), - Math.min(255, backgroundColor.getGreen() + INSIDE_STROKE_GREEN_OFFSET), - Math.min(255, backgroundColor.getBlue() + INSIDE_STROKE_BLUE_OFFSET), - INSIDE_STROKE_ALPHA - ); - - // Render background - if (fill) - { - graphics.setColor(backgroundColor); - graphics.fill(rectangle); - } - - // Render outside stroke - final Rectangle outsideStroke = new Rectangle(); - outsideStroke.setLocation(rectangle.x, rectangle.y); - outsideStroke.setSize(rectangle.width - BORDER_OFFSET / 2, rectangle.height - BORDER_OFFSET / 2); - graphics.setColor(outsideStrokeColor); - graphics.draw(outsideStroke); - - // Render inside stroke - final Rectangle insideStroke = new Rectangle(); - insideStroke.setLocation(rectangle.x + BORDER_OFFSET / 2, rectangle.y + BORDER_OFFSET / 2); - insideStroke.setSize(rectangle.width - BORDER_OFFSET - BORDER_OFFSET / 2, - rectangle.height - BORDER_OFFSET - BORDER_OFFSET / 2); - graphics.setColor(insideStrokeColor); - graphics.draw(insideStroke); - - return new Dimension(rectangle.getSize()); - } -} +/* + * Copyright (c) 2017, Tomas Slusny + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.ui.overlay.components; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.runelite.client.ui.overlay.RenderableEntity; + +@NoArgsConstructor +@AllArgsConstructor +@Setter +public class BackgroundComponent implements RenderableEntity +{ + private static final int BORDER_OFFSET = 2; + + private static final int OUTSIDE_STROKE_RED_OFFSET = 14; + private static final int OUTSIDE_STROKE_GREEN_OFFSET = 13; + private static final int OUTSIDE_STROKE_BLUE_OFFSET = 15; + private static final int OUTSIDE_STROKE_ALPHA = 255; + + private static final int INSIDE_STROKE_RED_OFFSET = 20; + private static final int INSIDE_STROKE_GREEN_OFFSET = 21; + private static final int INSIDE_STROKE_BLUE_OFFSET = 19; + private static final int INSIDE_STROKE_ALPHA = 255; + + private Color backgroundColor = ComponentConstants.STANDARD_BACKGROUND_COLOR; + private Rectangle rectangle = new Rectangle(); + private boolean fill = true; + + @Override + public Dimension render(Graphics2D graphics) + { + Color outsideStrokeColor = new Color( + Math.max(0, backgroundColor.getRed() - OUTSIDE_STROKE_RED_OFFSET), + Math.max(0, backgroundColor.getGreen() - OUTSIDE_STROKE_GREEN_OFFSET), + Math.max(0, backgroundColor.getBlue() - OUTSIDE_STROKE_BLUE_OFFSET), + OUTSIDE_STROKE_ALPHA + ); + + Color insideStrokeColor = new Color( + Math.min(255, backgroundColor.getRed() + INSIDE_STROKE_RED_OFFSET), + Math.min(255, backgroundColor.getGreen() + INSIDE_STROKE_GREEN_OFFSET), + Math.min(255, backgroundColor.getBlue() + INSIDE_STROKE_BLUE_OFFSET), + INSIDE_STROKE_ALPHA + ); + + // Render background + if (fill) + { + graphics.setColor(backgroundColor); + graphics.fill(rectangle); + } + + // Render outside stroke + final Rectangle outsideStroke = new Rectangle(); + outsideStroke.setLocation(rectangle.x, rectangle.y); + outsideStroke.setSize(rectangle.width - BORDER_OFFSET / 2, rectangle.height - BORDER_OFFSET / 2); + graphics.setColor(outsideStrokeColor); + graphics.draw(outsideStroke); + + // Render inside stroke + final Rectangle insideStroke = new Rectangle(); + insideStroke.setLocation(rectangle.x + BORDER_OFFSET / 2, rectangle.y + BORDER_OFFSET / 2); + insideStroke.setSize(rectangle.width - BORDER_OFFSET - BORDER_OFFSET / 2, + rectangle.height - BORDER_OFFSET - BORDER_OFFSET / 2); + graphics.setColor(insideStrokeColor); + graphics.draw(insideStroke); + + return new Dimension(rectangle.getSize()); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/LayoutableRenderableEntity.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/LayoutableRenderableEntity.java index 7a736686d0..6858fbab8c 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/LayoutableRenderableEntity.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/LayoutableRenderableEntity.java @@ -1,37 +1,39 @@ -/* - * Copyright (c) 2018, Tomas Slusny - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.ui.overlay.components; - -import java.awt.Dimension; -import java.awt.Point; -import java.awt.Rectangle; -import net.runelite.client.ui.overlay.RenderableEntity; - -public interface LayoutableRenderableEntity extends RenderableEntity -{ - Rectangle getBounds(); - void setPreferredLocation(Point position); - void setPreferredSize(Dimension dimension); -} +/* + * Copyright (c) 2018, Tomas Slusny + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.ui.overlay.components; + +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Rectangle; +import net.runelite.client.ui.overlay.RenderableEntity; + +public interface LayoutableRenderableEntity extends RenderableEntity +{ + Rectangle getBounds(); + + void setPreferredLocation(Point position); + + void setPreferredSize(Dimension dimension); +} diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/PanelComponent.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/PanelComponent.java index a792dbda14..3eda960450 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/PanelComponent.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/PanelComponent.java @@ -61,10 +61,10 @@ public class PanelComponent implements LayoutableRenderableEntity @Setter private Rectangle border = new Rectangle( - ComponentConstants.STANDARD_BORDER, - ComponentConstants.STANDARD_BORDER, - ComponentConstants.STANDARD_BORDER, - ComponentConstants.STANDARD_BORDER); + ComponentConstants.STANDARD_BORDER, + ComponentConstants.STANDARD_BORDER, + ComponentConstants.STANDARD_BORDER, + ComponentConstants.STANDARD_BORDER); @Setter private Point gap = new Point(0, 0); @@ -81,8 +81,8 @@ public class PanelComponent implements LayoutableRenderableEntity // Calculate panel dimension final Dimension dimension = new Dimension( - border.x + childDimensions.width + border.width, - border.y + childDimensions.height + border.height); + border.x + childDimensions.width + border.width, + border.y + childDimensions.height + border.height); // Render background if (backgroundColor != null) @@ -103,15 +103,15 @@ public class PanelComponent implements LayoutableRenderableEntity // Create child preferred size final Dimension childPreferredSize = new Dimension( - preferredSize.width - border.x - border.width, - preferredSize.height - border.y - border.height); + preferredSize.width - border.x - border.width, + preferredSize.height - border.y - border.height); // Calculate max width/height for infoboxes int totalHeight = 0; int totalWidth = 0; // Render all children - for (int i = 0; i < children.size(); i ++) + for (int i = 0; i < children.size(); i++) { final LayoutableRenderableEntity child = children.get(i); child.setPreferredLocation(new Point(x, y)); @@ -136,7 +136,7 @@ public class PanelComponent implements LayoutableRenderableEntity totalWidth = Math.max(totalWidth, width); totalHeight = Math.max(totalHeight, height); - if (wrapping > 0 && i < children.size() - 1 && (i + 1) % wrapping == 0) + if (wrapping > 0 && i < children.size() - 1 && (i + 1) % wrapping == 0) { switch (orientation) { diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/TooltipComponent.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/TooltipComponent.java index c7c5381b86..b81ede1f43 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/TooltipComponent.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/TooltipComponent.java @@ -1,220 +1,220 @@ -/* - * Copyright (c) 2016-2017, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.ui.overlay.components; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.FontMetrics; -import java.awt.Graphics2D; -import java.awt.Point; -import java.awt.Rectangle; -import java.util.regex.Pattern; -import lombok.Setter; -import net.runelite.api.IndexedSprite; -import net.runelite.client.ui.overlay.RenderableEntity; - -@Setter -public class TooltipComponent implements RenderableEntity -{ - private static final Pattern BR = Pattern.compile("
"); - private static final int OFFSET = 4; - private static final int MOD_ICON_WIDTH = 13; // they are generally 13px wide - - private String text; - private Color backgroundColor = ComponentConstants.STANDARD_BACKGROUND_COLOR; - private Point position = new Point(); - private IndexedSprite[] modIcons; - - @Override - public Dimension render(Graphics2D graphics) - { - // Tooltip size - final FontMetrics metrics = graphics.getFontMetrics(); - final int textDescent = metrics.getDescent(); - final int textHeight = metrics.getHeight(); - int tooltipWidth = 0; - int tooltipHeight = 0; - String[] lines = BR.split(text); - - // Calculate tooltip size - for (String line : lines) - { - int textWidth = calculateTextWidth(metrics, line); - - if (textWidth > tooltipWidth) - { - tooltipWidth = textWidth; - } - - tooltipHeight += textHeight; - } - - // Tooltip position - int x = position.x; - int y = position.y; - - // Render tooltip - background - final Rectangle tooltipBackground = new Rectangle(x, y, - tooltipWidth + OFFSET * 2, tooltipHeight + OFFSET * 2); - final BackgroundComponent backgroundComponent = new BackgroundComponent(); - backgroundComponent.setBackgroundColor(backgroundColor); - backgroundComponent.setRectangle(tooltipBackground); - backgroundComponent.render(graphics); - graphics.setColor(Color.WHITE); - - // Render tooltip - text - line by line - int textX = x + OFFSET; - int textY = y + OFFSET; - int lineX; - Color nextColor = Color.WHITE; - for (int i = 0; i < lines.length; i++) - { - lineX = textX; - final String line = lines[i]; - char[] chars = line.toCharArray(); - - int begin = 0; - for (int j = 0; j < chars.length; j++) - { - if (chars[j] == '<') - { - TextComponent textComponent = new TextComponent(); - textComponent.setColor(nextColor); - String text = line.substring(begin, j); - textComponent.setText(text); - textComponent.setPosition(new Point(lineX, textY + (i + 1) * textHeight - textDescent)); - textComponent.render(graphics); - - lineX += metrics.stringWidth(text); - - begin = j; - } - else if (chars[j] == '>') - { - String subLine = line.substring(begin + 1, j); - - if (subLine.startsWith("col=")) - { - String argument = subLine.substring(4); - nextColor = Color.decode("#" + argument); - } - else if (subLine.equals("/col")) - { - nextColor = Color.WHITE; - } - else if (subLine.startsWith("img=")) - { - if (modIcons != null) - { - String argument = subLine.substring(4); - int iconId = Integer.parseInt(argument); - IndexedSprite modIcon = modIcons[iconId]; - renderModIcon(graphics, lineX, textY + i * textHeight - textDescent, modIcon); - lineX += modIcon.getWidth(); - } - } - else - { - TextComponent textComponent = new TextComponent(); - textComponent.setColor(nextColor); - String text = line.substring(begin, j + 1); - textComponent.setText(text); - textComponent.setPosition(new Point(lineX, textY + (i + 1) * textHeight - textDescent)); - textComponent.render(graphics); - - lineX += metrics.stringWidth(text); - } - - begin = j + 1; - } - } - - // Draw trailing text (after last tag) - final TextComponent textComponent = new TextComponent(); - textComponent.setColor(nextColor); - textComponent.setText(line.substring(begin, line.length())); - textComponent.setPosition(new Point(lineX, textY + (i + 1) * textHeight - textDescent)); - textComponent.render(graphics); - } - - return new Dimension(tooltipWidth + OFFSET * 2, tooltipHeight + OFFSET * 2); - } - - private static int calculateTextWidth(FontMetrics metrics, String line) - { - char[] chars = line.toCharArray(); - int textWidth = 0; - - int begin = 0; - for (int j = 0; j < chars.length; j++) - { - if (chars[j] == '<') - { - textWidth += metrics.stringWidth(line.substring(begin, j)); - - begin = j; - } - else if (chars[j] == '>') - { - String subLine = line.substring(begin + 1, j); - - if (subLine.startsWith("img=")) - { - textWidth += MOD_ICON_WIDTH; - } - else if (!subLine.startsWith("col=") && !subLine.startsWith("/col")) - { - textWidth += metrics.stringWidth(line.substring(begin, j + 1)); - } - - begin = j + 1; - } - } - - // Include trailing text (after last tag) - textWidth += metrics.stringWidth(line.substring(begin, line.length())); - - return textWidth; - } - - private void renderModIcon(Graphics2D graphics, int x, int y, IndexedSprite modIcon) - { - int sourceOffset = 0; - - for (int y2 = 0; y2 < modIcon.getHeight(); y2++) - { - for (int x2 = 0; x2 < modIcon.getWidth(); x2++) - { - int index = modIcon.getPixels()[sourceOffset++] & 0xff; - - if (index != 0) - { - graphics.setColor(new Color(modIcon.getPalette()[index])); - graphics.drawLine(x + x2, y + y2, x + x2, y + y2); - } - } - } - } -} +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.ui.overlay.components; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Rectangle; +import java.util.regex.Pattern; +import lombok.Setter; +import net.runelite.api.IndexedSprite; +import net.runelite.client.ui.overlay.RenderableEntity; + +@Setter +public class TooltipComponent implements RenderableEntity +{ + private static final Pattern BR = Pattern.compile("
"); + private static final int OFFSET = 4; + private static final int MOD_ICON_WIDTH = 13; // they are generally 13px wide + + private String text; + private Color backgroundColor = ComponentConstants.STANDARD_BACKGROUND_COLOR; + private Point position = new Point(); + private IndexedSprite[] modIcons; + + @Override + public Dimension render(Graphics2D graphics) + { + // Tooltip size + final FontMetrics metrics = graphics.getFontMetrics(); + final int textDescent = metrics.getDescent(); + final int textHeight = metrics.getHeight(); + int tooltipWidth = 0; + int tooltipHeight = 0; + String[] lines = BR.split(text); + + // Calculate tooltip size + for (String line : lines) + { + int textWidth = calculateTextWidth(metrics, line); + + if (textWidth > tooltipWidth) + { + tooltipWidth = textWidth; + } + + tooltipHeight += textHeight; + } + + // Tooltip position + int x = position.x; + int y = position.y; + + // Render tooltip - background + final Rectangle tooltipBackground = new Rectangle(x, y, + tooltipWidth + OFFSET * 2, tooltipHeight + OFFSET * 2); + final BackgroundComponent backgroundComponent = new BackgroundComponent(); + backgroundComponent.setBackgroundColor(backgroundColor); + backgroundComponent.setRectangle(tooltipBackground); + backgroundComponent.render(graphics); + graphics.setColor(Color.WHITE); + + // Render tooltip - text - line by line + int textX = x + OFFSET; + int textY = y + OFFSET; + int lineX; + Color nextColor = Color.WHITE; + for (int i = 0; i < lines.length; i++) + { + lineX = textX; + final String line = lines[i]; + char[] chars = line.toCharArray(); + + int begin = 0; + for (int j = 0; j < chars.length; j++) + { + if (chars[j] == '<') + { + TextComponent textComponent = new TextComponent(); + textComponent.setColor(nextColor); + String text = line.substring(begin, j); + textComponent.setText(text); + textComponent.setPosition(new Point(lineX, textY + (i + 1) * textHeight - textDescent)); + textComponent.render(graphics); + + lineX += metrics.stringWidth(text); + + begin = j; + } + else if (chars[j] == '>') + { + String subLine = line.substring(begin + 1, j); + + if (subLine.startsWith("col=")) + { + String argument = subLine.substring(4); + nextColor = Color.decode("#" + argument); + } + else if (subLine.equals("/col")) + { + nextColor = Color.WHITE; + } + else if (subLine.startsWith("img=")) + { + if (modIcons != null) + { + String argument = subLine.substring(4); + int iconId = Integer.parseInt(argument); + IndexedSprite modIcon = modIcons[iconId]; + renderModIcon(graphics, lineX, textY + i * textHeight - textDescent, modIcon); + lineX += modIcon.getWidth(); + } + } + else + { + TextComponent textComponent = new TextComponent(); + textComponent.setColor(nextColor); + String text = line.substring(begin, j + 1); + textComponent.setText(text); + textComponent.setPosition(new Point(lineX, textY + (i + 1) * textHeight - textDescent)); + textComponent.render(graphics); + + lineX += metrics.stringWidth(text); + } + + begin = j + 1; + } + } + + // Draw trailing text (after last tag) + final TextComponent textComponent = new TextComponent(); + textComponent.setColor(nextColor); + textComponent.setText(line.substring(begin)); + textComponent.setPosition(new Point(lineX, textY + (i + 1) * textHeight - textDescent)); + textComponent.render(graphics); + } + + return new Dimension(tooltipWidth + OFFSET * 2, tooltipHeight + OFFSET * 2); + } + + private static int calculateTextWidth(FontMetrics metrics, String line) + { + char[] chars = line.toCharArray(); + int textWidth = 0; + + int begin = 0; + for (int j = 0; j < chars.length; j++) + { + if (chars[j] == '<') + { + textWidth += metrics.stringWidth(line.substring(begin, j)); + + begin = j; + } + else if (chars[j] == '>') + { + String subLine = line.substring(begin + 1, j); + + if (subLine.startsWith("img=")) + { + textWidth += MOD_ICON_WIDTH; + } + else if (!subLine.startsWith("col=") && !subLine.startsWith("/col")) + { + textWidth += metrics.stringWidth(line.substring(begin, j + 1)); + } + + begin = j + 1; + } + } + + // Include trailing text (after last tag) + textWidth += metrics.stringWidth(line.substring(begin)); + + return textWidth; + } + + private void renderModIcon(Graphics2D graphics, int x, int y, IndexedSprite modIcon) + { + int sourceOffset = 0; + + for (int y2 = 0; y2 < modIcon.getHeight(); y2++) + { + for (int x2 = 0; x2 < modIcon.getWidth(); x2++) + { + int index = modIcon.getPixels()[sourceOffset++] & 0xff; + + if (index != 0) + { + graphics.setColor(new Color(modIcon.getPalette()[index])); + graphics.drawLine(x + x2, y + y2, x + x2, y + y2); + } + } + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxManager.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxManager.java index 4fd1c1ca11..fc85fce6d6 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxManager.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxManager.java @@ -1,166 +1,166 @@ -/* - * Copyright (c) 2017, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.ui.overlay.infobox; - -import com.google.common.base.Preconditions; -import com.google.common.collect.ComparisonChain; -import java.awt.Graphics; -import java.awt.Image; -import java.awt.image.BufferedImage; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.function.Predicate; -import javax.inject.Inject; -import javax.inject.Singleton; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.events.ConfigChanged; -import net.runelite.client.config.RuneLiteConfig; -import net.runelite.client.eventbus.Subscribe; -import net.runelite.client.plugins.PluginDescriptor; - -@Singleton -@Slf4j -public class InfoBoxManager -{ - private final List infoBoxes = new ArrayList<>(); - private final RuneLiteConfig runeLiteConfig; - - @Inject - private InfoBoxManager(final RuneLiteConfig runeLiteConfig) - { - this.runeLiteConfig = runeLiteConfig; - } - - @Subscribe - public void onConfigChanged(ConfigChanged event) - { - if (event.getGroup().equals("runelite") && event.getKey().equals("infoBoxSize")) - { - infoBoxes.forEach(this::updateInfoBoxImage); - } - } - - public void addInfoBox(InfoBox infoBox) - { - Preconditions.checkNotNull(infoBox); - log.debug("Adding InfoBox {}", infoBox); - - updateInfoBoxImage(infoBox); - infoBoxes.add(infoBox); - refreshInfoBoxes(); - } - - public void removeInfoBox(InfoBox infoBox) - { - if (infoBoxes.remove(infoBox)) - { - log.debug("Removed InfoBox {}", infoBox); - refreshInfoBoxes(); - } - } - - public void removeIf(Predicate filter) - { - if (infoBoxes.removeIf(filter)) - { - log.debug("Removed InfoBoxes for filter {}", filter); - refreshInfoBoxes(); - } - } - - public List getInfoBoxes() - { - return Collections.unmodifiableList(infoBoxes); - } - - public void cull() - { - boolean culled = false; - for (Iterator it = infoBoxes.iterator(); it.hasNext();) - { - InfoBox box = it.next(); - - if (box.cull()) - { - log.debug("Culling InfoBox {}", box); - it.remove(); - culled = true; - } - } - - if (culled) - { - refreshInfoBoxes(); - } - } - - private void updateInfoBoxImage(final InfoBox infoBox) - { - if (infoBox.getImage() == null) - { - return; - } - - // Set scaled InfoBox image - final Image image = infoBox.getImage(); - Image resultImage = image; - final double width = image.getWidth(null); - final double height = image.getHeight(null); - final double size = Math.max(2, runeLiteConfig.infoBoxSize()); // Limit size to 2 as that is minimum size not causing breakage - - if (size < width || size < height) - { - final double scalex = size / width; - final double scaley = size / height; - - if (scalex == 1 && scaley == 1) - { - return; - } - - final double scale = Math.min(scalex, scaley); - final int newWidth = (int) (width * scale); - final int newHeight = (int) (height * scale); - final BufferedImage scaledImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB); - final Graphics g = scaledImage.createGraphics(); - g.drawImage(image, 0, 0, newWidth, newHeight, null); - g.dispose(); - resultImage = scaledImage; - } - - infoBox.setScaledImage(resultImage); - } - - private void refreshInfoBoxes() - { - infoBoxes.sort((b1, b2) -> ComparisonChain - .start() - .compare(b1.getPriority(), b2.getPriority()) - .compare(b1.getPlugin().getClass().getAnnotation(PluginDescriptor.class).name(), b2.getPlugin().getClass().getAnnotation(PluginDescriptor.class).name()) - .result()); - } -} +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.ui.overlay.infobox; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ComparisonChain; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.image.BufferedImage; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.function.Predicate; +import javax.inject.Inject; +import javax.inject.Singleton; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.events.ConfigChanged; +import net.runelite.client.config.RuneLiteConfig; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.plugins.PluginDescriptor; + +@Singleton +@Slf4j +public class InfoBoxManager +{ + private final List infoBoxes = new ArrayList<>(); + private final RuneLiteConfig runeLiteConfig; + + @Inject + private InfoBoxManager(final RuneLiteConfig runeLiteConfig) + { + this.runeLiteConfig = runeLiteConfig; + } + + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + if (event.getGroup().equals("runelite") && event.getKey().equals("infoBoxSize")) + { + infoBoxes.forEach(this::updateInfoBoxImage); + } + } + + public void addInfoBox(InfoBox infoBox) + { + Preconditions.checkNotNull(infoBox); + log.debug("Adding InfoBox {}", infoBox); + + updateInfoBoxImage(infoBox); + infoBoxes.add(infoBox); + refreshInfoBoxes(); + } + + public void removeInfoBox(InfoBox infoBox) + { + if (infoBoxes.remove(infoBox)) + { + log.debug("Removed InfoBox {}", infoBox); + refreshInfoBoxes(); + } + } + + public void removeIf(Predicate filter) + { + if (infoBoxes.removeIf(filter)) + { + log.debug("Removed InfoBoxes for filter {}", filter); + refreshInfoBoxes(); + } + } + + public List getInfoBoxes() + { + return Collections.unmodifiableList(infoBoxes); + } + + public void cull() + { + boolean culled = false; + for (Iterator it = infoBoxes.iterator(); it.hasNext(); ) + { + InfoBox box = it.next(); + + if (box.cull()) + { + log.debug("Culling InfoBox {}", box); + it.remove(); + culled = true; + } + } + + if (culled) + { + refreshInfoBoxes(); + } + } + + private void updateInfoBoxImage(final InfoBox infoBox) + { + if (infoBox.getImage() == null) + { + return; + } + + // Set scaled InfoBox image + final Image image = infoBox.getImage(); + Image resultImage = image; + final double width = image.getWidth(null); + final double height = image.getHeight(null); + final double size = Math.max(2, runeLiteConfig.infoBoxSize()); // Limit size to 2 as that is minimum size not causing breakage + + if (size < width || size < height) + { + final double scalex = size / width; + final double scaley = size / height; + + if (scalex == 1 && scaley == 1) + { + return; + } + + final double scale = Math.min(scalex, scaley); + final int newWidth = (int) (width * scale); + final int newHeight = (int) (height * scale); + final BufferedImage scaledImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB); + final Graphics g = scaledImage.createGraphics(); + g.drawImage(image, 0, 0, newWidth, newHeight, null); + g.dispose(); + resultImage = scaledImage; + } + + infoBox.setScaledImage(resultImage); + } + + private void refreshInfoBoxes() + { + infoBoxes.sort((b1, b2) -> ComparisonChain + .start() + .compare(b1.getPriority(), b2.getPriority()) + .compare(b1.getPlugin().getClass().getAnnotation(PluginDescriptor.class).name(), b2.getPlugin().getClass().getAnnotation(PluginDescriptor.class).name()) + .result()); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/worldmap/WorldMapOverlay.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/worldmap/WorldMapOverlay.java index 6b5b7474a6..2faa4e0008 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/worldmap/WorldMapOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/worldmap/WorldMapOverlay.java @@ -1,311 +1,312 @@ -/* - * Copyright (c) 2018, Morgan Lewis - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.ui.overlay.worldmap; - -import java.awt.Dimension; -import java.awt.FontMetrics; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.geom.Area; -import java.awt.image.BufferedImage; -import java.util.List; -import javax.inject.Inject; -import javax.inject.Singleton; -import net.runelite.api.Client; -import net.runelite.api.Point; -import net.runelite.api.RenderOverview; -import net.runelite.api.coords.WorldPoint; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.client.input.MouseManager; -import net.runelite.client.ui.FontManager; -import net.runelite.client.ui.JagexColors; -import net.runelite.client.ui.overlay.Overlay; -import net.runelite.client.ui.overlay.OverlayLayer; -import net.runelite.client.ui.overlay.OverlayPosition; -import net.runelite.client.ui.overlay.OverlayPriority; - -@Singleton -public class WorldMapOverlay extends Overlay -{ - private static final int TOOLTIP_OFFSET_HEIGHT = 25; - private static final int TOOLTIP_OFFSET_WIDTH = 5; - private static final int TOOLTIP_PADDING_HEIGHT = 1; - private static final int TOOLTIP_PADDING_WIDTH = 2; - - private final WorldMapPointManager worldMapPointManager; - private final Client client; - - @Inject - private WorldMapOverlay( - Client client, - WorldMapPointManager worldMapPointManager, - MouseManager mouseManager, - WorldMapOverlayMouseListener worldMapOverlayMouseListener) - { - this.client = client; - this.worldMapPointManager = worldMapPointManager; - setPosition(OverlayPosition.DYNAMIC); - setPriority(OverlayPriority.HIGHEST); - setLayer(OverlayLayer.ABOVE_MAP); - mouseManager.registerMouseListener(worldMapOverlayMouseListener); - } - - @Override - public Dimension render(Graphics2D graphics) - { - final List points = worldMapPointManager.getWorldMapPoints(); - - if (points.isEmpty()) - { - return null; - } - - Widget widget = client.getWidget(WidgetInfo.WORLD_MAP_VIEW); - if (widget == null) - { - return null; - } - - final Rectangle worldMapRectangle = widget.getBounds(); - final Area mapViewArea = getWorldMapClipArea(worldMapRectangle); - final Rectangle canvasBounds = client.getCanvas().getBounds(); - // in fixed, the bounds are offset by the size of the black borders outside the canvas - canvasBounds.setLocation(0, 0); - final Area canvasViewArea = getWorldMapClipArea(canvasBounds); - Area currentClip = null; - - WorldMapPoint tooltipPoint = null; - - for (WorldMapPoint worldPoint : points) - { - BufferedImage image = worldPoint.getImage(); - WorldPoint point = worldPoint.getWorldPoint(); - - if (image != null && point != null) - { - Point drawPoint = mapWorldPointToGraphicsPoint(point); - - if (drawPoint == null) - { - worldPoint.setClickbox(null); - continue; - } - - if (worldPoint.isSnapToEdge() && canvasViewArea != currentClip) - { - graphics.setClip(canvasViewArea); - currentClip = canvasViewArea; - } - else if (!worldPoint.isSnapToEdge() && mapViewArea != currentClip) - { - graphics.setClip(mapViewArea); - currentClip = mapViewArea; - } - - if (worldPoint.isSnapToEdge()) - { - if (worldMapRectangle.contains(drawPoint.getX(), drawPoint.getY())) - { - if (worldPoint.isCurrentlyEdgeSnapped()) - { - worldPoint.setCurrentlyEdgeSnapped(false); - worldPoint.onEdgeUnsnap(); - } - } - else - { - drawPoint = clipToRectangle(drawPoint, worldMapRectangle); - if (!worldPoint.isCurrentlyEdgeSnapped()) - { - worldPoint.setCurrentlyEdgeSnapped(true); - worldPoint.onEdgeSnap(); - } - } - } - - int drawX = drawPoint.getX(); - int drawY = drawPoint.getY(); - - if (worldPoint.getImagePoint() == null) - { - drawX -= image.getWidth() / 2; - drawY -= image.getHeight() / 2; - } - else - { - drawX -= worldPoint.getImagePoint().getX(); - drawY -= worldPoint.getImagePoint().getY(); - } - - graphics.drawImage(image, drawX, drawY, null); - Rectangle clickbox = new Rectangle(drawX, drawY, image.getWidth(), image.getHeight()); - worldPoint.setClickbox(clickbox); - - if (worldPoint.isTooltipVisible()) - { - tooltipPoint = worldPoint; - } - } - } - - if (tooltipPoint != null) - { - drawTooltip(graphics, tooltipPoint); - } - - return null; - } - - /** - * Get the screen coordinates for a WorldPoint on the world map - * @param worldPoint WorldPoint to get screen coordinates of - * @return Point of screen coordinates of the center of the world point - */ - public Point mapWorldPointToGraphicsPoint(WorldPoint worldPoint) - { - RenderOverview ro = client.getRenderOverview(); - - if (!ro.getWorldMapData().surfaceContainsPosition(worldPoint.getX(), worldPoint.getY())) - { - return null; - } - - Float pixelsPerTile = ro.getWorldMapZoom(); - - Widget map = client.getWidget(WidgetInfo.WORLD_MAP_VIEW); - if (map != null) - { - Rectangle worldMapRect = map.getBounds(); - - int widthInTiles = (int) Math.ceil(worldMapRect.getWidth() / pixelsPerTile); - int heightInTiles = (int) Math.ceil(worldMapRect.getHeight() / pixelsPerTile); - - Point worldMapPosition = ro.getWorldMapPosition(); - - //Offset in tiles from anchor sides - int yTileMax = worldMapPosition.getY() - heightInTiles / 2; - int yTileOffset = (yTileMax - worldPoint.getY() - 1) * -1; - int xTileOffset = worldPoint.getX() + widthInTiles / 2 - worldMapPosition.getX(); - - int xGraphDiff = ((int) (xTileOffset * pixelsPerTile)); - int yGraphDiff = (int) (yTileOffset * pixelsPerTile); - - //Center on tile. - yGraphDiff -= pixelsPerTile - Math.ceil(pixelsPerTile / 2); - xGraphDiff += pixelsPerTile - Math.ceil(pixelsPerTile / 2); - - yGraphDiff = worldMapRect.height - yGraphDiff; - yGraphDiff += (int) worldMapRect.getY(); - xGraphDiff += (int) worldMapRect.getX(); - - return new Point(xGraphDiff, yGraphDiff); - } - return null; - } - - /** - * Gets a clip area which excludes the area of widgets which overlay the world map. - * - * @param baseRectangle The base area to clip from - * @return An {@link Area} representing baseRectangle, with the area - * of visible widgets overlaying the world map clipped from it. - */ - private Area getWorldMapClipArea(Rectangle baseRectangle) - { - final Widget overview = client.getWidget(WidgetInfo.WORLD_MAP_OVERVIEW_MAP); - final Widget surfaceSelector = client.getWidget(WidgetInfo.WORLD_MAP_SURFACE_SELECTOR); - - Area clipArea = new Area(baseRectangle); - - if (overview != null && !overview.isHidden()) - { - clipArea.subtract(new Area(overview.getBounds())); - } - - if (surfaceSelector != null && !surfaceSelector.isHidden()) - { - clipArea.subtract(new Area(surfaceSelector.getBounds())); - } - - return clipArea; - } - - private void drawTooltip(Graphics2D graphics, WorldMapPoint worldPoint) - { - String tooltip = worldPoint.getTooltip(); - Point drawPoint = mapWorldPointToGraphicsPoint(worldPoint.getWorldPoint()); - if (tooltip == null || tooltip.length() <= 0 || drawPoint == null) - { - return; - } - - drawPoint = new Point(drawPoint.getX() + TOOLTIP_OFFSET_WIDTH, drawPoint.getY() + TOOLTIP_OFFSET_HEIGHT); - - graphics.setClip(client.getCanvas().getBounds()); - graphics.setColor(JagexColors.TOOLTIP_BACKGROUND); - graphics.setFont(FontManager.getRunescapeFont()); - FontMetrics fm = graphics.getFontMetrics(); - int width = fm.stringWidth(tooltip); - int height = fm.getHeight(); - - Rectangle tooltipRect = new Rectangle(drawPoint.getX() - TOOLTIP_PADDING_WIDTH, drawPoint.getY() - TOOLTIP_PADDING_HEIGHT, width + TOOLTIP_PADDING_WIDTH * 2, height + TOOLTIP_PADDING_HEIGHT * 2); - graphics.fillRect((int) tooltipRect.getX(), (int) tooltipRect.getY(), (int) tooltipRect.getWidth(), (int) tooltipRect.getHeight()); - - graphics.setColor(JagexColors.TOOLTIP_BORDER); - graphics.drawRect((int) tooltipRect.getX(), (int) tooltipRect.getY(), (int) tooltipRect.getWidth(), (int) tooltipRect.getHeight()); - graphics.setColor(JagexColors.TOOLTIP_TEXT); - graphics.drawString(tooltip, drawPoint.getX(), drawPoint.getY() + height); - } - - private Point clipToRectangle(Point drawPoint, Rectangle mapDisplayRectangle) - { - int clippedX = drawPoint.getX(); - - if (drawPoint.getX() < mapDisplayRectangle.getX()) - { - clippedX = (int) mapDisplayRectangle.getX(); - } - - if (drawPoint.getX() > mapDisplayRectangle.getX() + mapDisplayRectangle.getWidth()) - { - clippedX = (int) (mapDisplayRectangle.getX() + mapDisplayRectangle.getWidth()); - } - - int clippedY = drawPoint.getY(); - - if (drawPoint.getY() < mapDisplayRectangle.getY()) - { - clippedY = (int) mapDisplayRectangle.getY(); - } - - if (drawPoint.getY() > mapDisplayRectangle.getY() + mapDisplayRectangle.getHeight()) - { - clippedY = (int) (mapDisplayRectangle.getY() + mapDisplayRectangle.getHeight()); - } - - return new Point(clippedX, clippedY); - } -} +/* + * Copyright (c) 2018, Morgan Lewis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.ui.overlay.worldmap; + +import java.awt.Dimension; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.geom.Area; +import java.awt.image.BufferedImage; +import java.util.List; +import javax.inject.Inject; +import javax.inject.Singleton; +import net.runelite.api.Client; +import net.runelite.api.Point; +import net.runelite.api.RenderOverview; +import net.runelite.api.coords.WorldPoint; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.input.MouseManager; +import net.runelite.client.ui.FontManager; +import net.runelite.client.ui.JagexColors; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayPriority; + +@Singleton +public class WorldMapOverlay extends Overlay +{ + private static final int TOOLTIP_OFFSET_HEIGHT = 25; + private static final int TOOLTIP_OFFSET_WIDTH = 5; + private static final int TOOLTIP_PADDING_HEIGHT = 1; + private static final int TOOLTIP_PADDING_WIDTH = 2; + + private final WorldMapPointManager worldMapPointManager; + private final Client client; + + @Inject + private WorldMapOverlay( + Client client, + WorldMapPointManager worldMapPointManager, + MouseManager mouseManager, + WorldMapOverlayMouseListener worldMapOverlayMouseListener) + { + this.client = client; + this.worldMapPointManager = worldMapPointManager; + setPosition(OverlayPosition.DYNAMIC); + setPriority(OverlayPriority.HIGHEST); + setLayer(OverlayLayer.ABOVE_MAP); + mouseManager.registerMouseListener(worldMapOverlayMouseListener); + } + + @Override + public Dimension render(Graphics2D graphics) + { + final List points = worldMapPointManager.getWorldMapPoints(); + + if (points.isEmpty()) + { + return null; + } + + Widget widget = client.getWidget(WidgetInfo.WORLD_MAP_VIEW); + if (widget == null) + { + return null; + } + + final Rectangle worldMapRectangle = widget.getBounds(); + final Area mapViewArea = getWorldMapClipArea(worldMapRectangle); + final Rectangle canvasBounds = client.getCanvas().getBounds(); + // in fixed, the bounds are offset by the size of the black borders outside the canvas + canvasBounds.setLocation(0, 0); + final Area canvasViewArea = getWorldMapClipArea(canvasBounds); + Area currentClip = null; + + WorldMapPoint tooltipPoint = null; + + for (WorldMapPoint worldPoint : points) + { + BufferedImage image = worldPoint.getImage(); + WorldPoint point = worldPoint.getWorldPoint(); + + if (image != null && point != null) + { + Point drawPoint = mapWorldPointToGraphicsPoint(point); + + if (drawPoint == null) + { + worldPoint.setClickbox(null); + continue; + } + + if (worldPoint.isSnapToEdge() && canvasViewArea != currentClip) + { + graphics.setClip(canvasViewArea); + currentClip = canvasViewArea; + } + else if (!worldPoint.isSnapToEdge() && mapViewArea != currentClip) + { + graphics.setClip(mapViewArea); + currentClip = mapViewArea; + } + + if (worldPoint.isSnapToEdge()) + { + if (worldMapRectangle.contains(drawPoint.getX(), drawPoint.getY())) + { + if (worldPoint.isCurrentlyEdgeSnapped()) + { + worldPoint.setCurrentlyEdgeSnapped(false); + worldPoint.onEdgeUnsnap(); + } + } + else + { + drawPoint = clipToRectangle(drawPoint, worldMapRectangle); + if (!worldPoint.isCurrentlyEdgeSnapped()) + { + worldPoint.setCurrentlyEdgeSnapped(true); + worldPoint.onEdgeSnap(); + } + } + } + + int drawX = drawPoint.getX(); + int drawY = drawPoint.getY(); + + if (worldPoint.getImagePoint() == null) + { + drawX -= image.getWidth() / 2; + drawY -= image.getHeight() / 2; + } + else + { + drawX -= worldPoint.getImagePoint().getX(); + drawY -= worldPoint.getImagePoint().getY(); + } + + graphics.drawImage(image, drawX, drawY, null); + Rectangle clickbox = new Rectangle(drawX, drawY, image.getWidth(), image.getHeight()); + worldPoint.setClickbox(clickbox); + + if (worldPoint.isTooltipVisible()) + { + tooltipPoint = worldPoint; + } + } + } + + if (tooltipPoint != null) + { + drawTooltip(graphics, tooltipPoint); + } + + return null; + } + + /** + * Get the screen coordinates for a WorldPoint on the world map + * + * @param worldPoint WorldPoint to get screen coordinates of + * @return Point of screen coordinates of the center of the world point + */ + public Point mapWorldPointToGraphicsPoint(WorldPoint worldPoint) + { + RenderOverview ro = client.getRenderOverview(); + + if (!ro.getWorldMapData().surfaceContainsPosition(worldPoint.getX(), worldPoint.getY())) + { + return null; + } + + Float pixelsPerTile = ro.getWorldMapZoom(); + + Widget map = client.getWidget(WidgetInfo.WORLD_MAP_VIEW); + if (map != null) + { + Rectangle worldMapRect = map.getBounds(); + + int widthInTiles = (int) Math.ceil(worldMapRect.getWidth() / pixelsPerTile); + int heightInTiles = (int) Math.ceil(worldMapRect.getHeight() / pixelsPerTile); + + Point worldMapPosition = ro.getWorldMapPosition(); + + //Offset in tiles from anchor sides + int yTileMax = worldMapPosition.getY() - heightInTiles / 2; + int yTileOffset = (yTileMax - worldPoint.getY() - 1) * -1; + int xTileOffset = worldPoint.getX() + widthInTiles / 2 - worldMapPosition.getX(); + + int xGraphDiff = ((int) (xTileOffset * pixelsPerTile)); + int yGraphDiff = (int) (yTileOffset * pixelsPerTile); + + //Center on tile. + yGraphDiff -= pixelsPerTile - Math.ceil(pixelsPerTile / 2); + xGraphDiff += pixelsPerTile - Math.ceil(pixelsPerTile / 2); + + yGraphDiff = worldMapRect.height - yGraphDiff; + yGraphDiff += (int) worldMapRect.getY(); + xGraphDiff += (int) worldMapRect.getX(); + + return new Point(xGraphDiff, yGraphDiff); + } + return null; + } + + /** + * Gets a clip area which excludes the area of widgets which overlay the world map. + * + * @param baseRectangle The base area to clip from + * @return An {@link Area} representing baseRectangle, with the area + * of visible widgets overlaying the world map clipped from it. + */ + private Area getWorldMapClipArea(Rectangle baseRectangle) + { + final Widget overview = client.getWidget(WidgetInfo.WORLD_MAP_OVERVIEW_MAP); + final Widget surfaceSelector = client.getWidget(WidgetInfo.WORLD_MAP_SURFACE_SELECTOR); + + Area clipArea = new Area(baseRectangle); + + if (overview != null && !overview.isHidden()) + { + clipArea.subtract(new Area(overview.getBounds())); + } + + if (surfaceSelector != null && !surfaceSelector.isHidden()) + { + clipArea.subtract(new Area(surfaceSelector.getBounds())); + } + + return clipArea; + } + + private void drawTooltip(Graphics2D graphics, WorldMapPoint worldPoint) + { + String tooltip = worldPoint.getTooltip(); + Point drawPoint = mapWorldPointToGraphicsPoint(worldPoint.getWorldPoint()); + if (tooltip == null || tooltip.length() <= 0 || drawPoint == null) + { + return; + } + + drawPoint = new Point(drawPoint.getX() + TOOLTIP_OFFSET_WIDTH, drawPoint.getY() + TOOLTIP_OFFSET_HEIGHT); + + graphics.setClip(client.getCanvas().getBounds()); + graphics.setColor(JagexColors.TOOLTIP_BACKGROUND); + graphics.setFont(FontManager.getRunescapeFont()); + FontMetrics fm = graphics.getFontMetrics(); + int width = fm.stringWidth(tooltip); + int height = fm.getHeight(); + + Rectangle tooltipRect = new Rectangle(drawPoint.getX() - TOOLTIP_PADDING_WIDTH, drawPoint.getY() - TOOLTIP_PADDING_HEIGHT, width + TOOLTIP_PADDING_WIDTH * 2, height + TOOLTIP_PADDING_HEIGHT * 2); + graphics.fillRect((int) tooltipRect.getX(), (int) tooltipRect.getY(), (int) tooltipRect.getWidth(), (int) tooltipRect.getHeight()); + + graphics.setColor(JagexColors.TOOLTIP_BORDER); + graphics.drawRect((int) tooltipRect.getX(), (int) tooltipRect.getY(), (int) tooltipRect.getWidth(), (int) tooltipRect.getHeight()); + graphics.setColor(JagexColors.TOOLTIP_TEXT); + graphics.drawString(tooltip, drawPoint.getX(), drawPoint.getY() + height); + } + + private Point clipToRectangle(Point drawPoint, Rectangle mapDisplayRectangle) + { + int clippedX = drawPoint.getX(); + + if (drawPoint.getX() < mapDisplayRectangle.getX()) + { + clippedX = (int) mapDisplayRectangle.getX(); + } + + if (drawPoint.getX() > mapDisplayRectangle.getX() + mapDisplayRectangle.getWidth()) + { + clippedX = (int) (mapDisplayRectangle.getX() + mapDisplayRectangle.getWidth()); + } + + int clippedY = drawPoint.getY(); + + if (drawPoint.getY() < mapDisplayRectangle.getY()) + { + clippedY = (int) mapDisplayRectangle.getY(); + } + + if (drawPoint.getY() > mapDisplayRectangle.getY() + mapDisplayRectangle.getHeight()) + { + clippedY = (int) (mapDisplayRectangle.getY() + mapDisplayRectangle.getHeight()); + } + + return new Point(clippedX, clippedY); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/util/ColorUtil.java b/runelite-client/src/main/java/net/runelite/client/util/ColorUtil.java index 5c66d129b3..ec48dba9ff 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/ColorUtil.java +++ b/runelite-client/src/main/java/net/runelite/client/util/ColorUtil.java @@ -1,242 +1,243 @@ -/* - * Copyright (c) 2018, Jordan Atwood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.util; - -import com.google.common.primitives.Ints; -import java.awt.Color; -import java.util.regex.Pattern; -import javax.annotation.Nonnull; - -public class ColorUtil -{ - public static final int MAX_RGB_VALUE = 255; - public static final int MIN_RGB_VALUE = 0; - private static final String OPENING_COLOR_TAG_START = " + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.util; + +import com.google.common.primitives.Ints; +import java.awt.Color; +import java.util.regex.Pattern; +import javax.annotation.Nonnull; + +public class ColorUtil +{ + public static final int MAX_RGB_VALUE = 255; + public static final int MIN_RGB_VALUE = 0; + private static final String OPENING_COLOR_TAG_START = " fillCondition) { @@ -296,8 +296,8 @@ public class ImageUtil * @param image The image to be outlined. * @param color The color to use for the outline. * @param outlineCorners Whether to draw an outline around corners, or only around edges. - * @return The BufferedImage with its edges--and optionally, corners--outlined - * with the given color. + * @return The BufferedImage with its edges--and optionally, corners--outlined + * with the given color. */ public static BufferedImage outlineImage(final BufferedImage image, final Color color, final Boolean outlineCorners) { @@ -312,8 +312,8 @@ public class ImageUtil * @param color The color to use for the outline. * @param fillCondition The predicate to be consumed by {@link #fillImage(BufferedImage, Color, Predicate) fillImage(BufferedImage, Color, Predicate)} * @param outlineCorners Whether to draw an outline around corners, or only around edges. - * @return The BufferedImage with its edges--and optionally, corners--outlined - * with the given color. + * @return The BufferedImage with its edges--and optionally, corners--outlined + * with the given color. */ public static BufferedImage outlineImage(final BufferedImage image, final Color color, final Predicate fillCondition, final Boolean outlineCorners) { @@ -347,7 +347,7 @@ public class ImageUtil * * @param c The class to be referenced for resource path. * @param path The path, relative to the given class. - * @return A {@link BufferedImage} of the loaded image resource from the given path. + * @return A {@link BufferedImage} of the loaded image resource from the given path. */ public static BufferedImage getResourceStreamFromClass(final Class c, final String path) { @@ -369,7 +369,7 @@ public class ImageUtil * * @param image The image which should have its non-transparent pixels filled. * @param color The color with which to fill pixels. - * @return The given image with all non-transparent pixels set to the given color. + * @return The given image with all non-transparent pixels set to the given color. */ public static BufferedImage fillImage(final BufferedImage image, final Color color) { @@ -377,14 +377,14 @@ public class ImageUtil } /** - * Fills pixels of the given image with the given color based on a given fill condition - * predicate. + * Fills pixels of the given image with the given color based on a given fill condition + * predicate. * * @param image The image which should have its non-transparent pixels filled. * @param color The color with which to fill pixels. * @param fillCondition The condition on which to fill pixels with the given color. - * @return The given image with all pixels fulfilling the fill condition predicate - * set to the given color. + * @return The given image with all pixels fulfilling the fill condition predicate + * set to the given color. */ static BufferedImage fillImage(final BufferedImage image, final Color color, final Predicate fillCondition) { @@ -411,7 +411,7 @@ public class ImageUtil * @param image The image to be adjusted. * @param scales An array of scale operations to be performed on the image's color components. * @param offsets An array of offset operations to be performed on the image's color components. - * @return The modified image after applying the given adjustments. + * @return The modified image after applying the given adjustments. */ private static BufferedImage offset(final BufferedImage image, final float[] scales, final float[] offsets) { @@ -421,9 +421,10 @@ public class ImageUtil /** * Converts the buffered image into a sprite image and returns it + * * @param image The image to be converted * @param client Current client instance - * @return The buffered image as a sprite image + * @return The buffered image as a sprite image */ public static SpritePixels getImageSpritePixels(BufferedImage image, Client client) { @@ -455,12 +456,12 @@ public class ImageUtil /** * Converts an image into an {@code IndexedSprite} instance. - * + *

* The passed in image can only have at max 255 different colors. * * @param image The image to be converted * @param client Current client instance - * @return The image as an {@code IndexedSprite} + * @return The image as an {@code IndexedSprite} */ public static IndexedSprite getImageIndexedSprite(BufferedImage image, Client client) { diff --git a/runelite-client/src/main/java/net/runelite/client/util/LinkBrowser.java b/runelite-client/src/main/java/net/runelite/client/util/LinkBrowser.java index 194b1974b2..b5d4ab23f8 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/LinkBrowser.java +++ b/runelite-client/src/main/java/net/runelite/client/util/LinkBrowser.java @@ -1,150 +1,152 @@ -/* - * Copyright (c) 2018, Tomas Slusny - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.util; - -import com.google.common.base.Strings; -import java.awt.Desktop; -import java.awt.Toolkit; -import java.awt.datatransfer.StringSelection; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import javax.inject.Singleton; -import javax.swing.JOptionPane; -import javax.swing.SwingUtilities; -import lombok.extern.slf4j.Slf4j; - -/** - * Utility class used for browser navigation - */ -@Singleton -@Slf4j -public class LinkBrowser -{ - private static boolean shouldAttemptXdg = OSType.getOSType() == OSType.Linux; - - /** - * Tries to navigate to specified URL in browser. In case operation fails, displays message box with message - * and copies link to clipboard to navigate to. - * @param url url to open - * @return true if operation was successful - */ - public static boolean browse(final String url) - { - if (Strings.isNullOrEmpty(url)) - { - return false; - } - - if (attemptDesktopBrowse(url)) - { - log.debug("Opened browser through Desktop#browse to {}", url); - return true; - } - - if (shouldAttemptXdg && attemptXdgOpen(url)) - { - log.debug("Opened browser through xdg-open to {}", url); - return true; - } - - showMessageBox("Unable to open link. Press 'OK' and link will be copied to your clipboard.", url); - return false; - } - - private static boolean attemptXdgOpen(String url) - { - try - { - final Process exec = Runtime.getRuntime().exec(new String[]{"xdg-open", url}); - exec.waitFor(); - - final int ret = exec.exitValue(); - if (ret == 0) - { - return true; - } - - log.warn("xdg-open {} returned with error code {}", url, ret); - return false; - } - catch (IOException ex) - { - // xdg-open not found - shouldAttemptXdg = false; - return false; - } - catch (InterruptedException ex) - { - log.warn("Interrupted while waiting for xdg-open {} to execute", url); - return false; - } - } - - private static boolean attemptDesktopBrowse(String url) - { - if (!Desktop.isDesktopSupported()) - { - return false; - } - - final Desktop desktop = Desktop.getDesktop(); - - if (!desktop.isSupported(Desktop.Action.BROWSE)) - { - return false; - } - - try - { - desktop.browse(new URI(url)); - return true; - } - catch (IOException | URISyntaxException ex) - { - log.warn("Failed to open Desktop#browser {}", url, ex); - return false; - } - } - - /** - * Open swing message box with specified message and copy data to clipboard - * @param message message to show - */ - private static void showMessageBox(final String message, final String data) - { - SwingUtilities.invokeLater(() -> - { - final int result = JOptionPane.showConfirmDialog(null, message, "Message", - JOptionPane.OK_CANCEL_OPTION); - - if (result == JOptionPane.OK_OPTION) - { - final StringSelection stringSelection = new StringSelection(data); - Toolkit.getDefaultToolkit().getSystemClipboard().setContents(stringSelection, null); - } - }); - } -} +/* + * Copyright (c) 2018, Tomas Slusny + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.util; + +import com.google.common.base.Strings; +import java.awt.Desktop; +import java.awt.Toolkit; +import java.awt.datatransfer.StringSelection; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import javax.inject.Singleton; +import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; +import lombok.extern.slf4j.Slf4j; + +/** + * Utility class used for browser navigation + */ +@Singleton +@Slf4j +public class LinkBrowser +{ + private static boolean shouldAttemptXdg = OSType.getOSType() == OSType.Linux; + + /** + * Tries to navigate to specified URL in browser. In case operation fails, displays message box with message + * and copies link to clipboard to navigate to. + * + * @param url url to open + * @return true if operation was successful + */ + public static boolean browse(final String url) + { + if (Strings.isNullOrEmpty(url)) + { + return false; + } + + if (attemptDesktopBrowse(url)) + { + log.debug("Opened browser through Desktop#browse to {}", url); + return true; + } + + if (shouldAttemptXdg && attemptXdgOpen(url)) + { + log.debug("Opened browser through xdg-open to {}", url); + return true; + } + + showMessageBox("Unable to open link. Press 'OK' and link will be copied to your clipboard.", url); + return false; + } + + private static boolean attemptXdgOpen(String url) + { + try + { + final Process exec = Runtime.getRuntime().exec(new String[]{"xdg-open", url}); + exec.waitFor(); + + final int ret = exec.exitValue(); + if (ret == 0) + { + return true; + } + + log.warn("xdg-open {} returned with error code {}", url, ret); + return false; + } + catch (IOException ex) + { + // xdg-open not found + shouldAttemptXdg = false; + return false; + } + catch (InterruptedException ex) + { + log.warn("Interrupted while waiting for xdg-open {} to execute", url); + return false; + } + } + + private static boolean attemptDesktopBrowse(String url) + { + if (!Desktop.isDesktopSupported()) + { + return false; + } + + final Desktop desktop = Desktop.getDesktop(); + + if (!desktop.isSupported(Desktop.Action.BROWSE)) + { + return false; + } + + try + { + desktop.browse(new URI(url)); + return true; + } + catch (IOException | URISyntaxException ex) + { + log.warn("Failed to open Desktop#browser {}", url, ex); + return false; + } + } + + /** + * Open swing message box with specified message and copy data to clipboard + * + * @param message message to show + */ + private static void showMessageBox(final String message, final String data) + { + SwingUtilities.invokeLater(() -> + { + final int result = JOptionPane.showConfirmDialog(null, message, "Message", + JOptionPane.OK_CANCEL_OPTION); + + if (result == JOptionPane.OK_OPTION) + { + final StringSelection stringSelection = new StringSelection(data); + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(stringSelection, null); + } + }); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/util/MenuUtil.java b/runelite-client/src/main/java/net/runelite/client/util/MenuUtil.java index 7677c16d2f..e98c3d1dd3 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/MenuUtil.java +++ b/runelite-client/src/main/java/net/runelite/client/util/MenuUtil.java @@ -109,8 +109,8 @@ public class MenuUtil private static MenuEntry findOptionTarget(Stream stream, String option, String target) { Optional maybeEntry = stream.filter(e -> Text.standardize(e.getOption()).equals(option) && - Text.standardize(e.getTarget()).equals(target)) - /* autism */ .findFirst(); + Text.standardize(e.getTarget()).equals(target)) + /* autism */.findFirst(); return maybeEntry.orElse(null); } @@ -118,8 +118,8 @@ public class MenuUtil private static MenuEntry findOptionTargetLenient(Stream stream, String option, String target) { Optional maybeEntry = stream.filter(e -> Text.standardize(e.getOption()).contains(option) && - Text.standardize(e.getTarget()).contains(target)) - /* autism */ .findFirst(); + Text.standardize(e.getTarget()).contains(target)) + /* autism */.findFirst(); return maybeEntry.orElse(null); } diff --git a/runelite-client/src/main/java/net/runelite/client/util/MiscUtils.java b/runelite-client/src/main/java/net/runelite/client/util/MiscUtils.java index 077439ee88..6bd6d09b1c 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/MiscUtils.java +++ b/runelite-client/src/main/java/net/runelite/client/util/MiscUtils.java @@ -1,79 +1,92 @@ -package net.runelite.client.util; - -import net.runelite.api.Client; -import net.runelite.api.Player; -import net.runelite.api.WorldType; -import net.runelite.api.coords.WorldPoint; - -import java.awt.*; - -public class MiscUtils -{ - private static int[] abovePointsX = { 2944, 3392, 3392, 2944 }; - private static int[] abovePointsY = { 3523, 3523, 3971, 3971 }; - private static int[] belowPointsX = { 2944, 2944, 3264, 3264 }; - private static int[] belowPointsY = { 9918, 10360, 10360, 9918 }; - - private static Polygon abovePoly = new Polygon(abovePointsX, abovePointsY, abovePointsX.length); - private static Polygon belowPoly = new Polygon(belowPointsX, belowPointsY, belowPointsX.length); - - //test replacement so private for now - private static boolean inWildy(WorldPoint point) - { - if (point == null) - return false; - - return abovePoly.contains(point.getX(), point.getY()) || belowPoly.contains(point.getX(), point.getY()); - } - - public static int getWildernessLevelFrom(Client client, WorldPoint point) - { - if (client == null) - return 0; - - if (point == null) - return 0; - - int x = point.getX(); - - if (point.getPlane() == 0 && (x < 2940 || x > 3391)) - return 0; - - int y = point.getY(); - //v underground //v above ground - int wildernessLevel = clamp(y > 6400 ? ((y - 9920) / 8) + 1 : ((y - 3520) / 8) + 1, 0, 56); - - if (point.getPlane() > 0) - if (y < 9920) - wildernessLevel = 0; - - if (client.getWorldType().stream().anyMatch(worldType -> worldType == WorldType.PVP || worldType == WorldType.HIGH_RISK)) - { - wildernessLevel += 15; - } - - return Math.max(0, wildernessLevel); - } - - public static int clamp(int val, int min, int max) - { - return Math.max(min, Math.min(max, val)); - } - - public static float clamp(float val, float min, float max) - { - return Math.max(min, Math.min(max, val)); - } - - public static boolean inWilderness(Client client) - { - Player localPlayer = client.getLocalPlayer(); - - if (localPlayer == null) - return false; - - return inWildy(localPlayer.getWorldLocation()); - - //return getWildernessLevelFrom(client, localPlayer.getWorldLocation()) > 0; - } -} +package net.runelite.client.util; + +import java.awt.Polygon; +import net.runelite.api.Client; +import net.runelite.api.Player; +import net.runelite.api.WorldType; +import net.runelite.api.coords.WorldPoint; + +public class MiscUtils +{ + private static int[] abovePointsX = {2944, 3392, 3392, 2944}; + private static int[] abovePointsY = {3523, 3523, 3971, 3971}; + private static int[] belowPointsX = {2944, 2944, 3264, 3264}; + private static int[] belowPointsY = {9918, 10360, 10360, 9918}; + + private static Polygon abovePoly = new Polygon(abovePointsX, abovePointsY, abovePointsX.length); + private static Polygon belowPoly = new Polygon(belowPointsX, belowPointsY, belowPointsX.length); + + //test replacement so private for now + private static boolean inWildy(WorldPoint point) + { + if (point == null) + { + return false; + } + + return abovePoly.contains(point.getX(), point.getY()) || belowPoly.contains(point.getX(), point.getY()); + } + + public static int getWildernessLevelFrom(Client client, WorldPoint point) + { + if (client == null) + { + return 0; + } + + if (point == null) + { + return 0; + } + + int x = point.getX(); + + if (point.getPlane() == 0 && (x < 2940 || x > 3391)) + { + return 0; + } + + int y = point.getY(); + //v underground //v above ground + int wildernessLevel = clamp(y > 6400 ? ((y - 9920) / 8) + 1 : ((y - 3520) / 8) + 1, 0, 56); + + if (point.getPlane() > 0) + { + if (y < 9920) + { + wildernessLevel = 0; + } + } + + if (client.getWorldType().stream().anyMatch(worldType -> worldType == WorldType.PVP || worldType == WorldType.HIGH_RISK)) + { + wildernessLevel += 15; + } + + return Math.max(0, wildernessLevel); + } + + public static int clamp(int val, int min, int max) + { + return Math.max(min, Math.min(max, val)); + } + + public static float clamp(float val, float min, float max) + { + return Math.max(min, Math.min(max, val)); + } + + public static boolean inWilderness(Client client) + { + Player localPlayer = client.getLocalPlayer(); + + if (localPlayer == null) + { + return false; + } + + return inWildy(localPlayer.getWorldLocation()); + + //return getWildernessLevelFrom(client, localPlayer.getWorldLocation()) > 0; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/util/PvPUtil.java b/runelite-client/src/main/java/net/runelite/client/util/PvPUtil.java index c306d45125..3150816a9d 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/PvPUtil.java +++ b/runelite-client/src/main/java/net/runelite/client/util/PvPUtil.java @@ -1,111 +1,113 @@ -/* - * Copyright (c) 2019. PKLite - All Rights Reserved - * Unauthorized modification, distribution, or possession of this source file, via any medium is strictly prohibited. - * Proprietary and confidential. Refer to PKLite License file for more information on - * full terms of this copyright and to determine what constitutes authorized use. - * Written by PKLite(ST0NEWALL, others) , 2019 - * - */ - -package net.runelite.client.util; - -import java.util.Comparator; -import java.util.Objects; -import java.util.TreeMap; -import net.runelite.api.Client; -import net.runelite.api.InventoryID; -import net.runelite.api.Item; -import net.runelite.api.ItemComposition; -import net.runelite.api.Player; -import net.runelite.api.Varbits; -import net.runelite.api.WorldType; -import net.runelite.api.coords.WorldPoint; -import net.runelite.client.game.ItemManager; -import static net.runelite.client.util.StackFormatter.quantityToRSDecimalStack; -import org.apache.commons.lang3.ArrayUtils; - -/** - * - */ -public class PvPUtil -{ - - /** - * Gets the wilderness level based on a world point - * @param point the point in the world to get the wilderness level for - * @return the int representing the wilderness level - */ - public static int getWildernessLevelFrom(WorldPoint point) - { - int x = point.getX(); - int y = point.getY(); - - int underLevel = ((y - 9920) / 8) + 1; - int upperLevel = ((y - 3520) / 8) + 1; - - return y > 6400 ? underLevel : upperLevel; - } - - /** - * Determines if another player is attackable based off of wilderness level and combat levels - * @param client The client of the local player - * @param player the player to determine attackability - * @return returns true if the player is attackable, false otherwise - */ - public static boolean isAttackable(Client client, Player player) - { - int wildernessLevel = 0; - if (!(client.getVar(Varbits.IN_WILDERNESS) == 1 || WorldType.isPvpWorld(client.getWorldType()))) - { - return false; - } - if (WorldType.isPvpWorld(client.getWorldType())) - { - if (client.getVar(Varbits.IN_WILDERNESS) != 1) - { - return Math.abs(client.getLocalPlayer().getCombatLevel() - player.getCombatLevel()) <= 15; - } - wildernessLevel = 15; - } - return Math.abs(client.getLocalPlayer().getCombatLevel() - player.getCombatLevel()) - < (getWildernessLevelFrom(client.getLocalPlayer().getWorldLocation())+ wildernessLevel); - } - - public static int calculateRisk(Client client, ItemManager itemManager) - { - if (client.getItemContainer(InventoryID.EQUIPMENT) == null) - { - return 0; - } - if (client.getItemContainer(InventoryID.INVENTORY).getItems() == null) - { - return 0; - } - Item[] items = ArrayUtils.addAll(Objects.requireNonNull(client.getItemContainer(InventoryID.EQUIPMENT)).getItems(), - Objects.requireNonNull(client.getItemContainer(InventoryID.INVENTORY)).getItems()); - TreeMap priceMap = new TreeMap<>(Comparator.comparingInt(Integer::intValue)); - int wealth = 0; - for (Item i : items) - { - int value = (itemManager.getItemPrice(i.getId()) * i.getQuantity()); - - final ItemComposition itemComposition = itemManager.getItemComposition(i.getId()); - if (!itemComposition.isTradeable() && value == 0) - { - value = itemComposition.getPrice() * i.getQuantity(); - priceMap.put(value, i); - } - else - { - value = itemManager.getItemPrice(i.getId()) * i.getQuantity(); - if (i.getId() > 0 && value > 0) - { - priceMap.put(value, i); - } - } - wealth += value; - } - return Integer.parseInt(quantityToRSDecimalStack(priceMap.keySet().stream().mapToInt(Integer::intValue).sum())); - - } -} +/* + * Copyright (c) 2019. PKLite - All Rights Reserved + * Unauthorized modification, distribution, or possession of this source file, via any medium is strictly prohibited. + * Proprietary and confidential. Refer to PKLite License file for more information on + * full terms of this copyright and to determine what constitutes authorized use. + * Written by PKLite(ST0NEWALL, others) , 2019 + * + */ + +package net.runelite.client.util; + +import java.util.Comparator; +import java.util.Objects; +import java.util.TreeMap; +import net.runelite.api.Client; +import net.runelite.api.InventoryID; +import net.runelite.api.Item; +import net.runelite.api.ItemComposition; +import net.runelite.api.Player; +import net.runelite.api.Varbits; +import net.runelite.api.WorldType; +import net.runelite.api.coords.WorldPoint; +import net.runelite.client.game.ItemManager; +import static net.runelite.client.util.StackFormatter.quantityToRSDecimalStack; +import org.apache.commons.lang3.ArrayUtils; + +/** + * + */ +public class PvPUtil +{ + + /** + * Gets the wilderness level based on a world point + * + * @param point the point in the world to get the wilderness level for + * @return the int representing the wilderness level + */ + public static int getWildernessLevelFrom(WorldPoint point) + { + int x = point.getX(); + int y = point.getY(); + + int underLevel = ((y - 9920) / 8) + 1; + int upperLevel = ((y - 3520) / 8) + 1; + + return y > 6400 ? underLevel : upperLevel; + } + + /** + * Determines if another player is attackable based off of wilderness level and combat levels + * + * @param client The client of the local player + * @param player the player to determine attackability + * @return returns true if the player is attackable, false otherwise + */ + public static boolean isAttackable(Client client, Player player) + { + int wildernessLevel = 0; + if (!(client.getVar(Varbits.IN_WILDERNESS) == 1 || WorldType.isPvpWorld(client.getWorldType()))) + { + return false; + } + if (WorldType.isPvpWorld(client.getWorldType())) + { + if (client.getVar(Varbits.IN_WILDERNESS) != 1) + { + return Math.abs(client.getLocalPlayer().getCombatLevel() - player.getCombatLevel()) <= 15; + } + wildernessLevel = 15; + } + return Math.abs(client.getLocalPlayer().getCombatLevel() - player.getCombatLevel()) + < (getWildernessLevelFrom(client.getLocalPlayer().getWorldLocation()) + wildernessLevel); + } + + public static int calculateRisk(Client client, ItemManager itemManager) + { + if (client.getItemContainer(InventoryID.EQUIPMENT) == null) + { + return 0; + } + if (client.getItemContainer(InventoryID.INVENTORY).getItems() == null) + { + return 0; + } + Item[] items = ArrayUtils.addAll(Objects.requireNonNull(client.getItemContainer(InventoryID.EQUIPMENT)).getItems(), + Objects.requireNonNull(client.getItemContainer(InventoryID.INVENTORY)).getItems()); + TreeMap priceMap = new TreeMap<>(Comparator.comparingInt(Integer::intValue)); + int wealth = 0; + for (Item i : items) + { + int value = (itemManager.getItemPrice(i.getId()) * i.getQuantity()); + + final ItemComposition itemComposition = itemManager.getItemComposition(i.getId()); + if (!itemComposition.isTradeable() && value == 0) + { + value = itemComposition.getPrice() * i.getQuantity(); + priceMap.put(value, i); + } + else + { + value = itemManager.getItemPrice(i.getId()) * i.getQuantity(); + if (i.getId() > 0 && value > 0) + { + priceMap.put(value, i); + } + } + wealth += value; + } + return Integer.parseInt(quantityToRSDecimalStack(priceMap.keySet().stream().mapToInt(Integer::intValue).sum())); + + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/util/RefUtils.java b/runelite-client/src/main/java/net/runelite/client/util/RefUtils.java index 50733334b9..5c4e5d08f3 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/RefUtils.java +++ b/runelite-client/src/main/java/net/runelite/client/util/RefUtils.java @@ -32,20 +32,20 @@ import org.objectweb.asm.tree.MethodNode; public class RefUtils implements Opcodes { - + private static final String TYPE_PREFIX = "us/runelitepl/mixinprocessor/annotations/"; - + public static boolean isReturn(int opcode, boolean checkType) { return (opcode == RETURN && !checkType) || opcode == IRETURN || opcode == LRETURN || opcode == DRETURN || - opcode == ARETURN || opcode == FRETURN; + opcode == ARETURN || opcode == FRETURN; } - + public static boolean isReturn(int opcode) { return isReturn(opcode, false); } - + public static boolean checkAnnotation(MethodNode method, String annotation) { if (method.visibleAnnotations != null) @@ -60,7 +60,7 @@ public class RefUtils implements Opcodes } return false; } - + public static boolean checkAnnotation(FieldNode field, String annotation) { if (field.visibleAnnotations != null) @@ -75,10 +75,10 @@ public class RefUtils implements Opcodes } return false; } - + public static String makeAnnotationDesc(String annot) { return "L" + TYPE_PREFIX + annot + ";"; } - + } diff --git a/runelite-client/src/main/java/net/runelite/client/util/StackFormatter.java b/runelite-client/src/main/java/net/runelite/client/util/StackFormatter.java index c9282f7f46..38a8669244 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/StackFormatter.java +++ b/runelite-client/src/main/java/net/runelite/client/util/StackFormatter.java @@ -173,7 +173,7 @@ public class StackFormatter *

* * @param quantity The quantity to convert. - * @param precise If true, the returned string will have thousandths precision if quantity is larger than 1 million. + * @param precise If true, the returned string will have thousandths precision if quantity is larger than 1 million. * @return The stack size as it would appear in RS, with decimals, * with K after 100,000 and M after 10,000,000 */ diff --git a/runelite-client/src/main/java/net/runelite/client/util/Text.java b/runelite-client/src/main/java/net/runelite/client/util/Text.java index 6158b9a32f..67892bdbc3 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/Text.java +++ b/runelite-client/src/main/java/net/runelite/client/util/Text.java @@ -81,8 +81,8 @@ public class Text /** * In addition to removing all tags, replaces nbsp with space, trims string and lowercases it - * @param str The string to standardize * + * @param str The string to standardize * @return The given `str` that is standardized */ public static String standardize(String str) @@ -166,9 +166,9 @@ public class Text * converts enum name format from THIS_FORMAT to This Format. * * @param o an enum - * @return the enum's name in title case, - * or if it overrides toString, - * the value returned by toString + * @return the enum's name in title case, + * or if it overrides toString, + * the value returned by toString */ public static String titleCase(Enum o) { diff --git a/runelite-client/src/main/java/net/runelite/client/util/WildernessLocation.java b/runelite-client/src/main/java/net/runelite/client/util/WildernessLocation.java index 0338f874bd..d212fe7060 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/WildernessLocation.java +++ b/runelite-client/src/main/java/net/runelite/client/util/WildernessLocation.java @@ -1,93 +1,95 @@ -package net.runelite.client.util; - -import lombok.Getter; -import net.runelite.api.coords.WorldArea; - -public enum WildernessLocation -{ - - REV_CAVE_OTHER("Rev Cave", new Location(3128, 10232, 3225, 10059), 0), - REV_BLACK_DRAGS("Rev Black Drags", new Location(3223, 10216, 3254, 10190), 0), - REV_DARK_BEAST("Rev Dark Beast", new Location(3243, 10154, 3264, 10136), 0), - REV_MAIN_CHAMBER("Main Rev Chamber", new Location(3227, 10187, 3261, 10157), 0), - REV_ENTRANCE_INSIDE("Inside Rev Ent.", new Location(3238, 10236, 3243, 10231), 0), - ICE_ROCK("Ice Rock", new Location(2957, 3942, 2984, 3929), 0), - WILDY_AGILITY_COURSE("Wildy Agility Course", new Location(2988, 3967, 3008, 3906), 0), - FIRE_GIANT_ENTRANCE("Fire Giant Entrance", new Location(3042, 3929, 3051, 3920), 0), - PIRATE_HUT("Pirate Hut", new Location(3037, 3959, 3045, 3948), 0), - MAGE_BANK("Mage Bank", new Location(3082, 3960, 3103, 3952), 0), - MAGE_ARENA("Mage Arena", new Location(3088, 3949, 3123, 3919), 0), - LEVER("Lever", new Location(3149, 3933, 3162, 3917), 0), - WEB("Web", new Location(3153, 3961, 3163, 3948), 0), - RESOURCE_ARENA("Resource Arena", new Location(3174, 3946, 3195, 3923), 0), - AXE_HUT("Axe Hut", new Location(3187, 3962, 3194, 3957), 0), - SCORPIA("Scorpia", new Location(3216, 3949, 3248, 3935), 0), - ROGUE_CASTLE("Rogue Castle", new Location(3275, 3947, 3299, 3920), 0), - FIFTY_PORTS("50 ports", new Location(3301, 3923, 3315, 3909), 0), - VOLCANO("Volcano", new Location(3345, 3957, 3390, 3916), 0), - NEW_GATE("New Gate", new Location(3345, 3957, 3390, 3916), 0), - GLORY_HOLE("Glory Hole", new Location(3352, 3897, 3386, 3869), 0), - GLORY_HILL("Glory Hill", new Location(3331, 3890, 3348, 3866), 0), - GDZ("Gdz", new Location(3279, 3895, 3296, 3875), 0), - GAP("Gap", new Location(3238, 3855, 3258, 3841), 0), - OLD_GATE("Old Gate", new Location(3211, 3906, 3238, 3882), 0), - LAVA_DRAGS("Lava Drags", new Location(3175, 3857, 3221, 3805), 0), - SPIDER_HILL("Spider Hill", new Location(3156, 3896, 3182, 3871), 0), - RUNE_ROCKS("Rune Rocks", new Location(3055, 3890, 3072, 3876), 0), - ICE_GATE("Ice Gate", new Location(2945, 3913, 2978, 3878), 0), - VENENATIS("Venenatis", new Location(3298, 3759, 3353, 3722), 0), - SINGLE_STRIP("Single Strip", new Location(3333, 3842, 3348, 3774), 0), - CALLISTO("Callisto", new Location(3266, 3863, 3315, 3827), 0), - DWARVES("Dwarves", new Location(3230, 3805, 3264, 3779), 0), - VETTION("Vet'tion", new Location(3183, 3796, 3227, 3765), 0), - EAST_DRAGONS("East Drags", new Location(3326, 3704, 3365, 3671), 0), - HILL_GIANTS("Hill Giants", new Location(3282, 3687, 3300, 3674), 0), - ENTS("Ents", new Location(3300, 3627, 3320, 3584), 0), - CHAOS_TEMPLE("Chaos Temple", new Location(3220, 3632, 3255, 3593), 0), - NINETEEN_OBELISK("19s", new Location(3220, 3672, 3234, 3660), 0), - CORP_CAVE("Corp Cave", new Location(3201, 3684, 3219, 3672), 0), - THIRTEEN_OBELISK("13s", new Location(3145, 3628, 3168, 3609), 0), - SOUTH_REV_ENTRANCE("Lvl 18 Rev Ent", new Location(3071, 3660, 3092, 3645), 0), - GRAVES("Graves", new Location(3128, 3686, 3181, 3658), 0), - GRAVEYARD_DRAGS("Graveyard Drags", new Location(3129, 3717, 3172, 3691), 0), - CHINS("Chins", new Location(3128, 3792, 3160, 3754), 0), - REV_ENTRANCE("Rev Entrance", new Location(3118, 3837, 3142, 3818), 0), - HOB_OBELISK("35 Obelisk", new Location(3097, 3804, 3115, 3785), 0), - HOBGOBLINS("Hobgoblins", new Location(3073, 3775, 3104, 3745), 0), - GWD("God Wars Dungeon", new Location(3010, 3745, 3027, 3727), 0), - LAVA_MAZE_TELE("Lava Maze Tele", new Location(3019, 3842, 3044, 3812), 0), - KBD_CAGE("KBD CAGE", new Location(3007, 3855, 3021, 3839), 0), - GHORROCK("44s", new Location(2973, 3870, 2987, 3859), 0), - CHAOS_FANATIC("Chaos Fanatic", new Location(2971, 3854, 2992, 3834), 0), - HIGH_ALTAR("High Altar", new Location(2945, 3826, 2970, 3813), 0), - CEMETERY("Cemetery", new Location(2956, 3767, 2996, 3736), 0), - CRAZY_ARCHAEOLOGIST("Crazy Archaeologist", new Location(2952, 3709, 2985, 3678), 0), - DARK_WARRIOR_FORTRESS("Dark Warriors", new Location(3014, 3648, 3046, 3616), 0), - WEST_DRAGONS("West Drags", new Location(2960, 3627, 2992, 3598), 0), - BANDIT_CAMP("Bandit Camp", new Location(3017, 3712, 3059, 3681), 0); - - @Getter - private final String name; - @Getter - private final WorldArea worldArea; - WildernessLocation(String name, Location location, int plane) - { - this.name = name; - this.worldArea = new WorldArea(location.x, location.y, location.width, location.height, plane); - } - - public static class Location - { - public int x; - public int y; - public int width; - public int height; - Location(int x, int y, int x1, int y1) - { - this.x = x; - this.y = y1; - this.width = x1 - x; - this.height = y - y1; - } - } -} +package net.runelite.client.util; + +import lombok.Getter; +import net.runelite.api.coords.WorldArea; + +public enum WildernessLocation +{ + + REV_CAVE_OTHER("Rev Cave", new Location(3128, 10232, 3225, 10059), 0), + REV_BLACK_DRAGS("Rev Black Drags", new Location(3223, 10216, 3254, 10190), 0), + REV_DARK_BEAST("Rev Dark Beast", new Location(3243, 10154, 3264, 10136), 0), + REV_MAIN_CHAMBER("Main Rev Chamber", new Location(3227, 10187, 3261, 10157), 0), + REV_ENTRANCE_INSIDE("Inside Rev Ent.", new Location(3238, 10236, 3243, 10231), 0), + ICE_ROCK("Ice Rock", new Location(2957, 3942, 2984, 3929), 0), + WILDY_AGILITY_COURSE("Wildy Agility Course", new Location(2988, 3967, 3008, 3906), 0), + FIRE_GIANT_ENTRANCE("Fire Giant Entrance", new Location(3042, 3929, 3051, 3920), 0), + PIRATE_HUT("Pirate Hut", new Location(3037, 3959, 3045, 3948), 0), + MAGE_BANK("Mage Bank", new Location(3082, 3960, 3103, 3952), 0), + MAGE_ARENA("Mage Arena", new Location(3088, 3949, 3123, 3919), 0), + LEVER("Lever", new Location(3149, 3933, 3162, 3917), 0), + WEB("Web", new Location(3153, 3961, 3163, 3948), 0), + RESOURCE_ARENA("Resource Arena", new Location(3174, 3946, 3195, 3923), 0), + AXE_HUT("Axe Hut", new Location(3187, 3962, 3194, 3957), 0), + SCORPIA("Scorpia", new Location(3216, 3949, 3248, 3935), 0), + ROGUE_CASTLE("Rogue Castle", new Location(3275, 3947, 3299, 3920), 0), + FIFTY_PORTS("50 ports", new Location(3301, 3923, 3315, 3909), 0), + VOLCANO("Volcano", new Location(3345, 3957, 3390, 3916), 0), + NEW_GATE("New Gate", new Location(3345, 3957, 3390, 3916), 0), + GLORY_HOLE("Glory Hole", new Location(3352, 3897, 3386, 3869), 0), + GLORY_HILL("Glory Hill", new Location(3331, 3890, 3348, 3866), 0), + GDZ("Gdz", new Location(3279, 3895, 3296, 3875), 0), + GAP("Gap", new Location(3238, 3855, 3258, 3841), 0), + OLD_GATE("Old Gate", new Location(3211, 3906, 3238, 3882), 0), + LAVA_DRAGS("Lava Drags", new Location(3175, 3857, 3221, 3805), 0), + SPIDER_HILL("Spider Hill", new Location(3156, 3896, 3182, 3871), 0), + RUNE_ROCKS("Rune Rocks", new Location(3055, 3890, 3072, 3876), 0), + ICE_GATE("Ice Gate", new Location(2945, 3913, 2978, 3878), 0), + VENENATIS("Venenatis", new Location(3298, 3759, 3353, 3722), 0), + SINGLE_STRIP("Single Strip", new Location(3333, 3842, 3348, 3774), 0), + CALLISTO("Callisto", new Location(3266, 3863, 3315, 3827), 0), + DWARVES("Dwarves", new Location(3230, 3805, 3264, 3779), 0), + VETTION("Vet'tion", new Location(3183, 3796, 3227, 3765), 0), + EAST_DRAGONS("East Drags", new Location(3326, 3704, 3365, 3671), 0), + HILL_GIANTS("Hill Giants", new Location(3282, 3687, 3300, 3674), 0), + ENTS("Ents", new Location(3300, 3627, 3320, 3584), 0), + CHAOS_TEMPLE("Chaos Temple", new Location(3220, 3632, 3255, 3593), 0), + NINETEEN_OBELISK("19s", new Location(3220, 3672, 3234, 3660), 0), + CORP_CAVE("Corp Cave", new Location(3201, 3684, 3219, 3672), 0), + THIRTEEN_OBELISK("13s", new Location(3145, 3628, 3168, 3609), 0), + SOUTH_REV_ENTRANCE("Lvl 18 Rev Ent", new Location(3071, 3660, 3092, 3645), 0), + GRAVES("Graves", new Location(3128, 3686, 3181, 3658), 0), + GRAVEYARD_DRAGS("Graveyard Drags", new Location(3129, 3717, 3172, 3691), 0), + CHINS("Chins", new Location(3128, 3792, 3160, 3754), 0), + REV_ENTRANCE("Rev Entrance", new Location(3118, 3837, 3142, 3818), 0), + HOB_OBELISK("35 Obelisk", new Location(3097, 3804, 3115, 3785), 0), + HOBGOBLINS("Hobgoblins", new Location(3073, 3775, 3104, 3745), 0), + GWD("God Wars Dungeon", new Location(3010, 3745, 3027, 3727), 0), + LAVA_MAZE_TELE("Lava Maze Tele", new Location(3019, 3842, 3044, 3812), 0), + KBD_CAGE("KBD CAGE", new Location(3007, 3855, 3021, 3839), 0), + GHORROCK("44s", new Location(2973, 3870, 2987, 3859), 0), + CHAOS_FANATIC("Chaos Fanatic", new Location(2971, 3854, 2992, 3834), 0), + HIGH_ALTAR("High Altar", new Location(2945, 3826, 2970, 3813), 0), + CEMETERY("Cemetery", new Location(2956, 3767, 2996, 3736), 0), + CRAZY_ARCHAEOLOGIST("Crazy Archaeologist", new Location(2952, 3709, 2985, 3678), 0), + DARK_WARRIOR_FORTRESS("Dark Warriors", new Location(3014, 3648, 3046, 3616), 0), + WEST_DRAGONS("West Drags", new Location(2960, 3627, 2992, 3598), 0), + BANDIT_CAMP("Bandit Camp", new Location(3017, 3712, 3059, 3681), 0); + + @Getter + private final String name; + @Getter + private final WorldArea worldArea; + + WildernessLocation(String name, Location location, int plane) + { + this.name = name; + this.worldArea = new WorldArea(location.x, location.y, location.width, location.height, plane); + } + + public static class Location + { + public int x; + public int y; + public int width; + public int height; + + Location(int x, int y, int x1, int y1) + { + this.x = x; + this.y = y1; + this.width = x1 - x; + this.height = y - y1; + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/util/WorldUtil.java b/runelite-client/src/main/java/net/runelite/client/util/WorldUtil.java index 9f508676a5..67115d49ac 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/WorldUtil.java +++ b/runelite-client/src/main/java/net/runelite/client/util/WorldUtil.java @@ -1,52 +1,53 @@ -/* - * Copyright (c) 2018, Tomas Slusny - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.util; - -import java.util.EnumSet; -import net.runelite.api.WorldType; - -/** - * Utility class for RuneScape worlds - */ -public class WorldUtil -{ - /** - * Converts http-api world types to runelite-api world types - * TODO: Find a better way to handle these to not have duplicate interfaces - * @param apiTypes http-api world types - * @return runelite-api world types - */ - public static EnumSet toWorldTypes(final EnumSet apiTypes) - { - final EnumSet types = EnumSet.noneOf(net.runelite.api.WorldType.class); - - for (net.runelite.http.api.worlds.WorldType apiType : apiTypes) - { - types.add(net.runelite.api.WorldType.valueOf(apiType.name())); - } - - return types; - } -} +/* + * Copyright (c) 2018, Tomas Slusny + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.util; + +import java.util.EnumSet; +import net.runelite.api.WorldType; + +/** + * Utility class for RuneScape worlds + */ +public class WorldUtil +{ + /** + * Converts http-api world types to runelite-api world types + * TODO: Find a better way to handle these to not have duplicate interfaces + * + * @param apiTypes http-api world types + * @return runelite-api world types + */ + public static EnumSet toWorldTypes(final EnumSet apiTypes) + { + final EnumSet types = EnumSet.noneOf(net.runelite.api.WorldType.class); + + for (net.runelite.http.api.worlds.WorldType apiType : apiTypes) + { + types.add(net.runelite.api.WorldType.valueOf(apiType.name())); + } + + return types; + } +} diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/slayer/SlayerPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/slayer/SlayerPluginTest.java index e7e5d914f2..099a76d19b 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/slayer/SlayerPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/slayer/SlayerPluginTest.java @@ -34,9 +34,7 @@ import net.runelite.api.ChatMessageType; import static net.runelite.api.ChatMessageType.GAMEMESSAGE; import net.runelite.api.Client; import net.runelite.api.MessageNode; -import net.runelite.api.Player; import net.runelite.api.Varbits; -import net.runelite.api.coords.LocalPoint; import net.runelite.api.events.ChatMessage; import net.runelite.api.events.GameTick; import net.runelite.api.events.VarbitChanged;