more checkstyle etc

This commit is contained in:
Lucas
2019-05-17 05:11:02 +02:00
parent 11543b5739
commit 53a82699e4
106 changed files with 7790 additions and 6950 deletions

View File

@@ -79,7 +79,7 @@ public class ClientSessionManager
}
sessionId = null;
}
scheduledFuture.cancel(true);
}

View File

@@ -100,7 +100,7 @@ public class Notifier
// First check if we are running in launcher
this.terminalNotifierAvailable =
!Strings.isNullOrEmpty(RuneLiteProperties.getLauncherVersion())
&& isTerminalNotifierAvailable();
&& isTerminalNotifierAvailable();
storeIcon();
}

View File

@@ -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();

View File

@@ -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);
}
}

View File

@@ -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);
}

View File

@@ -1,232 +1,232 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* 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 <Adam@sigterm.info>
* 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();
}
}

View File

@@ -374,6 +374,7 @@ public class Hooks implements Callbacks
/**
* Copy an image
*
* @param src
* @return
*/

View File

@@ -1,153 +1,153 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* 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<MethodHandles.Lookup> 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 <Adam@sigterm.info>
* 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<MethodHandles.Lookup> 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);
}
}

View File

@@ -1,52 +1,52 @@
/*
* Copyright (c) 2018, Craftiii4 <craftiii4@gmail.com>
* 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<ConfigItemDescriptor> items;
public ConfigItemsGroup(String group)
{
this.group = group;
this.items = new ArrayList<>();
}
public void addItem(ConfigItemDescriptor item)
{
items.add(item);
}
}
/*
* Copyright (c) 2018, Craftiii4 <craftiii4@gmail.com>
* 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<ConfigItemDescriptor> items;
public ConfigItemsGroup(String group)
{
this.group = group;
this.items = new ArrayList<>();
}
public void addItem(ConfigItemDescriptor item)
{
items.add(item);
}
}

View File

@@ -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<String, String> 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<String, String> 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;
}

View File

@@ -1,49 +1,48 @@
/*
* Copyright (c) 2018, Tanner <https://github.com/Reasel>
* 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 <https://github.com/Reasel>
* 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;
}
}

View File

@@ -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()
{

View File

@@ -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);
}

View File

@@ -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()<initialMS+delayMS) {
try {
Thread.sleep(10);
} catch (Exception e) {
e.printStackTrace();
}
}
isActive = false;
}
private RobotDisposer(RobotPeer peer)
{
this.peer = peer;
}
@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 void dispose()
{
if (peer != null)
{
peer.dispose();
}
}
}
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();
}
}
private void pauseMS(int delayMS)
{
long initialMS = System.currentTimeMillis();
while (System.currentTimeMillis() < initialMS + delayMS)
{
try
{
Thread.sleep(10);
}
catch (Exception e)
{
e.printStackTrace();
}
}
isActive = false;
}
@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());
}
@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
* <code>keyRelease</code> method.
* <p>
* Key codes that have more than one physical key associated with them
* (e.g. <code>KeyEvent.VK_SHIFT</code> could mean either the
* left or right shift key) will map to the left key.
*
* @param keycode Key to press (e.g. <code>KeyEvent.VK_A</code>)
* @throws IllegalArgumentException if <code>keycode</code> 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
* <code>keyRelease</code> method.
* <p>
* Key codes that have more than one physical key associated with them
* (e.g. <code>KeyEvent.VK_SHIFT</code> could mean either the
* left or right shift key) will map to the left key.
*
* @param keycode Key to press (e.g. <code>KeyEvent.VK_A</code>)
* @throws IllegalArgumentException if <code>keycode</code> 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();
}
}

View File

@@ -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;
}
}

View File

@@ -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),

View File

@@ -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<Runnable> 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<Runnable> 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);
}
}

View File

@@ -1,271 +1,675 @@
/*
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
* Copyright (c) 2018, Seth <Sethtroll3@gmail.com>
* 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<Integer, Integer> 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<Integer> map(int itemId)
{
final Collection<Integer> 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<Integer> mapping = MAPPINGS.get(itemId);
if (mapping == null || mapping.isEmpty())
{
return itemId;
}
return mapping.iterator().next();
}
}
/*
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
* Copyright (c) 2018, Seth <Sethtroll3@gmail.com>
* 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<Integer, Integer> 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<Integer> map(int itemId)
{
final Collection<Integer> 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<Integer> mapping = MAPPINGS.get(itemId);
if (mapping == null || mapping.isEmpty())
{
return itemId;
}
return mapping.iterator().next();
}
}

View File

@@ -1,65 +1,66 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* 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<String, Integer> healthMap;
@Inject
private NPCManager()
{
final Gson gson = new Gson();
final Type typeToken = new TypeToken<Map<String, Integer>>()
{
}.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 <Adam@sigterm.info>
* 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<String, Integer> healthMap;
@Inject
private NPCManager()
{
final Gson gson = new Gson();
final Type typeToken = new TypeToken<Map<String, Integer>>()
{
}.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);
}
}

View File

@@ -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<ChatboxTextMenuInput> chatboxTextMenuInputProvider;
private final Provider<ChatboxTextInput> chatboxTextInputProvider;
@Getter
private ChatboxInput currentInput = null;
@Inject
private ChatboxPanelManager(EventBus eventBus, Client client, ClientThread clientThread,
KeyManager keyManager, MouseManager mouseManager,
Provider<ChatboxTextMenuInput> chatboxTextMenuInputProvider, Provider<ChatboxTextInput> 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<ChatboxTextMenuInput> chatboxTextMenuInputProvider;
private final Provider<ChatboxTextInput> chatboxTextInputProvider;
@Getter
private ChatboxInput currentInput = null;
@Inject
private ChatboxPanelManager(EventBus eventBus, Client client, ClientThread clientThread,
KeyManager keyManager, MouseManager mouseManager,
Provider<ChatboxTextMenuInput> chatboxTextMenuInputProvider, Provider<ChatboxTextInput> 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);
}
}

View File

@@ -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<Entry> 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<Entry> 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)
{
}
}

View File

@@ -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<PixelDistanceAlpha> 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)
{

View File

@@ -1,106 +1,105 @@
/*
* Copyright (c) 2017, Robin <robin.weymans@gmail.com>
* 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 <robin.weymans@gmail.com>
* 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;
}
}

View File

@@ -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)

View File

@@ -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);

View File

@@ -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;

View File

@@ -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())

View File

@@ -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);

View File

@@ -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());
}

View File

@@ -53,7 +53,7 @@ import org.apache.commons.lang3.ArrayUtils;
)
public class FriendTaggingPlugin extends Plugin
{
public static ConcurrentHashMap<String, String> taggedFriends = new ConcurrentHashMap<>();
public static final ConcurrentHashMap<String, String> taggedFriends = new ConcurrentHashMap<>();
private static final String CONFIG_GROUP = "friendtagging";
private static final int CHARACTER_LIMIT = 30;

View File

@@ -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)
{

View File

@@ -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();

View File

@@ -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<InventorySetupItem> 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<InventorySetupItem> 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);
}

View File

@@ -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<String> 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<InventorySetupItem> normInv = plugin.getNormalizedContainer(InventoryID.INVENTORY);
final ArrayList<InventorySetupItem> 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<InventorySetupItem> 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<String> 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<InventorySetupItem> normInv = plugin.getNormalizedContainer(InventoryID.INVENTORY);
final ArrayList<InventorySetupItem> 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<InventorySetupItem> 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();
}
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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(

View File

@@ -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),

View File

@@ -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),

View File

@@ -365,7 +365,7 @@ public class PlayerIndicatorsPlugin extends Plugin
}
}
public enum minimapSkullLocations
public enum MinimapSkullLocations
{
BEFORE_NAME,
AFTER_NAME

View File

@@ -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
}

View File

@@ -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);

View File

@@ -162,6 +162,7 @@ public class PyramidPlunderPlugin extends Plugin
break;
case LOADING:
obstacles.clear();
break;
case LOGGED_IN:
if (!isInRegion())
{

View File

@@ -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("</br>Lower level: " + secondsToTime(lowerTime - upperTime));
builder.append("</br>Lower level: ").append(secondsToTime(lowerTime - upperTime));
}
}
else
{
builder.append("</br>Middle level: " + secondsToTime(middleTime - upperTime));
builder.append("</br>Middle level: ").append(secondsToTime(middleTime - upperTime));
if (lowerTime == -1)
{
tooltip = builder.toString();
@@ -865,7 +865,7 @@ public class RaidsPlugin extends Plugin
}
else
{
builder.append("</br>Lower level: " + secondsToTime(lowerTime - middleTime));
builder.append("</br>Lower level: ").append(secondsToTime(lowerTime - middleTime));
}
}
if (raidTime == -1)
@@ -873,7 +873,7 @@ public class RaidsPlugin extends Plugin
tooltip = builder.toString();
return;
}
builder.append("</br>Olm: " + secondsToTime(raidTime - lowerTime));
builder.append("</br>Olm: ").append(secondsToTime(raidTime - lowerTime));
tooltip = builder.toString();
}
}

View File

@@ -1,61 +1,61 @@
/*
* Copyright (c) 2018, Tim Lehner <Timothy.Lehner.2011@live.rhul.ac.uk>
* 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 <Timothy.Lehner.2011@live.rhul.ac.uk>
* 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;
}
}

View File

@@ -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)
{

View File

@@ -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);
}
}

View File

@@ -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--)

View File

@@ -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);
}
}

View File

@@ -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<Integer> makeSimple(int[][] board)
ArrayList<Integer> makeSimple(int[][] board)
{
ArrayList<Integer> 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);

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);

View File

@@ -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<Entry<String, Integer>> 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)
{

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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<String, byte[]> 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<String, String> hashes;
@@ -143,33 +138,33 @@ public class ClientLoader
{
}.getType());
}
for (Map.Entry<String, String> 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<String, byte[]> 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<String, byte[]> patches = new HashMap<>();
for (Map.Entry<String, byte[]> 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;

View File

@@ -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<String, byte[]> classes;
private final Map<String, byte[]> patches;
public Map<String, byte[]> 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<? extends Remapper> clazz) throws IllegalAccessException, InstantiationException
{
for (Map.Entry<String, byte[]> 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<? extends ClassVisitor> clazz)
throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException
throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException
{
runVisitor(clazz, 1);
}
private void runVisitor(Class<? extends ClassVisitor> clazz, int flags)
throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException
throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException
{
for (Map.Entry<String, byte[]> 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<? extends SanityChecker> clazz)
throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException
throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException
{
runSanityChecker(clazz, 1);
}
private void runSanityChecker(Class<? extends SanityChecker> clazz, int flags)
throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException
throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException
{
for (Map.Entry<String, byte[]> 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);
}
}

View File

@@ -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;
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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<String> 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);

View File

@@ -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;
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -34,5 +34,5 @@ public abstract class SanityChecker extends ClassVisitor implements Opcodes
{
super(i, classVisitor);
}
}

View File

@@ -1,66 +1,66 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* 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 <Adam@sigterm.info>
* 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);
}
}
}

View File

@@ -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)
{

View File

@@ -1,200 +1,202 @@
/*
* Copyright (c) 2018, Woox <https://github.com/wooxsolo>
* 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 <https://github.com/wooxsolo>
* 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;
}
}

View File

@@ -1,215 +1,216 @@
/*
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
* 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<Component, Dimension> 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 <slusnucky@gmail.com>
* 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.
* <p>
* 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<Component, Dimension> 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());
}
}

View File

@@ -1,96 +1,96 @@
/*
* Copyright (c) 2017, Tyler <https://github.com/tylerthardy>
* 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 <https://github.com/tylerthardy>
* 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;
}
}

View File

@@ -1,243 +1,248 @@
/*
* Copyright (c) 2016-2017, Jeremy Plsek <github.com/jplsek>
* 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 <github.com/jplsek>
* 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);
});
}
}

View File

@@ -1,90 +1,91 @@
/*
* Copyright (c) 2018, Levi <me@levischuck.com>
* 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 <me@levischuck.com>
* 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);
}
}
}

View File

@@ -1,95 +1,95 @@
/*
* Copyright (c) 2018, Psikoi <https://github.com/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 <https://github.com/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);
}
}

View File

@@ -1,71 +1,72 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* 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<OverlayMenuEntry> 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 <Adam@sigterm.info>
* 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<OverlayMenuEntry> 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();
}
}

View File

@@ -1,385 +1,385 @@
/*
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
* 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> 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<Overlay> overlays = new ArrayList<>();
@Getter
private final List<WidgetItem> itemWidgets = new ArrayList<>();
private final Map<OverlayLayer, List<Overlay>> 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<Overlay> optionalOverlay = overlays.stream().filter(o -> overlays.indexOf(o) == event.getId()).findAny();
if (optionalOverlay.isPresent())
{
Overlay overlay = optionalOverlay.get();
List<OverlayMenuEntry> menuEntries = overlay.getMenuEntries();
Optional<OverlayMenuEntry> 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<Overlay> 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<Overlay> 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 <slusnucky@gmail.com>
* 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> 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<Overlay> overlays = new ArrayList<>();
@Getter
private final List<WidgetItem> itemWidgets = new ArrayList<>();
private final Map<OverlayLayer, List<Overlay>> 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<Overlay> optionalOverlay = overlays.stream().filter(o -> overlays.indexOf(o) == event.getId()).findAny();
if (optionalOverlay.isPresent())
{
Overlay overlay = optionalOverlay.get();
List<OverlayMenuEntry> menuEntries = overlay.getMenuEntries();
Optional<OverlayMenuEntry> 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<Overlay> 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<Overlay> 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;
}
}

View File

@@ -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());

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -1,61 +1,59 @@
/*
* Copyright (c) 2018, Morgan Lewis <https://github.com/MESLewis>
* 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<Plugin, ArrowPoint> 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 <https://github.com/MESLewis>
* 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<Plugin, ArrowPoint> 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();
}
}

View File

@@ -1,98 +1,98 @@
/*
* Copyright (c) 2017, Tomas Slusny <slusnucky@gmail.com>
* 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 <slusnucky@gmail.com>
* 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());
}
}

View File

@@ -1,37 +1,39 @@
/*
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
* 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 <slusnucky@gmail.com>
* 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);
}

View File

@@ -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)
{

View File

@@ -1,220 +1,220 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* 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("</br>");
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 <Adam@sigterm.info>
* 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("</br>");
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);
}
}
}
}
}

View File

@@ -1,166 +1,166 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* 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<InfoBox> 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<InfoBox> filter)
{
if (infoBoxes.removeIf(filter))
{
log.debug("Removed InfoBoxes for filter {}", filter);
refreshInfoBoxes();
}
}
public List<InfoBox> getInfoBoxes()
{
return Collections.unmodifiableList(infoBoxes);
}
public void cull()
{
boolean culled = false;
for (Iterator<InfoBox> 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 <Adam@sigterm.info>
* 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<InfoBox> 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<InfoBox> filter)
{
if (infoBoxes.removeIf(filter))
{
log.debug("Removed InfoBoxes for filter {}", filter);
refreshInfoBoxes();
}
}
public List<InfoBox> getInfoBoxes()
{
return Collections.unmodifiableList(infoBoxes);
}
public void cull()
{
boolean culled = false;
for (Iterator<InfoBox> 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());
}
}

View File

@@ -1,311 +1,312 @@
/*
* Copyright (c) 2018, Morgan Lewis <https://github.com/MESLewis>
* 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<WorldMapPoint> 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 <code>baseRectangle</code>, 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 <https://github.com/MESLewis>
* 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<WorldMapPoint> 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 <code>baseRectangle</code>, 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);
}
}

View File

@@ -1,242 +1,243 @@
/*
* Copyright (c) 2018, Jordan Atwood <jordan.atwood423@gmail.com>
* 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 = "<col=";
private static final String OPENING_COLOR_TAG_END = ">";
private static final String CLOSING_COLOR_TAG = "</col>";
private final static Pattern ALPHA_HEX_PATTERN = Pattern.compile("^(#|0x)?[0-9a-fA-F]{7,8}");
private final static Pattern HEX_PATTERN = Pattern.compile("^(#|0x)?[0-9a-fA-F]{1,8}");
/**
* Creates a color tag from the given color.
*
* @param color The Color to create a tag from.
* @return A string of the color tag for the given color.
*/
public static String colorTag(Color color)
{
return OPENING_COLOR_TAG_START + colorToHexCode(color) + OPENING_COLOR_TAG_END;
}
/**
* Prepends the given str with an opening color tag of the given color.
*
* @param str The string to be colorized.
* @param color The color to be used in the color tag.
* @return The passed str with a prepended color tag.
*/
public static String prependColorTag(final String str, final Color color)
{
return colorTag(color) + str;
}
/**
* Wraps the given str with a color tag of the given color.
*
* @param str The string to be colorized.
* @param color The color to be used in the color tag.
* @return The passed str wrapped with opening and closing color tags.
*/
public static String wrapWithColorTag(final String str, final Color color)
{
return prependColorTag(str, color) + CLOSING_COLOR_TAG;
}
/**
* Converts a given color to it's hexidecimal equivalent.
*
* @param color Color to get hexidecimal string from.
* @return Hexidecimal string representing the given color, in the form "#abcdef".
*/
public static String toHexColor(final Color color)
{
return "#" + colorToHexCode(color);
}
/**
* Linearly interpolates between colors a and b by t.
*
* @param a first color
* @param b second color
* @param t factor
* @return interpolated color
*/
public static Color colorLerp(final Color a, final Color b, final double t)
{
final double r1 = a.getRed();
final double r2 = b.getRed();
final double g1 = a.getGreen();
final double g2 = b.getGreen();
final double b1 = a.getBlue();
final double b2 = b.getBlue();
return new Color(
(int) Math.round(r1 + (t * (r2 - r1))),
(int) Math.round(g1 + (t * (g2 - g1))),
(int) Math.round(b1 + (t * (b2 - b1)))
);
}
/**
* Gets the RGB hex color code of the passed color.
*
* @param color The color to get a hex code from.
* @return A lower-cased string of the RGB hex code of color.
*/
public static String colorToHexCode(final Color color)
{
return String.format("%06x", color.getRGB() & 0xFFFFFF);
}
/**
* Gets the ARGB hex color code of the passed color.
*
* @param color The color to get a hex code from.
* @return A lower-cased string of the ARGB hex code of color.
*/
public static String colorToAlphaHexCode(final Color color)
{
return String.format("%08x", color.getRGB());
}
static boolean isFullyTransparent(final Color color)
{
return color.getAlpha() == 0;
}
static boolean isNotFullyTransparent(final Color color)
{
return !isFullyTransparent(color);
}
/**
* Determines if the passed hex string is an alpha hex color.
*
* @param hex The hex to test.
* @return boolean
*/
public static boolean isAlphaHex(String hex)
{
return ALPHA_HEX_PATTERN.matcher(hex).matches();
}
/**
* Determines if the passed hex string is a hex color.
*
* @param hex The hex to test.
* @return boolean
*/
public static boolean isHex(String hex)
{
return HEX_PATTERN.matcher(hex).matches();
}
/**
* Limits an int to the rgba value range (0-255)
*
* @param value The value for the r, g, b, or a.
* @return An int between 0 - 255.
*/
public static int constrainValue(int value)
{
return Ints.constrainToRange(value, MIN_RGB_VALUE, MAX_RGB_VALUE);
}
/**
* Gets the Color from the passed int string.
*
* @param string The int to get a Color object from.
* @return A Color of the int of color.
*/
public static Color fromString(String string)
{
try
{
int i = Integer.decode(string);
return new Color(i, true);
}
catch (NumberFormatException e)
{
return null;
}
}
/**
* Gets the Color from the passed hex string.
*
* @param hex The hex to get a Color object from.
* @return A Color of the hex code of color.
*/
public static Color fromHex(String hex)
{
if (!hex.startsWith("#") && !hex.startsWith("0x"))
{
hex = "#" + hex;
}
if ((hex.length() <= 7 && hex.startsWith("#")) || (hex.length() <= 8 && hex.startsWith("0x")))
{
try
{
return Color.decode(hex);
}
catch (NumberFormatException e)
{
return null;
}
}
try
{
return new Color(Long.decode(hex).intValue(), true);
}
catch (NumberFormatException e)
{
return null;
}
}
/**
* Creates color from passed object hash code
* @param object object with hashCode
* @return color
*/
public static Color fromObject(@Nonnull final Object object)
{
int i = object.hashCode();
float h = (i % 360) / 360f;
return Color.getHSBColor(h, 1, 1);
}
}
/*
* Copyright (c) 2018, Jordan Atwood <jordan.atwood423@gmail.com>
* 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 = "<col=";
private static final String OPENING_COLOR_TAG_END = ">";
private static final String CLOSING_COLOR_TAG = "</col>";
private final static Pattern ALPHA_HEX_PATTERN = Pattern.compile("^(#|0x)?[0-9a-fA-F]{7,8}");
private final static Pattern HEX_PATTERN = Pattern.compile("^(#|0x)?[0-9a-fA-F]{1,8}");
/**
* Creates a color tag from the given color.
*
* @param color The Color to create a tag from.
* @return A string of the color tag for the given color.
*/
public static String colorTag(Color color)
{
return OPENING_COLOR_TAG_START + colorToHexCode(color) + OPENING_COLOR_TAG_END;
}
/**
* Prepends the given str with an opening color tag of the given color.
*
* @param str The string to be colorized.
* @param color The color to be used in the color tag.
* @return The passed str with a prepended color tag.
*/
public static String prependColorTag(final String str, final Color color)
{
return colorTag(color) + str;
}
/**
* Wraps the given str with a color tag of the given color.
*
* @param str The string to be colorized.
* @param color The color to be used in the color tag.
* @return The passed str wrapped with opening and closing color tags.
*/
public static String wrapWithColorTag(final String str, final Color color)
{
return prependColorTag(str, color) + CLOSING_COLOR_TAG;
}
/**
* Converts a given color to it's hexidecimal equivalent.
*
* @param color Color to get hexidecimal string from.
* @return Hexidecimal string representing the given color, in the form "#abcdef".
*/
public static String toHexColor(final Color color)
{
return "#" + colorToHexCode(color);
}
/**
* Linearly interpolates between colors a and b by t.
*
* @param a first color
* @param b second color
* @param t factor
* @return interpolated color
*/
public static Color colorLerp(final Color a, final Color b, final double t)
{
final double r1 = a.getRed();
final double r2 = b.getRed();
final double g1 = a.getGreen();
final double g2 = b.getGreen();
final double b1 = a.getBlue();
final double b2 = b.getBlue();
return new Color(
(int) Math.round(r1 + (t * (r2 - r1))),
(int) Math.round(g1 + (t * (g2 - g1))),
(int) Math.round(b1 + (t * (b2 - b1)))
);
}
/**
* Gets the RGB hex color code of the passed color.
*
* @param color The color to get a hex code from.
* @return A lower-cased string of the RGB hex code of color.
*/
public static String colorToHexCode(final Color color)
{
return String.format("%06x", color.getRGB() & 0xFFFFFF);
}
/**
* Gets the ARGB hex color code of the passed color.
*
* @param color The color to get a hex code from.
* @return A lower-cased string of the ARGB hex code of color.
*/
public static String colorToAlphaHexCode(final Color color)
{
return String.format("%08x", color.getRGB());
}
static boolean isFullyTransparent(final Color color)
{
return color.getAlpha() == 0;
}
static boolean isNotFullyTransparent(final Color color)
{
return !isFullyTransparent(color);
}
/**
* Determines if the passed hex string is an alpha hex color.
*
* @param hex The hex to test.
* @return boolean
*/
public static boolean isAlphaHex(String hex)
{
return ALPHA_HEX_PATTERN.matcher(hex).matches();
}
/**
* Determines if the passed hex string is a hex color.
*
* @param hex The hex to test.
* @return boolean
*/
public static boolean isHex(String hex)
{
return HEX_PATTERN.matcher(hex).matches();
}
/**
* Limits an int to the rgba value range (0-255)
*
* @param value The value for the r, g, b, or a.
* @return An int between 0 - 255.
*/
public static int constrainValue(int value)
{
return Ints.constrainToRange(value, MIN_RGB_VALUE, MAX_RGB_VALUE);
}
/**
* Gets the Color from the passed int string.
*
* @param string The int to get a Color object from.
* @return A Color of the int of color.
*/
public static Color fromString(String string)
{
try
{
int i = Integer.decode(string);
return new Color(i, true);
}
catch (NumberFormatException e)
{
return null;
}
}
/**
* Gets the Color from the passed hex string.
*
* @param hex The hex to get a Color object from.
* @return A Color of the hex code of color.
*/
public static Color fromHex(String hex)
{
if (!hex.startsWith("#") && !hex.startsWith("0x"))
{
hex = "#" + hex;
}
if ((hex.length() <= 7 && hex.startsWith("#")) || (hex.length() <= 8 && hex.startsWith("0x")))
{
try
{
return Color.decode(hex);
}
catch (NumberFormatException e)
{
return null;
}
}
try
{
return new Color(Long.decode(hex).intValue(), true);
}
catch (NumberFormatException e)
{
return null;
}
}
/**
* Creates color from passed object hash code
*
* @param object object with hashCode
* @return color
*/
public static Color fromObject(@Nonnull final Object object)
{
int i = object.hashCode();
float h = (i % 360) / 360f;
return Color.getHSBColor(h, 1, 1);
}
}

View File

@@ -38,9 +38,9 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import javax.imageio.ImageIO;
import javax.swing.GrayFilter;
import java.util.function.Predicate;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.IndexedSprite;
@@ -56,7 +56,7 @@ public class ImageUtil
* Creates a {@link BufferedImage} from an {@link Image}.
*
* @param image An Image to be converted to a BufferedImage.
* @return A BufferedImage instance of the same given image.
* @return A BufferedImage instance of the same given image.
*/
public static BufferedImage bufferedImageFromImage(final Image image)
{
@@ -78,7 +78,7 @@ public class ImageUtil
* @param image The image to be darkened or brightened.
* @param offset A signed 8-bit integer value to brighten or darken the image with.
* Values above 0 will brighten, and values below 0 will darken.
* @return The given image with its brightness adjusted by the given offset.
* @return The given image with its brightness adjusted by the given offset.
*/
public static BufferedImage grayscaleOffset(final BufferedImage image, final int offset)
{
@@ -104,7 +104,7 @@ public class ImageUtil
* @param image The image to be darkened or brightened.
* @param percentage The ratio to darken or brighten the given image.
* Values above 1 will brighten, and values below 1 will darken.
* @return The given image with its brightness scaled by the given percentage.
* @return The given image with its brightness scaled by the given percentage.
*/
public static BufferedImage grayscaleOffset(final BufferedImage image, final float percentage)
{
@@ -130,7 +130,7 @@ public class ImageUtil
* @param offset A signed 8-bit integer value to modify the image's alpha component with.
* Values above 0 will increase transparency, and values below 0 will decrease
* transparency.
* @return The given image with its alpha component adjusted by the given offset.
* @return The given image with its alpha component adjusted by the given offset.
*/
public static BufferedImage alphaOffset(final BufferedImage image, final int offset)
{
@@ -152,7 +152,7 @@ public class ImageUtil
* @param percentage The ratio to modify the image's alpha component with.
* Values above 1 will increase transparency, and values below 1 will decrease
* transparency.
* @return The given image with its alpha component scaled by the given percentage.
* @return The given image with its alpha component scaled by the given percentage.
*/
public static BufferedImage alphaOffset(final BufferedImage image, final float percentage)
{
@@ -170,7 +170,7 @@ public class ImageUtil
* Creates a grayscale image from the given image.
*
* @param image The source image to be converted.
* @return A copy of the given imnage, with colors converted to grayscale.
* @return A copy of the given imnage, with colors converted to grayscale.
*/
public static BufferedImage grayscaleImage(final BufferedImage image)
{
@@ -181,8 +181,8 @@ public class ImageUtil
/**
* Re-size a BufferedImage to the given dimensions.
*
* @param image the BufferedImage.
* @param newWidth The width to set the BufferedImage to.
* @param image the BufferedImage.
* @param newWidth The width to set the BufferedImage to.
* @param newHeight The height to set the BufferedImage to.
* @return The BufferedImage with the specified dimensions
*/
@@ -198,7 +198,7 @@ public class ImageUtil
* @param image The image whose canvas should be re-sized.
* @param newWidth The width to set the BufferedImage to.
* @param newHeight The height to set the BufferedImage to.
* @return The BufferedImage centered within canvas of given dimensions.
* @return The BufferedImage centered within canvas of given dimensions.
*/
public static BufferedImage resizeCanvas(final BufferedImage image, final int newWidth, final int newHeight)
{
@@ -217,7 +217,7 @@ public class ImageUtil
*
* @param image The image to be rotated.
* @param theta The number of radians to rotate the image.
* @return The given image, rotated by the given theta.
* @return The given image, rotated by the given theta.
*/
public static BufferedImage rotateImage(final BufferedImage image, final double theta)
{
@@ -233,7 +233,7 @@ public class ImageUtil
* @param image The image to be flipped.
* @param horizontal Whether the image should be flipped horizontally.
* @param vertical Whether the image should be flipped vertically.
* @return The given image, flipped horizontally and/or vertically.
* @return The given image, flipped horizontally and/or vertically.
*/
public static BufferedImage flipImage(final BufferedImage image, final boolean horizontal, final boolean vertical)
{
@@ -268,7 +268,7 @@ public class ImageUtil
*
* @param image The image to be outlined.
* @param color The color to use for the outline.
* @return The BufferedImage with its edges outlined with the given color.
* @return The BufferedImage with its edges outlined with the given color.
*/
public static BufferedImage outlineImage(final BufferedImage image, final Color color)
{
@@ -282,7 +282,7 @@ public class ImageUtil
* @param image The image to be outlined.
* @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)}
* @return The BufferedImage with its edges outlined with the given color.
* @return The BufferedImage with its edges outlined with the given color.
*/
public static BufferedImage outlineImage(final BufferedImage image, final Color color, final Predicate<Color> 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<Color> 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<Color> 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.
*
* <p>
* 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)
{

View File

@@ -1,150 +1,152 @@
/*
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
* 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 <slusnucky@gmail.com>
* 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);
}
});
}
}

View File

@@ -109,8 +109,8 @@ public class MenuUtil
private static MenuEntry findOptionTarget(Stream<MenuEntry> stream, String option, String target)
{
Optional<MenuEntry> 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<MenuEntry> stream, String option, String target)
{
Optional<MenuEntry> 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);
}

View File

@@ -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;
}
}

View File

@@ -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) <stonewall@thots.cc.usa>, 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<Integer, Item> 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) <stonewall@thots.cc.usa>, 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<Integer, Item> 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()));
}
}

Some files were not shown because too many files have changed in this diff Show More