Merge branch 'master' into pr/14
This commit is contained in:
@@ -1,113 +1,113 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Singleton
|
||||
@Slf4j
|
||||
public class ClientSessionManager
|
||||
{
|
||||
private final SessionClient sessionClient = new SessionClient();
|
||||
private final ScheduledExecutorService executorService;
|
||||
|
||||
private ScheduledFuture<?> scheduledFuture;
|
||||
private UUID sessionId;
|
||||
|
||||
|
||||
@Inject
|
||||
ClientSessionManager(ScheduledExecutorService executorService)
|
||||
{
|
||||
this.executorService = executorService;
|
||||
}
|
||||
|
||||
public void start()
|
||||
{
|
||||
try
|
||||
{
|
||||
sessionId = sessionClient.open();
|
||||
log.debug("Opened session {}", sessionId);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
log.warn("error opening session", ex);
|
||||
}
|
||||
|
||||
scheduledFuture = executorService.scheduleWithFixedDelay(this::ping, 1, 10, TimeUnit.MINUTES);
|
||||
}
|
||||
|
||||
public void shutdown()
|
||||
{
|
||||
if (sessionId != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
sessionClient.delete(sessionId);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
log.warn(null, ex);
|
||||
}
|
||||
sessionId = null;
|
||||
}
|
||||
|
||||
scheduledFuture.cancel(true);
|
||||
}
|
||||
|
||||
private void ping()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (sessionId == null)
|
||||
{
|
||||
sessionId = sessionClient.open();
|
||||
log.debug("Opened session {}", sessionId);
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
log.warn(null, ex);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
sessionClient.ping(sessionId);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
log.warn("Resetting session", ex);
|
||||
sessionId = null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Singleton
|
||||
@Slf4j
|
||||
public class ClientSessionManager
|
||||
{
|
||||
private final SessionClient sessionClient = new SessionClient();
|
||||
private final ScheduledExecutorService executorService;
|
||||
|
||||
private ScheduledFuture<?> scheduledFuture;
|
||||
private UUID sessionId;
|
||||
|
||||
|
||||
@Inject
|
||||
ClientSessionManager(ScheduledExecutorService executorService)
|
||||
{
|
||||
this.executorService = executorService;
|
||||
}
|
||||
|
||||
public void start()
|
||||
{
|
||||
try
|
||||
{
|
||||
sessionId = sessionClient.open();
|
||||
log.debug("Opened session {}", sessionId);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
log.warn("error opening session", ex);
|
||||
}
|
||||
|
||||
scheduledFuture = executorService.scheduleWithFixedDelay(this::ping, 1, 10, TimeUnit.MINUTES);
|
||||
}
|
||||
|
||||
public void shutdown()
|
||||
{
|
||||
if (sessionId != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
sessionClient.delete(sessionId);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
log.warn(null, ex);
|
||||
}
|
||||
sessionId = null;
|
||||
}
|
||||
|
||||
scheduledFuture.cancel(true);
|
||||
}
|
||||
|
||||
private void ping()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (sessionId == null)
|
||||
{
|
||||
sessionId = sessionClient.open();
|
||||
log.debug("Opened session {}", sessionId);
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
log.warn(null, ex);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
sessionClient.ping(sessionId);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
log.warn("Resetting session", ex);
|
||||
sessionId = null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
*/
|
||||
package net.runelite.client;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.escape.Escaper;
|
||||
import com.google.common.escape.Escapers;
|
||||
import com.google.inject.Inject;
|
||||
@@ -101,9 +100,7 @@ public class Notifier
|
||||
this.notifyIconPath = RuneLite.RUNELITE_DIR.toPath().resolve("icon.png");
|
||||
|
||||
// First check if we are running in launcher
|
||||
this.terminalNotifierAvailable =
|
||||
!Strings.isNullOrEmpty(RuneLiteProperties.getLauncherVersion())
|
||||
&& isTerminalNotifierAvailable();
|
||||
this.terminalNotifierAvailable = true;
|
||||
|
||||
storeIcon();
|
||||
}
|
||||
@@ -328,7 +325,7 @@ public class Notifier
|
||||
{
|
||||
if (OSType.getOSType() == OSType.Linux && !Files.exists(notifyIconPath))
|
||||
{
|
||||
try (InputStream stream = Notifier.class.getResourceAsStream("/runelite.png"))
|
||||
try (InputStream stream = Notifier.class.getResourceAsStream("/runeliteplus.png"))
|
||||
{
|
||||
Files.copy(stream, notifyIconPath);
|
||||
}
|
||||
|
||||
@@ -33,11 +33,12 @@ import com.google.inject.Injector;
|
||||
import java.io.File;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.RuntimeMXBean;
|
||||
import java.net.Authenticator;
|
||||
import java.net.PasswordAuthentication;
|
||||
import java.util.Locale;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
import javax.swing.SwingUtilities;
|
||||
import joptsimple.ArgumentAcceptingOptionSpec;
|
||||
import joptsimple.OptionParser;
|
||||
import joptsimple.OptionSet;
|
||||
@@ -50,27 +51,25 @@ import net.runelite.client.chat.ChatMessageManager;
|
||||
import net.runelite.client.chat.CommandManager;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.discord.DiscordService;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.game.ClanManager;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.game.LootManager;
|
||||
import net.runelite.client.game.chatbox.ChatboxPanelManager;
|
||||
import net.runelite.client.graphics.ModelOutlineRenderer;
|
||||
import net.runelite.client.menus.MenuManager;
|
||||
import net.runelite.client.plugins.PluginManager;
|
||||
import net.runelite.client.rs.ClientLoader;
|
||||
import net.runelite.client.rs.ClientUpdateCheckMode;
|
||||
import net.runelite.client.task.Scheduler;
|
||||
import net.runelite.client.ui.ClientUI;
|
||||
import net.runelite.client.ui.DrawManager;
|
||||
import net.runelite.client.ui.FatalErrorDialog;
|
||||
import net.runelite.client.ui.SplashScreen;
|
||||
import net.runelite.client.ui.RuneLiteSplashScreen;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
import net.runelite.client.ui.overlay.OverlayRenderer;
|
||||
import net.runelite.client.ui.overlay.WidgetOverlay;
|
||||
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
|
||||
import net.runelite.client.ui.overlay.arrow.ArrowMinimapOverlay;
|
||||
import net.runelite.client.ui.overlay.arrow.ArrowWorldOverlay;
|
||||
import net.runelite.client.ui.overlay.infobox.InfoBoxOverlay;
|
||||
import net.runelite.client.ui.overlay.tooltip.TooltipOverlay;
|
||||
import net.runelite.client.ui.overlay.worldmap.WorldMapOverlay;
|
||||
import net.runelite.client.ws.PartyService;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@Singleton
|
||||
@@ -79,8 +78,11 @@ public class RuneLite
|
||||
{
|
||||
public static final File RUNELITE_DIR = new File(System.getProperty("user.home"), ".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 final File LOGS_DIR = new File(RUNELITE_DIR, "logs");
|
||||
public static boolean allowPrivateServer = false;
|
||||
public static final Locale SYSTEM_LOCALE = Locale.getDefault();
|
||||
|
||||
@Getter
|
||||
private static Injector injector;
|
||||
@@ -88,20 +90,14 @@ public class RuneLite
|
||||
@Inject
|
||||
private PluginManager pluginManager;
|
||||
|
||||
@Inject
|
||||
private EventBus eventBus;
|
||||
|
||||
@Inject
|
||||
private ConfigManager configManager;
|
||||
|
||||
@Inject
|
||||
private DrawManager drawManager;
|
||||
|
||||
@Inject
|
||||
private SessionManager sessionManager;
|
||||
|
||||
@Inject
|
||||
private DiscordService discordService;
|
||||
public DiscordService discordService;
|
||||
|
||||
@Inject
|
||||
private ClientSessionManager clientSessionManager;
|
||||
@@ -109,15 +105,9 @@ public class RuneLite
|
||||
@Inject
|
||||
private ClientUI clientUI;
|
||||
|
||||
@Inject
|
||||
private InfoBoxManager infoBoxManager;
|
||||
|
||||
@Inject
|
||||
private OverlayManager overlayManager;
|
||||
|
||||
@Inject
|
||||
private Provider<PartyService> partyService;
|
||||
|
||||
@Inject
|
||||
private Provider<ItemManager> itemManager;
|
||||
|
||||
@@ -145,6 +135,12 @@ public class RuneLite
|
||||
@Inject
|
||||
private Provider<WorldMapOverlay> worldMapOverlay;
|
||||
|
||||
@Inject
|
||||
private Provider<ArrowWorldOverlay> arrowWorldOverlay;
|
||||
|
||||
@Inject
|
||||
private Provider<ArrowMinimapOverlay> arrowMinimapOverlay;
|
||||
|
||||
@Inject
|
||||
private Provider<LootManager> lootManager;
|
||||
|
||||
@@ -155,6 +151,12 @@ public class RuneLite
|
||||
@Nullable
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private Provider<ModelOutlineRenderer> modelOutlineRenderer;
|
||||
|
||||
@Inject
|
||||
private Scheduler scheduler;
|
||||
|
||||
public static void main(String[] args) throws Exception
|
||||
{
|
||||
Locale.setDefault(Locale.ENGLISH);
|
||||
@@ -162,6 +164,10 @@ public class RuneLite
|
||||
final OptionParser parser = new OptionParser();
|
||||
parser.accepts("developer-mode", "Enable developer tools");
|
||||
parser.accepts("debug", "Show extra debugging output");
|
||||
parser.accepts("no-splash", "Do not show the splash screen");
|
||||
final ArgumentAcceptingOptionSpec<String> proxyInfo = parser
|
||||
.accepts("proxy")
|
||||
.withRequiredArg().ofType(String.class);
|
||||
|
||||
final ArgumentAcceptingOptionSpec<ClientUpdateCheckMode> updateMode = parser
|
||||
.accepts("rs", "Select client type")
|
||||
@@ -180,12 +186,63 @@ public class RuneLite
|
||||
parser.accepts("help", "Show this text").forHelp();
|
||||
OptionSet options = parser.parse(args);
|
||||
|
||||
if (options.has("proxy"))
|
||||
{
|
||||
String[] proxy = options.valueOf(proxyInfo).split(":");
|
||||
|
||||
if (proxy.length >= 2)
|
||||
{
|
||||
System.setProperty("socksProxyHost", proxy[0]);
|
||||
System.setProperty("socksProxyPort", proxy[1]);
|
||||
}
|
||||
|
||||
if (proxy.length >= 4)
|
||||
{
|
||||
System.setProperty("java.net.socks.username", proxy[2]);
|
||||
System.setProperty("java.net.socks.password", proxy[3]);
|
||||
|
||||
final String user = proxy[2];
|
||||
final char[] pass = proxy[3].toCharArray();
|
||||
|
||||
Authenticator.setDefault(new Authenticator()
|
||||
{
|
||||
private PasswordAuthentication auth = new PasswordAuthentication(user, pass);
|
||||
|
||||
protected PasswordAuthentication getPasswordAuthentication()
|
||||
{
|
||||
return auth;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (options.has("help"))
|
||||
{
|
||||
parser.printHelpOn(System.out);
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
final boolean developerMode = options.has("developer-mode");
|
||||
|
||||
if (developerMode)
|
||||
{
|
||||
boolean assertions = false;
|
||||
assert assertions = true;
|
||||
if (!assertions)
|
||||
{
|
||||
java.util.logging.Logger.getAnonymousLogger().warning("Developers should enable assertions; Add `-ea` to your JVM arguments`");
|
||||
}
|
||||
}
|
||||
|
||||
if (!options.has("no-splash"))
|
||||
{
|
||||
RuneLiteSplashScreen.init();
|
||||
}
|
||||
|
||||
RuneLiteSplashScreen.stage(0, "Initializing client");
|
||||
|
||||
PROFILES_DIR.mkdirs();
|
||||
|
||||
if (options.has("debug"))
|
||||
{
|
||||
final Logger logger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
|
||||
@@ -197,65 +254,24 @@ public class RuneLite
|
||||
log.error("Uncaught exception:", throwable);
|
||||
if (throwable instanceof AbstractMethodError)
|
||||
{
|
||||
log.error("Classes are out of date; Build with maven again.");
|
||||
log.error("Classes are out of date; Build with Gradle again.");
|
||||
}
|
||||
});
|
||||
|
||||
SplashScreen.init();
|
||||
SplashScreen.stage(0, "Retrieving client", "");
|
||||
|
||||
try
|
||||
{
|
||||
final ClientLoader clientLoader = new ClientLoader(options.valueOf(updateMode));
|
||||
RuneLiteSplashScreen.stage(.2, "Starting RuneLitePlus injector");
|
||||
|
||||
new Thread(() ->
|
||||
{
|
||||
clientLoader.get();
|
||||
ClassPreloader.preload();
|
||||
}, "Preloader").start();
|
||||
final long start = System.currentTimeMillis();
|
||||
|
||||
final boolean developerMode = options.has("developer-mode") && RuneLiteProperties.getLauncherVersion() == null;
|
||||
injector = Guice.createInjector(new RuneLiteModule(
|
||||
options.valueOf(updateMode),
|
||||
true));
|
||||
|
||||
if (developerMode)
|
||||
{
|
||||
boolean assertions = false;
|
||||
assert assertions = true;
|
||||
if (!assertions)
|
||||
{
|
||||
SwingUtilities.invokeLater(() ->
|
||||
new FatalErrorDialog("Developers should enable assertions; Add `-ea` to your JVM arguments`")
|
||||
.addBuildingGuide()
|
||||
.open());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
PROFILES_DIR.mkdirs();
|
||||
|
||||
final long start = System.currentTimeMillis();
|
||||
|
||||
injector = Guice.createInjector(new RuneLiteModule(
|
||||
clientLoader,
|
||||
developerMode));
|
||||
|
||||
injector.getInstance(RuneLite.class).start();
|
||||
|
||||
final long end = System.currentTimeMillis();
|
||||
final RuntimeMXBean rb = ManagementFactory.getRuntimeMXBean();
|
||||
final long uptime = rb.getUptime();
|
||||
log.info("Client initialization took {}ms. Uptime: {}ms", end - start, uptime);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.warn("Failure during startup", e);
|
||||
SwingUtilities.invokeLater(() ->
|
||||
new FatalErrorDialog("RuneLite has encountered an unexpected error during startup.")
|
||||
.open());
|
||||
}
|
||||
finally
|
||||
{
|
||||
SplashScreen.stop();
|
||||
}
|
||||
injector.getInstance(RuneLite.class).start();
|
||||
final long end = System.currentTimeMillis();
|
||||
final RuntimeMXBean rb = ManagementFactory.getRuntimeMXBean();
|
||||
final long uptime = rb.getUptime();
|
||||
log.info("Client initialization took {}ms. Uptime: {}ms", end - start, uptime);
|
||||
}
|
||||
|
||||
public void start() throws Exception
|
||||
@@ -269,13 +285,17 @@ public class RuneLite
|
||||
injector.injectMembers(client);
|
||||
}
|
||||
|
||||
SplashScreen.stage(.57, null, "Loading configuration");
|
||||
|
||||
// Load user configuration
|
||||
|
||||
RuneLiteSplashScreen.stage(.57, "Loading user config");
|
||||
configManager.load();
|
||||
|
||||
// Load the session, including saved configuration
|
||||
sessionManager.loadSession();
|
||||
RuneLiteSplashScreen.stage(.58, "Loading session data");
|
||||
|
||||
// Begin watching for new plugins
|
||||
pluginManager.watch();
|
||||
|
||||
// Tell the plugin manager if client is outdated or not
|
||||
pluginManager.setOutdated(isOutdated);
|
||||
@@ -283,57 +303,55 @@ public class RuneLite
|
||||
// Load the plugins, but does not start them yet.
|
||||
// This will initialize configuration
|
||||
pluginManager.loadCorePlugins();
|
||||
|
||||
SplashScreen.stage(.70, null, "Finalizing configuration");
|
||||
RuneLiteSplashScreen.stage(.70, "Finalizing configuration");
|
||||
|
||||
// Plugins have provided their config, so set default config
|
||||
// to main settings
|
||||
pluginManager.loadDefaultPluginConfiguration();
|
||||
|
||||
// Start client session
|
||||
RuneLiteSplashScreen.stage(.80, "Starting core interface");
|
||||
clientSessionManager.start();
|
||||
|
||||
SplashScreen.stage(.75, null, "Starting core interface");
|
||||
|
||||
// Initialize UI
|
||||
clientUI.init(this);
|
||||
|
||||
// Initialize Discord service
|
||||
discordService.init();
|
||||
|
||||
// Register event listeners
|
||||
eventBus.register(clientUI);
|
||||
eventBus.register(pluginManager);
|
||||
eventBus.register(overlayManager);
|
||||
eventBus.register(drawManager);
|
||||
eventBus.register(infoBoxManager);
|
||||
|
||||
if (!isOutdated)
|
||||
{
|
||||
// Initialize chat colors
|
||||
chatMessageManager.get().loadColors();
|
||||
|
||||
eventBus.register(partyService.get());
|
||||
eventBus.register(overlayRenderer.get());
|
||||
eventBus.register(clanManager.get());
|
||||
eventBus.register(itemManager.get());
|
||||
eventBus.register(menuManager.get());
|
||||
eventBus.register(chatMessageManager.get());
|
||||
eventBus.register(commandManager.get());
|
||||
eventBus.register(lootManager.get());
|
||||
eventBus.register(chatboxPanelManager.get());
|
||||
overlayRenderer.get();
|
||||
clanManager.get();
|
||||
itemManager.get();
|
||||
menuManager.get();
|
||||
chatMessageManager.get();
|
||||
commandManager.get();
|
||||
lootManager.get();
|
||||
chatboxPanelManager.get();
|
||||
|
||||
// Add core overlays
|
||||
WidgetOverlay.createOverlays(client).forEach(overlayManager::add);
|
||||
overlayManager.add(infoBoxOverlay.get());
|
||||
overlayManager.add(worldMapOverlay.get());
|
||||
overlayManager.add(tooltipOverlay.get());
|
||||
overlayManager.add(arrowWorldOverlay.get());
|
||||
overlayManager.add(arrowMinimapOverlay.get());
|
||||
}
|
||||
|
||||
// Start plugins
|
||||
pluginManager.startCorePlugins();
|
||||
|
||||
SplashScreen.stop();
|
||||
discordService.init();
|
||||
|
||||
// Register additional schedulers
|
||||
if (this.client != null)
|
||||
{
|
||||
scheduler.registerObject(modelOutlineRenderer.get());
|
||||
}
|
||||
|
||||
// Close the splash screen
|
||||
RuneLiteSplashScreen.close();
|
||||
|
||||
clientUI.show();
|
||||
}
|
||||
@@ -350,4 +368,4 @@ public class RuneLite
|
||||
{
|
||||
RuneLite.injector = injector;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,6 @@ import com.google.inject.name.Names;
|
||||
import java.applet.Applet;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.function.Supplier;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Singleton;
|
||||
import net.runelite.api.Client;
|
||||
@@ -41,10 +40,13 @@ import net.runelite.client.chat.ChatMessageManager;
|
||||
import net.runelite.client.config.ChatColorConfig;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.config.RuneLiteConfig;
|
||||
import net.runelite.client.config.RuneLitePlusConfig;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.menus.MenuManager;
|
||||
import net.runelite.client.plugins.PluginManager;
|
||||
import net.runelite.client.rs.ClientLoader;
|
||||
import net.runelite.client.rs.ClientUpdateCheckMode;
|
||||
import net.runelite.client.task.Scheduler;
|
||||
import net.runelite.client.util.DeferredEventBus;
|
||||
import net.runelite.client.util.ExecutorServiceExceptionLogger;
|
||||
@@ -55,18 +57,19 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
public class RuneLiteModule extends AbstractModule
|
||||
{
|
||||
private final Supplier<Applet> clientLoader;
|
||||
private final ClientUpdateCheckMode updateCheckMode;
|
||||
private final boolean developerMode;
|
||||
|
||||
public RuneLiteModule(Supplier<Applet> clientLoader, boolean developerMode)
|
||||
public RuneLiteModule(final ClientUpdateCheckMode updateCheckMode, final boolean developerMode)
|
||||
{
|
||||
this.clientLoader = clientLoader;
|
||||
this.updateCheckMode = updateCheckMode;
|
||||
this.developerMode = developerMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure()
|
||||
{
|
||||
bindConstant().annotatedWith(Names.named("updateCheckMode")).to(updateCheckMode);
|
||||
bindConstant().annotatedWith(Names.named("developerMode")).to(developerMode);
|
||||
bind(ScheduledExecutorService.class).toInstance(new ExecutorServiceExceptionLogger(Executors.newSingleThreadScheduledExecutor()));
|
||||
bind(OkHttpClient.class).toInstance(RuneLiteAPI.CLIENT);
|
||||
@@ -75,6 +78,7 @@ public class RuneLiteModule extends AbstractModule
|
||||
bind(ItemManager.class);
|
||||
bind(Scheduler.class);
|
||||
bind(PluginManager.class);
|
||||
bind(RuneLiteProperties.class);
|
||||
bind(SessionManager.class);
|
||||
|
||||
bind(Callbacks.class).to(Hooks.class);
|
||||
@@ -93,9 +97,9 @@ public class RuneLiteModule extends AbstractModule
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
Applet provideApplet()
|
||||
Applet provideApplet(ClientLoader clientLoader)
|
||||
{
|
||||
return clientLoader.get();
|
||||
return clientLoader.load();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@@ -112,6 +116,13 @@ public class RuneLiteModule extends AbstractModule
|
||||
return configManager.getConfig(RuneLiteConfig.class);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
RuneLitePlusConfig providePlusConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(RuneLitePlusConfig.class);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
ChatColorConfig provideChatColorConfig(ConfigManager configManager)
|
||||
|
||||
@@ -24,17 +24,20 @@
|
||||
*/
|
||||
package net.runelite.client;
|
||||
|
||||
import com.google.inject.Singleton;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Properties;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@Singleton
|
||||
public class RuneLiteProperties
|
||||
{
|
||||
private static final String RUNELITE_TITLE = "runelite.title";
|
||||
private static final String RUNELITE_TITLE = "runelite.plus.title";
|
||||
private static final String RUNELITE_VERSION = "runelite.version";
|
||||
private static final String RUNELITE_PLUS_VERSION = "runelite.plus.version";
|
||||
private static final String RUNELITE_PLUS_DATE = "runelite.plus.builddate";
|
||||
private static final String RUNESCAPE_VERSION = "runescape.version";
|
||||
private static final String DISCORD_APP_ID = "runelite.discord.appid";
|
||||
private static final String DISCORD_APP_ID = "runelite.plus.discord.appid";
|
||||
private static final String DISCORD_INVITE = "runelite.discord.invite";
|
||||
private static final String GITHUB_LINK = "runelite.github.link";
|
||||
private static final String WIKI_LINK = "runelite.wiki.link";
|
||||
@@ -48,7 +51,7 @@ public class RuneLiteProperties
|
||||
|
||||
static
|
||||
{
|
||||
try (InputStream in = RuneLiteProperties.class.getResourceAsStream("runelite.properties"))
|
||||
try (InputStream in = RuneLiteProperties.class.getResourceAsStream("/runelite.plus.properties"))
|
||||
{
|
||||
properties.load(in);
|
||||
}
|
||||
@@ -60,7 +63,13 @@ public class RuneLiteProperties
|
||||
|
||||
public static String getTitle()
|
||||
{
|
||||
return properties.getProperty(RUNELITE_TITLE);
|
||||
final StringBuilder sb = new StringBuilder(properties.getProperty(RUNELITE_TITLE));
|
||||
String proxy;
|
||||
if ((proxy = System.getProperty("socksProxyHost")) != null)
|
||||
{
|
||||
sb.append(String.format(" (%s)", proxy));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String getVersion()
|
||||
@@ -68,6 +77,16 @@ public class RuneLiteProperties
|
||||
return properties.getProperty(RUNELITE_VERSION);
|
||||
}
|
||||
|
||||
public static String getPlusVersion()
|
||||
{
|
||||
return properties.getProperty(RUNELITE_PLUS_VERSION);
|
||||
}
|
||||
|
||||
public static String getPlusDate()
|
||||
{
|
||||
return properties.getProperty(RUNELITE_PLUS_DATE);
|
||||
}
|
||||
|
||||
public static String getRunescapeVersion()
|
||||
{
|
||||
return properties.getProperty(RUNESCAPE_VERSION);
|
||||
@@ -98,12 +117,6 @@ public class RuneLiteProperties
|
||||
return properties.getProperty(PATREON_LINK);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getLauncherVersion()
|
||||
{
|
||||
return System.getProperty(LAUNCHER_VERSION_PROPERTY);
|
||||
}
|
||||
|
||||
public static String getTroubleshootingLink()
|
||||
{
|
||||
return properties.getProperty(TROUBLESHOOTING_LINK);
|
||||
|
||||
@@ -1,95 +1,95 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.google.gson.JsonParseException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.UUID;
|
||||
import net.runelite.http.api.RuneLiteAPI;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
|
||||
class SessionClient
|
||||
{
|
||||
UUID open() throws IOException
|
||||
{
|
||||
HttpUrl url = RuneLiteAPI.getSessionBase().newBuilder()
|
||||
.build();
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.url(url)
|
||||
.build();
|
||||
|
||||
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);
|
||||
}
|
||||
catch (JsonParseException | IllegalArgumentException ex) // UUID.fromString can throw IllegalArgumentException
|
||||
{
|
||||
throw new IOException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
void ping(UUID uuid) throws IOException
|
||||
{
|
||||
HttpUrl url = RuneLiteAPI.getSessionBase().newBuilder()
|
||||
.addPathSegment("ping")
|
||||
.addQueryParameter("session", uuid.toString())
|
||||
.build();
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.url(url)
|
||||
.build();
|
||||
|
||||
try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute())
|
||||
{
|
||||
if (!response.isSuccessful())
|
||||
{
|
||||
throw new IOException("Unsuccessful ping");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void delete(UUID uuid) throws IOException
|
||||
{
|
||||
HttpUrl url = RuneLiteAPI.getSessionBase().newBuilder()
|
||||
.addQueryParameter("session", uuid.toString())
|
||||
.build();
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.delete()
|
||||
.url(url)
|
||||
.build();
|
||||
|
||||
RuneLiteAPI.CLIENT.newCall(request).execute().close();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.google.gson.JsonParseException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.UUID;
|
||||
import net.runelite.http.api.RuneLiteAPI;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
|
||||
class SessionClient
|
||||
{
|
||||
UUID open() throws IOException
|
||||
{
|
||||
HttpUrl url = RuneLiteAPI.getRuneLitePlusSessionBase().newBuilder()
|
||||
.build();
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.url(url)
|
||||
.build();
|
||||
|
||||
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);
|
||||
}
|
||||
catch (JsonParseException | IllegalArgumentException ex) // UUID.fromString can throw IllegalArgumentException
|
||||
{
|
||||
throw new IOException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
void ping(UUID uuid) throws IOException
|
||||
{
|
||||
HttpUrl url = RuneLiteAPI.getRuneLitePlusSessionBase().newBuilder()
|
||||
.addPathSegment("ping")
|
||||
.addQueryParameter("session", uuid.toString())
|
||||
.build();
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.url(url)
|
||||
.build();
|
||||
|
||||
try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute())
|
||||
{
|
||||
if (!response.isSuccessful())
|
||||
{
|
||||
throw new IOException("Unsuccessful ping");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void delete(UUID uuid) throws IOException
|
||||
{
|
||||
HttpUrl url = RuneLiteAPI.getRuneLitePlusSessionBase().newBuilder()
|
||||
.addQueryParameter("session", uuid.toString())
|
||||
.build();
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.delete()
|
||||
.url(url)
|
||||
.build();
|
||||
|
||||
RuneLiteAPI.CLIENT.newCall(request).execute().close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,12 +36,11 @@ 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.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;
|
||||
@@ -67,7 +66,8 @@ public class SessionManager
|
||||
this.configManager = configManager;
|
||||
this.eventBus = eventBus;
|
||||
this.wsClient = wsClient;
|
||||
eventBus.register(this);
|
||||
|
||||
this.eventBus.subscribe(LoginResponse.class, this, this::onLoginResponse);
|
||||
}
|
||||
|
||||
public void loadSession()
|
||||
@@ -147,10 +147,10 @@ public class SessionManager
|
||||
{
|
||||
// Initialize config for new session
|
||||
// If the session isn't logged in yet, don't switch to the new config
|
||||
configManager.switchSession(session);
|
||||
configManager.switchSession();
|
||||
}
|
||||
|
||||
eventBus.post(new SessionOpen());
|
||||
eventBus.post(SessionOpen.class, new SessionOpen());
|
||||
}
|
||||
|
||||
private void closeSession()
|
||||
@@ -177,9 +177,9 @@ public class SessionManager
|
||||
accountSession = null; // No more account
|
||||
|
||||
// Restore config
|
||||
configManager.switchSession(null);
|
||||
configManager.switchSession();
|
||||
|
||||
eventBus.post(new SessionClose());
|
||||
eventBus.post(SessionClose.class, new SessionClose());
|
||||
}
|
||||
|
||||
public void login()
|
||||
@@ -207,8 +207,7 @@ public class SessionManager
|
||||
LinkBrowser.browse(login.getOauthUrl());
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onLoginResponse(LoginResponse loginResponse)
|
||||
private void onLoginResponse(LoginResponse loginResponse)
|
||||
{
|
||||
log.debug("Now logged in as {}", loginResponse.getUsername());
|
||||
|
||||
|
||||
@@ -27,16 +27,18 @@ package net.runelite.client.callback;
|
||||
import com.google.inject.Inject;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import javax.inject.Singleton;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@Singleton
|
||||
@Slf4j
|
||||
public class ClientThread
|
||||
public class ClientThread implements Executor
|
||||
{
|
||||
private ConcurrentLinkedQueue<BooleanSupplier> invokes = new ConcurrentLinkedQueue<>();
|
||||
private final ConcurrentLinkedQueue<BooleanSupplier> invokes = new ConcurrentLinkedQueue<>();
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
@@ -112,4 +114,14 @@ public class ClientThread
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(@NotNull Runnable r)
|
||||
{
|
||||
invoke(() ->
|
||||
{
|
||||
r.run();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,13 +43,14 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.BufferProvider;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Constants;
|
||||
import net.runelite.api.Entity;
|
||||
import net.runelite.api.MainBufferProvider;
|
||||
import net.runelite.api.NullItemID;
|
||||
import net.runelite.api.RenderOverview;
|
||||
import net.runelite.api.Renderable;
|
||||
import net.runelite.api.WorldMapManager;
|
||||
import net.runelite.api.events.BeforeMenuRender;
|
||||
import net.runelite.api.events.BeforeRender;
|
||||
import net.runelite.api.events.Event;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.hooks.Callbacks;
|
||||
import net.runelite.api.hooks.DrawCallbacks;
|
||||
@@ -87,9 +88,6 @@ public class Hooks implements Callbacks
|
||||
private static final OverlayRenderer renderer = injector.getInstance(OverlayRenderer.class);
|
||||
private static final OverlayManager overlayManager = injector.getInstance(OverlayManager.class);
|
||||
|
||||
private static final GameTick GAME_TICK = new GameTick();
|
||||
private static final BeforeRender BEFORE_RENDER = new BeforeRender();
|
||||
|
||||
@Inject
|
||||
private EventBus eventBus;
|
||||
|
||||
@@ -156,15 +154,15 @@ public class Hooks implements Callbacks
|
||||
}
|
||||
|
||||
@Override
|
||||
public void post(Object event)
|
||||
public <T> void post(Class<T> eventClass, Event event)
|
||||
{
|
||||
eventBus.post(event);
|
||||
eventBus.post(eventClass, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postDeferred(Object event)
|
||||
public <T> void postDeferred(Class<T> eventClass, Event event)
|
||||
{
|
||||
deferredEventBus.post(event);
|
||||
deferredEventBus.post(eventClass, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -176,13 +174,13 @@ public class Hooks implements Callbacks
|
||||
|
||||
deferredEventBus.replay();
|
||||
|
||||
eventBus.post(GAME_TICK);
|
||||
eventBus.post(GameTick.class, GameTick.INSTANCE);
|
||||
|
||||
int tick = client.getTickCount();
|
||||
client.setTickCount(tick + 1);
|
||||
}
|
||||
|
||||
eventBus.post(BEFORE_RENDER);
|
||||
eventBus.post(BeforeRender.class, BeforeRender.INSTANCE);
|
||||
|
||||
clientThread.invoke();
|
||||
|
||||
@@ -397,8 +395,6 @@ public class Hooks implements Callbacks
|
||||
|
||||
/**
|
||||
* Copy an image
|
||||
* @param src
|
||||
* @return
|
||||
*/
|
||||
private static Image copy(Image src)
|
||||
{
|
||||
@@ -477,16 +473,16 @@ public class Hooks implements Callbacks
|
||||
deferredEventBus.replay();
|
||||
}
|
||||
|
||||
public static void renderDraw(Renderable renderable, int orientation, int pitchSin, int pitchCos, int yawSin, int yawCos, int x, int y, int z, long hash)
|
||||
public static void renderDraw(Entity entity, int orientation, int pitchSin, int pitchCos, int yawSin, int yawCos, int x, int y, int z, long hash)
|
||||
{
|
||||
DrawCallbacks drawCallbacks = client.getDrawCallbacks();
|
||||
if (drawCallbacks != null)
|
||||
{
|
||||
drawCallbacks.draw(renderable, orientation, pitchSin, pitchCos, yawSin, yawCos, x, y, z, hash);
|
||||
drawCallbacks.draw(entity, orientation, pitchSin, pitchCos, yawSin, yawCos, x, y, z, hash);
|
||||
}
|
||||
else
|
||||
{
|
||||
renderable.draw(orientation, pitchSin, pitchCos, yawSin, yawCos, x, y, z, hash);
|
||||
entity.draw(orientation, pitchSin, pitchCos, yawSin, yawCos, x, y, z, hash);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -522,7 +518,7 @@ public class Hooks implements Callbacks
|
||||
public static boolean drawMenu()
|
||||
{
|
||||
BeforeMenuRender event = new BeforeMenuRender();
|
||||
client.getCallbacks().post(event);
|
||||
client.getCallbacks().post(BeforeMenuRender.class, event);
|
||||
return event.isConsumed();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@ import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.events.ChatInput;
|
||||
import net.runelite.client.events.ChatboxInput;
|
||||
import net.runelite.client.events.PrivateMessageInput;
|
||||
@@ -53,8 +52,10 @@ public class ChatCommandManager implements ChatboxInputListener
|
||||
{
|
||||
this.client = client;
|
||||
this.scheduledExecutorService = scheduledExecutorService;
|
||||
eventBus.register(this);
|
||||
// eventBus.register(this);
|
||||
commandManager.register(this);
|
||||
|
||||
eventBus.subscribe(ChatMessage.class, this, this::onChatMessage);
|
||||
}
|
||||
|
||||
public void registerCommand(String command, BiConsumer<ChatMessage, String> execute)
|
||||
@@ -82,8 +83,7 @@ public class ChatCommandManager implements ChatboxInputListener
|
||||
commands.remove(command.toLowerCase());
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onChatMessage(ChatMessage chatMessage)
|
||||
private void onChatMessage(ChatMessage chatMessage)
|
||||
{
|
||||
if (client.getGameState() != GameState.LOGGED_IN)
|
||||
{
|
||||
|
||||
@@ -52,7 +52,7 @@ import net.runelite.api.events.ScriptCallbackEvent;
|
||||
import net.runelite.api.events.VarbitChanged;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.config.ChatColorConfig;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.ui.JagexColors;
|
||||
import net.runelite.client.util.ColorUtil;
|
||||
|
||||
@@ -70,17 +70,23 @@ public class ChatMessageManager
|
||||
|
||||
@Inject
|
||||
private ChatMessageManager(
|
||||
Client client,
|
||||
ChatColorConfig chatColorConfig,
|
||||
ClientThread clientThread)
|
||||
final Client client,
|
||||
final ChatColorConfig chatColorConfig,
|
||||
final ClientThread clientThread,
|
||||
final EventBus eventbus)
|
||||
{
|
||||
this.client = client;
|
||||
this.chatColorConfig = chatColorConfig;
|
||||
this.clientThread = clientThread;
|
||||
|
||||
eventbus.subscribe(VarbitChanged.class, this, this::onVarbitChanged);
|
||||
eventbus.subscribe(ResizeableChanged.class, this, this::onResizeableChanged);
|
||||
eventbus.subscribe(ConfigChanged.class, this, this::onConfigChanged);
|
||||
eventbus.subscribe(ChatMessage.class, this, this::onChatMessage);
|
||||
eventbus.subscribe(ScriptCallbackEvent.class, this, this::onScriptCallbackEvent);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onVarbitChanged(VarbitChanged event)
|
||||
private void onVarbitChanged(VarbitChanged event)
|
||||
{
|
||||
int setting = client.getVar(Varbits.TRANSPARENT_CHATBOX);
|
||||
|
||||
@@ -91,14 +97,12 @@ public class ChatMessageManager
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onResizeableChanged(ResizeableChanged event)
|
||||
private void onResizeableChanged(ResizeableChanged event)
|
||||
{
|
||||
refreshAll();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onConfigChanged(ConfigChanged event)
|
||||
private void onConfigChanged(ConfigChanged event)
|
||||
{
|
||||
if (event.getGroup().equals("textrecolor"))
|
||||
{
|
||||
@@ -107,15 +111,14 @@ public class ChatMessageManager
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onChatMessage(ChatMessage chatMessage)
|
||||
private void onChatMessage(ChatMessage chatMessage)
|
||||
{
|
||||
MessageNode messageNode = chatMessage.getMessageNode();
|
||||
ChatMessageType chatMessageType = chatMessage.getType();
|
||||
|
||||
boolean isChatboxTransparent = client.isResized() && client.getVar(Varbits.TRANSPARENT_CHATBOX) == 1;
|
||||
Color usernameColor = null;
|
||||
Color senderColor = null;
|
||||
Color senderColor;
|
||||
|
||||
switch (chatMessageType)
|
||||
{
|
||||
@@ -173,8 +176,7 @@ public class ChatMessageManager
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onScriptCallbackEvent(ScriptCallbackEvent scriptCallbackEvent)
|
||||
private void onScriptCallbackEvent(ScriptCallbackEvent scriptCallbackEvent)
|
||||
{
|
||||
final String eventName = scriptCallbackEvent.getEventName();
|
||||
|
||||
@@ -568,6 +570,12 @@ public class ChatMessageManager
|
||||
return;
|
||||
}
|
||||
|
||||
//guard case for google MoreObjects#firstNonNull
|
||||
if (message.getValue() == null && message.getRuneLiteFormattedMessage() == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// this updates chat cycle
|
||||
client.addChatMessage(
|
||||
message.getType(),
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
/*
|
||||
* 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.chat;
|
||||
|
||||
import net.runelite.client.events.ChatboxInput;
|
||||
import net.runelite.client.events.PrivateMessageInput;
|
||||
|
||||
public interface ChatboxInputListener
|
||||
{
|
||||
boolean onChatboxInput(ChatboxInput chatboxInput);
|
||||
|
||||
boolean onPrivateMessageInput(PrivateMessageInput privateMessageInput);
|
||||
}
|
||||
/*
|
||||
* 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.chat;
|
||||
|
||||
import net.runelite.client.events.ChatboxInput;
|
||||
import net.runelite.client.events.PrivateMessageInput;
|
||||
|
||||
public interface ChatboxInputListener
|
||||
{
|
||||
boolean onChatboxInput(ChatboxInput chatboxInput);
|
||||
|
||||
boolean onPrivateMessageInput(PrivateMessageInput privateMessageInput);
|
||||
}
|
||||
|
||||
@@ -38,7 +38,6 @@ import net.runelite.api.events.CommandExecuted;
|
||||
import net.runelite.api.events.ScriptCallbackEvent;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.events.ChatboxInput;
|
||||
import net.runelite.client.events.PrivateMessageInput;
|
||||
|
||||
@@ -58,11 +57,17 @@ public class CommandManager
|
||||
private final List<ChatboxInputListener> chatboxInputListenerList = new ArrayList<>();
|
||||
|
||||
@Inject
|
||||
private CommandManager(Client client, EventBus eventBus, ClientThread clientThread)
|
||||
private CommandManager(
|
||||
final Client client,
|
||||
final EventBus eventBus,
|
||||
final ClientThread clientThread
|
||||
)
|
||||
{
|
||||
this.client = client;
|
||||
this.eventBus = eventBus;
|
||||
this.clientThread = clientThread;
|
||||
|
||||
eventBus.subscribe(ScriptCallbackEvent.class, this, this::onScriptCallbackEvent);
|
||||
}
|
||||
|
||||
public void register(ChatboxInputListener chatboxInputListener)
|
||||
@@ -75,7 +80,6 @@ public class CommandManager
|
||||
chatboxInputListenerList.remove(chatboxInputListener);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
private void onScriptCallbackEvent(ScriptCallbackEvent event)
|
||||
{
|
||||
if (sending)
|
||||
@@ -115,7 +119,7 @@ public class CommandManager
|
||||
String[] args = Arrays.copyOfRange(split, 1, split.length);
|
||||
|
||||
CommandExecuted commandExecuted = new CommandExecuted(command, args);
|
||||
eventBus.post(commandExecuted);
|
||||
eventBus.post(CommandExecuted.class, commandExecuted);
|
||||
}
|
||||
|
||||
private void handleInput(ScriptCallbackEvent event)
|
||||
|
||||
@@ -24,17 +24,18 @@
|
||||
*/
|
||||
package net.runelite.client.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
public class ConfigDescriptor
|
||||
{
|
||||
private final ConfigGroup group;
|
||||
private final Collection<ConfigItemDescriptor> items;
|
||||
private final Collection<ConfigItemsGroup> itemGroups;
|
||||
|
||||
public ConfigDescriptor(ConfigGroup group, Collection<ConfigItemDescriptor> items)
|
||||
public ConfigDescriptor(ConfigGroup group, Collection<ConfigItemsGroup> itemGroups)
|
||||
{
|
||||
this.group = group;
|
||||
this.items = items;
|
||||
this.itemGroups = itemGroups;
|
||||
}
|
||||
|
||||
public ConfigGroup getGroup()
|
||||
@@ -42,8 +43,19 @@ public class ConfigDescriptor
|
||||
return group;
|
||||
}
|
||||
|
||||
public Collection<ConfigItemsGroup> getItemGroups()
|
||||
{
|
||||
return itemGroups;
|
||||
}
|
||||
|
||||
public Collection<ConfigItemDescriptor> getItems()
|
||||
{
|
||||
return items;
|
||||
Collection<ConfigItemDescriptor> allItems = new ArrayList<>();
|
||||
for (ConfigItemsGroup g : itemGroups)
|
||||
{
|
||||
allItems.addAll(g.getItems());
|
||||
}
|
||||
return allItems;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,56 +24,63 @@
|
||||
*/
|
||||
package net.runelite.client.config;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
class ConfigInvocationHandler implements InvocationHandler
|
||||
{
|
||||
// Special object to represent null values in the cache
|
||||
private static final Object NULL = new Object();
|
||||
|
||||
private final ConfigManager manager;
|
||||
private final Cache<Method, Object> cache = CacheBuilder.newBuilder()
|
||||
.maximumSize(128)
|
||||
.build();
|
||||
|
||||
ConfigInvocationHandler(ConfigManager manager)
|
||||
// Caches for annotation values
|
||||
private static final Map<Class<?>, String> groupValueCache = new HashMap<>();
|
||||
private static final Map<Method, String> methodKeyNameCache = new HashMap<>();
|
||||
|
||||
public ConfigInvocationHandler(ConfigManager manager)
|
||||
{
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
private static String groupValueFromProxy(Class<?> proxyClass)
|
||||
{
|
||||
Class<?> iface = proxyClass.getInterfaces()[0];
|
||||
ConfigGroup group = iface.getAnnotation(ConfigGroup.class);
|
||||
|
||||
return group == null ? null : group.value();
|
||||
}
|
||||
|
||||
private static String keyNameFromMethod(Method method)
|
||||
{
|
||||
ConfigItem item = method.getAnnotation(ConfigItem.class);
|
||||
|
||||
return item == null ? null : item.keyName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
|
||||
{
|
||||
// Use cached configuration value if available
|
||||
if (args == null)
|
||||
String itemKeyName, groupValue;
|
||||
try
|
||||
{
|
||||
Object cachedValue = cache.getIfPresent(method);
|
||||
if (cachedValue != null)
|
||||
{
|
||||
return cachedValue == NULL ? null : cachedValue;
|
||||
}
|
||||
groupValue = groupValueCache.computeIfAbsent(proxy.getClass(), ConfigInvocationHandler::groupValueFromProxy);
|
||||
}
|
||||
|
||||
Class<?> iface = proxy.getClass().getInterfaces()[0];
|
||||
|
||||
ConfigGroup group = iface.getAnnotation(ConfigGroup.class);
|
||||
ConfigItem item = method.getAnnotation(ConfigItem.class);
|
||||
|
||||
if (group == null)
|
||||
catch (NullPointerException e)
|
||||
{
|
||||
log.warn("Configuration proxy class {} has no @ConfigGroup!", proxy.getClass());
|
||||
return null;
|
||||
}
|
||||
|
||||
if (item == null)
|
||||
try
|
||||
{
|
||||
itemKeyName = methodKeyNameCache.computeIfAbsent(method, ConfigInvocationHandler::keyNameFromMethod);
|
||||
}
|
||||
catch (NullPointerException e)
|
||||
{
|
||||
log.warn("Configuration method {} has no @ConfigItem!", method);
|
||||
return null;
|
||||
@@ -81,42 +88,44 @@ class ConfigInvocationHandler implements InvocationHandler
|
||||
|
||||
if (args == null)
|
||||
{
|
||||
log.trace("cache miss (size: {}, group: {}, key: {})", cache.size(), group.value(), item.keyName());
|
||||
|
||||
// Getting configuration item
|
||||
String value = manager.getConfiguration(group.value(), item.keyName());
|
||||
|
||||
if (value == null)
|
||||
return manager.getConfigObjectFromCacheOrElse(groupValue, itemKeyName, (value) ->
|
||||
{
|
||||
if (method.isDefault())
|
||||
try
|
||||
{
|
||||
Object defaultValue = callDefaultMethod(proxy, method, null);
|
||||
cache.put(method, defaultValue == null ? NULL : defaultValue);
|
||||
return defaultValue;
|
||||
value = manager.getConfiguration(value);
|
||||
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 {}.{} ", groupValue, itemKeyName, e);
|
||||
if (method.isDefault())
|
||||
{
|
||||
return callDefaultMethod(proxy, method, null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
cache.put(method, NULL);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Convert value to return type
|
||||
Class<?> returnType = method.getReturnType();
|
||||
|
||||
try
|
||||
{
|
||||
Object objectValue = ConfigManager.stringToObject(value, returnType);
|
||||
cache.put(method, objectValue == null ? NULL : objectValue);
|
||||
return objectValue;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.warn("Unable to unmarshal {}.{} ", group.value(), item.keyName(), e);
|
||||
if (method.isDefault())
|
||||
catch (Throwable throwable)
|
||||
{
|
||||
return callDefaultMethod(proxy, method, null);
|
||||
log.error("Unable to resolve configuration value {}.{}", groupValue, itemKeyName, throwable);
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -130,7 +139,7 @@ class ConfigInvocationHandler implements InvocationHandler
|
||||
Object newValue = args[0];
|
||||
|
||||
Class<?> type = method.getParameterTypes()[0];
|
||||
Object oldValue = manager.getConfiguration(group.value(), item.keyName(), type);
|
||||
Object oldValue = manager.getConfiguration(groupValue, itemKeyName, type);
|
||||
|
||||
if (Objects.equals(oldValue, newValue))
|
||||
{
|
||||
@@ -145,19 +154,19 @@ class ConfigInvocationHandler implements InvocationHandler
|
||||
if (Objects.equals(newValue, defaultValue))
|
||||
{
|
||||
// Just unset if it goes back to the default
|
||||
manager.unsetConfiguration(group.value(), item.keyName());
|
||||
manager.unsetConfiguration(groupValue, itemKeyName);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (newValue == null)
|
||||
{
|
||||
manager.unsetConfiguration(group.value(), item.keyName());
|
||||
manager.unsetConfiguration(groupValue, itemKeyName);
|
||||
}
|
||||
else
|
||||
{
|
||||
String newValueStr = ConfigManager.objectToString(newValue);
|
||||
manager.setConfiguration(group.value(), item.keyName(), newValueStr);
|
||||
manager.setConfiguration(groupValue, itemKeyName, newValueStr);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -175,10 +184,4 @@ class ConfigInvocationHandler implements InvocationHandler
|
||||
.bindTo(proxy)
|
||||
.invokeWithArguments(args);
|
||||
}
|
||||
|
||||
void invalidate()
|
||||
{
|
||||
log.trace("cache invalidate");
|
||||
cache.invalidateAll();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,4 +46,29 @@ public @interface ConfigItem
|
||||
String warning() default "";
|
||||
|
||||
boolean secret() default false;
|
||||
}
|
||||
|
||||
String group() default "";
|
||||
|
||||
String unhide() default "";
|
||||
|
||||
String unhideValue() default "";
|
||||
|
||||
String hide() default "";
|
||||
|
||||
String hideValue() default "";
|
||||
|
||||
String parent() default "";
|
||||
|
||||
String enabledBy() default "";
|
||||
|
||||
String enabledByValue() default "";
|
||||
|
||||
String disabledBy() default "";
|
||||
|
||||
String disabledByValue() default "";
|
||||
|
||||
boolean parse() default false;
|
||||
|
||||
Class<?> clazz() default void.class;
|
||||
String method() default "";
|
||||
}
|
||||
@@ -0,0 +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 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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -42,13 +42,12 @@ import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.nio.channels.FileLock;
|
||||
import java.nio.charset.Charset;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -56,6 +55,7 @@ import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
@@ -63,146 +63,42 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.client.RuneLite;
|
||||
import net.runelite.client.account.AccountSession;
|
||||
import static net.runelite.client.RuneLite.PROFILES_DIR;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.util.ColorUtil;
|
||||
import net.runelite.http.api.config.ConfigClient;
|
||||
import net.runelite.http.api.config.ConfigEntry;
|
||||
import net.runelite.http.api.config.Configuration;
|
||||
|
||||
@Singleton
|
||||
@Slf4j
|
||||
public class ConfigManager
|
||||
{
|
||||
private static final String SETTINGS_FILE_NAME = "settings.properties";
|
||||
private static final DateFormat TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
|
||||
private static final String SETTINGS_FILE_NAME = "runeliteplus.properties";
|
||||
private static final String STANDARD_SETTINGS_FILE_NAME = "settings.properties";
|
||||
private static final File SETTINGS_FILE = new File(RuneLite.RUNELITE_DIR, SETTINGS_FILE_NAME);
|
||||
private static final File STANDARD_SETTINGS_FILE = new File(RuneLite.RUNELITE_DIR, STANDARD_SETTINGS_FILE_NAME);
|
||||
|
||||
@Inject
|
||||
EventBus eventBus;
|
||||
|
||||
private final ScheduledExecutorService executor;
|
||||
|
||||
private AccountSession session;
|
||||
private ConfigClient client;
|
||||
private File propertiesFile;
|
||||
|
||||
private final ConfigInvocationHandler handler = new ConfigInvocationHandler(this);
|
||||
private final Properties properties = new Properties();
|
||||
private final Map<String, Object> configObjectCache = new HashMap<>();
|
||||
private final Map<String, String> pendingChanges = new HashMap<>();
|
||||
|
||||
@Inject
|
||||
public ConfigManager(ScheduledExecutorService scheduledExecutorService)
|
||||
{
|
||||
this.executor = scheduledExecutorService;
|
||||
this.propertiesFile = getPropertiesFile();
|
||||
|
||||
executor.scheduleWithFixedDelay(this::sendConfig, 30, 30, TimeUnit.SECONDS);
|
||||
scheduledExecutorService.scheduleWithFixedDelay(this::sendConfig, 30, 30, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
public final void switchSession(AccountSession session)
|
||||
public final void switchSession()
|
||||
{
|
||||
// Ensure existing config is saved
|
||||
sendConfig();
|
||||
|
||||
if (session == null)
|
||||
{
|
||||
this.session = null;
|
||||
this.client = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.session = session;
|
||||
this.client = new ConfigClient(session.getUuid());
|
||||
}
|
||||
|
||||
this.propertiesFile = getPropertiesFile();
|
||||
|
||||
load(); // load profile specific config
|
||||
}
|
||||
|
||||
private File getLocalPropertiesFile()
|
||||
{
|
||||
return new File(RuneLite.RUNELITE_DIR, SETTINGS_FILE_NAME);
|
||||
}
|
||||
|
||||
private File getPropertiesFile()
|
||||
{
|
||||
// Sessions that aren't logged in have no username
|
||||
if (session == null || session.getUsername() == null)
|
||||
{
|
||||
return getLocalPropertiesFile();
|
||||
}
|
||||
else
|
||||
{
|
||||
File profileDir = new File(RuneLite.PROFILES_DIR, session.getUsername().toLowerCase());
|
||||
return new File(profileDir, SETTINGS_FILE_NAME);
|
||||
}
|
||||
load();
|
||||
}
|
||||
|
||||
public void load()
|
||||
{
|
||||
if (client == null)
|
||||
{
|
||||
loadFromFile();
|
||||
return;
|
||||
}
|
||||
|
||||
Configuration configuration;
|
||||
|
||||
try
|
||||
{
|
||||
configuration = client.get();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
log.debug("Unable to load configuration from client, using saved configuration from disk", ex);
|
||||
loadFromFile();
|
||||
return;
|
||||
}
|
||||
|
||||
if (configuration.getConfig() == null || configuration.getConfig().isEmpty())
|
||||
{
|
||||
log.debug("No configuration from client, using saved configuration on disk");
|
||||
loadFromFile();
|
||||
return;
|
||||
}
|
||||
|
||||
handler.invalidate();
|
||||
properties.clear();
|
||||
|
||||
for (ConfigEntry entry : configuration.getConfig())
|
||||
{
|
||||
log.debug("Loading configuration value from client {}: {}", entry.getKey(), entry.getValue());
|
||||
final String[] split = entry.getKey().split("\\.", 2);
|
||||
|
||||
if (split.length != 2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
final String groupName = split[0];
|
||||
final String key = split[1];
|
||||
final String value = entry.getValue();
|
||||
final String oldValue = (String) properties.setProperty(entry.getKey(), value);
|
||||
|
||||
ConfigChanged configChanged = new ConfigChanged();
|
||||
configChanged.setGroup(groupName);
|
||||
configChanged.setKey(key);
|
||||
configChanged.setOldValue(oldValue);
|
||||
configChanged.setNewValue(value);
|
||||
eventBus.post(configChanged);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
saveToFile(propertiesFile);
|
||||
|
||||
log.debug("Updated configuration on disk with the latest version");
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
log.warn("Unable to update configuration on disk", ex);
|
||||
}
|
||||
loadFromFile();
|
||||
}
|
||||
|
||||
private synchronized void syncPropertiesFromFile(File propertiesFile)
|
||||
@@ -210,7 +106,7 @@ public class ConfigManager
|
||||
final Properties properties = new Properties();
|
||||
try (FileInputStream in = new FileInputStream(propertiesFile))
|
||||
{
|
||||
properties.load(new InputStreamReader(in, Charset.forName("UTF-8")));
|
||||
properties.load(new InputStreamReader(in, StandardCharsets.UTF_8));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -218,7 +114,7 @@ public class ConfigManager
|
||||
return;
|
||||
}
|
||||
|
||||
final Map<String, String> copy = (Map) ImmutableMap.copyOf(this.properties);
|
||||
@SuppressWarnings("unchecked") final Map<String, String> copy = (Map) ImmutableMap.copyOf(this.properties);
|
||||
copy.forEach((groupAndKey, value) ->
|
||||
{
|
||||
if (!properties.containsKey(groupAndKey))
|
||||
@@ -253,39 +149,21 @@ public class ConfigManager
|
||||
|
||||
public void importLocal()
|
||||
{
|
||||
if (session == null)
|
||||
{
|
||||
// No session, no import
|
||||
return;
|
||||
}
|
||||
|
||||
final File file = new File(propertiesFile.getParent(), propertiesFile.getName() + "." + TIME_FORMAT.format(new Date()));
|
||||
|
||||
try
|
||||
{
|
||||
saveToFile(file);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
log.warn("Backup failed, skipping import", e);
|
||||
return;
|
||||
}
|
||||
|
||||
syncPropertiesFromFile(getLocalPropertiesFile());
|
||||
log.info("Nothing changed, don't worry!");
|
||||
}
|
||||
|
||||
private synchronized void loadFromFile()
|
||||
{
|
||||
handler.invalidate();
|
||||
properties.clear();
|
||||
|
||||
try (FileInputStream in = new FileInputStream(propertiesFile))
|
||||
try (FileInputStream in = new FileInputStream(SETTINGS_FILE))
|
||||
{
|
||||
properties.load(new InputStreamReader(in, Charset.forName("UTF-8")));
|
||||
properties.load(new InputStreamReader(in, StandardCharsets.UTF_8));
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
{
|
||||
log.debug("Unable to load settings - no such file");
|
||||
log.debug("Unable to load settings - no such file, syncing from standard settings");
|
||||
syncLastModified();
|
||||
}
|
||||
catch (IllegalArgumentException | IOException ex)
|
||||
{
|
||||
@@ -294,7 +172,7 @@ public class ConfigManager
|
||||
|
||||
try
|
||||
{
|
||||
Map<String, String> copy = (Map) ImmutableMap.copyOf(properties);
|
||||
@SuppressWarnings("unchecked") Map<String, String> copy = (Map) ImmutableMap.copyOf(properties);
|
||||
copy.forEach((groupAndKey, value) ->
|
||||
{
|
||||
final String[] split = groupAndKey.split("\\.", 2);
|
||||
@@ -313,7 +191,7 @@ public class ConfigManager
|
||||
configChanged.setKey(key);
|
||||
configChanged.setOldValue(null);
|
||||
configChanged.setNewValue(value);
|
||||
eventBus.post(configChanged);
|
||||
eventBus.post(ConfigChanged.class, configChanged);
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -322,17 +200,17 @@ public class ConfigManager
|
||||
}
|
||||
}
|
||||
|
||||
private void saveToFile(final File propertiesFile) throws IOException
|
||||
private void saveToFile() throws IOException
|
||||
{
|
||||
propertiesFile.getParentFile().mkdirs();
|
||||
ConfigManager.SETTINGS_FILE.getParentFile().mkdirs();
|
||||
|
||||
try (FileOutputStream out = new FileOutputStream(propertiesFile))
|
||||
try (FileOutputStream out = new FileOutputStream(ConfigManager.SETTINGS_FILE))
|
||||
{
|
||||
final FileLock lock = out.getChannel().lock();
|
||||
|
||||
try
|
||||
{
|
||||
properties.store(new OutputStreamWriter(out, Charset.forName("UTF-8")), "RuneLite configuration");
|
||||
properties.store(new OutputStreamWriter(out, StandardCharsets.UTF_8), "RuneLite configuration");
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -341,6 +219,21 @@ public class ConfigManager
|
||||
}
|
||||
}
|
||||
|
||||
// Attempts to fetch the config value from the cache if present. Otherwise it calls the get value function and caches the result
|
||||
Object getConfigObjectFromCacheOrElse(String groupName, String key, Function<String, Object> getValue)
|
||||
{
|
||||
String configItemKey = groupName + "." + key;
|
||||
return configObjectCache.computeIfAbsent(configItemKey, getValue);
|
||||
}
|
||||
|
||||
// Posts the configchanged event to the event bus and remove the changed key from the cache
|
||||
private void postConfigChanged(ConfigChanged configChanged)
|
||||
{
|
||||
configObjectCache.remove(configChanged.getGroup() + "." + configChanged.getKey());
|
||||
eventBus.post(ConfigChanged.class, configChanged);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getConfig(Class<T> clazz)
|
||||
{
|
||||
if (!Modifier.isPublic(clazz.getModifiers()))
|
||||
@@ -348,12 +241,10 @@ public class ConfigManager
|
||||
throw new RuntimeException("Non-public configuration classes can't have default methods invoked");
|
||||
}
|
||||
|
||||
T t = (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class<?>[]
|
||||
return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class<?>[]
|
||||
{
|
||||
clazz
|
||||
}, handler);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
public List<String> getConfigurationKeys(String prefix)
|
||||
@@ -366,6 +257,12 @@ public class ConfigManager
|
||||
return properties.getProperty(groupName + "." + key);
|
||||
}
|
||||
|
||||
public String getConfiguration(String propertyKey)
|
||||
{
|
||||
return properties.getProperty(propertyKey);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getConfiguration(String groupName, String key, Class<T> clazz)
|
||||
{
|
||||
String value = getConfiguration(groupName, key);
|
||||
@@ -393,7 +290,6 @@ public class ConfigManager
|
||||
}
|
||||
|
||||
log.debug("Setting configuration value for {}.{} to {}", groupName, key, value);
|
||||
handler.invalidate();
|
||||
|
||||
synchronized (pendingChanges)
|
||||
{
|
||||
@@ -406,7 +302,7 @@ public class ConfigManager
|
||||
configChanged.setOldValue(oldValue);
|
||||
configChanged.setNewValue(value);
|
||||
|
||||
eventBus.post(configChanged);
|
||||
postConfigChanged(configChanged);
|
||||
}
|
||||
|
||||
public void setConfiguration(String groupName, String key, Object value)
|
||||
@@ -424,7 +320,6 @@ public class ConfigManager
|
||||
}
|
||||
|
||||
log.debug("Unsetting configuration value for {}.{}", groupName, key);
|
||||
handler.invalidate();
|
||||
|
||||
synchronized (pendingChanges)
|
||||
{
|
||||
@@ -436,7 +331,7 @@ public class ConfigManager
|
||||
configChanged.setKey(key);
|
||||
configChanged.setOldValue(oldValue);
|
||||
|
||||
eventBus.post(configChanged);
|
||||
eventBus.post(ConfigChanged.class, configChanged);
|
||||
}
|
||||
|
||||
public ConfigDescriptor getConfigDescriptor(Object configurationProxy)
|
||||
@@ -463,7 +358,35 @@ public class ConfigManager
|
||||
.result())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return new ConfigDescriptor(group, items);
|
||||
Collection<ConfigItemsGroup> itemGroups = new ArrayList<>();
|
||||
|
||||
for (ConfigItemDescriptor item : items)
|
||||
{
|
||||
String groupName = item.getItem().group();
|
||||
boolean found = false;
|
||||
for (ConfigItemsGroup g : itemGroups)
|
||||
{
|
||||
if (g.getGroup().equals(groupName))
|
||||
{
|
||||
g.addItem(item);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
ConfigItemsGroup newGroup = new ConfigItemsGroup(groupName);
|
||||
newGroup.addItem(item);
|
||||
itemGroups.add(newGroup);
|
||||
}
|
||||
}
|
||||
|
||||
itemGroups = itemGroups.stream().sorted((a, b) -> ComparisonChain.start()
|
||||
.compare(a.getGroup(), b.getGroup())
|
||||
.result())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return new ConfigDescriptor(group, itemGroups);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -541,6 +464,7 @@ public class ConfigManager
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static Object stringToObject(String str, Class<?> type)
|
||||
{
|
||||
if (type == boolean.class || type == Boolean.class)
|
||||
@@ -609,6 +533,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]);
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
@@ -663,23 +603,6 @@ public class ConfigManager
|
||||
boolean changed;
|
||||
synchronized (pendingChanges)
|
||||
{
|
||||
if (client != null)
|
||||
{
|
||||
for (Map.Entry<String, String> entry : pendingChanges.entrySet())
|
||||
{
|
||||
String key = entry.getKey();
|
||||
String value = entry.getValue();
|
||||
|
||||
if (Strings.isNullOrEmpty(value))
|
||||
{
|
||||
client.unset(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
client.set(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
changed = !pendingChanges.isEmpty();
|
||||
pendingChanges.clear();
|
||||
}
|
||||
@@ -688,7 +611,7 @@ public class ConfigManager
|
||||
{
|
||||
try
|
||||
{
|
||||
saveToFile(propertiesFile);
|
||||
saveToFile();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
@@ -696,4 +619,44 @@ public class ConfigManager
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void syncLastModified()
|
||||
{
|
||||
File newestFile;
|
||||
|
||||
newestFile = STANDARD_SETTINGS_FILE;
|
||||
|
||||
File[] profileDirFiles = PROFILES_DIR.listFiles();
|
||||
|
||||
if (profileDirFiles != null)
|
||||
{
|
||||
for (File profileDir : profileDirFiles)
|
||||
{
|
||||
if (!profileDir.isDirectory())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
File[] settingsFiles = profileDir.listFiles();
|
||||
|
||||
if (settingsFiles == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (File settings : settingsFiles)
|
||||
{
|
||||
if (!settings.getName().equals(STANDARD_SETTINGS_FILE_NAME) ||
|
||||
settings.lastModified() < newestFile.lastModified())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
newestFile = settings;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
syncPropertiesFromFile(newestFile);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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.List;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
|
||||
public class ConfigPanelItem
|
||||
{
|
||||
|
||||
@Getter(AccessLevel.PUBLIC)
|
||||
private ConfigPanelItem parent;
|
||||
|
||||
@Getter(AccessLevel.PUBLIC)
|
||||
private List<ConfigPanelItem> children;
|
||||
|
||||
@Getter(AccessLevel.PUBLIC)
|
||||
private ConfigItemDescriptor item;
|
||||
|
||||
public ConfigPanelItem(ConfigPanelItem parent, ConfigItemDescriptor item)
|
||||
{
|
||||
this.parent = parent;
|
||||
this.children = new ArrayList<>();
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
public List<ConfigPanelItem> getItemsAsList()
|
||||
{
|
||||
List<ConfigPanelItem> items = new ArrayList<>();
|
||||
|
||||
items.add(this);
|
||||
|
||||
for (ConfigPanelItem child : children)
|
||||
{
|
||||
items.addAll(child.getItemsAsList());
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
public int getDepth()
|
||||
{
|
||||
return (parent == null ? 0 : parent.getDepth() + 1);
|
||||
}
|
||||
|
||||
public boolean addChildIfMatchParent(ConfigItemDescriptor cid)
|
||||
{
|
||||
|
||||
if (item != null && item.getItem().keyName().equals(cid.getItem().parent()))
|
||||
{
|
||||
children.add(new ConfigPanelItem(this, cid));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (ConfigPanelItem child : children)
|
||||
{
|
||||
if (child.addChildIfMatchParent(cid))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,11 +24,10 @@
|
||||
*/
|
||||
package net.runelite.client.config;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import net.runelite.client.ui.FontManager;
|
||||
|
||||
import java.awt.Font;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.runelite.client.ui.FontManager;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
|
||||
@@ -60,7 +60,7 @@ public class Keybind
|
||||
private final int keyCode;
|
||||
private final int modifiers;
|
||||
|
||||
protected Keybind(int keyCode, int modifiers, boolean ignoreModifiers)
|
||||
Keybind(int keyCode, int modifiers, boolean ignoreModifiers)
|
||||
{
|
||||
modifiers &= KEYBOARD_MODIFIER_MASK;
|
||||
|
||||
@@ -108,7 +108,7 @@ public class Keybind
|
||||
return matches(e, false);
|
||||
}
|
||||
|
||||
protected boolean matches(KeyEvent e, boolean ignoreModifiers)
|
||||
boolean matches(KeyEvent e, boolean ignoreModifiers)
|
||||
{
|
||||
if (NOT_SET.equals(this))
|
||||
{
|
||||
@@ -177,7 +177,7 @@ public class Keybind
|
||||
return mod;
|
||||
}
|
||||
|
||||
public static String getModifiersExText(int modifiers)
|
||||
private static String getModifiersExText(int modifiers)
|
||||
{
|
||||
StringBuilder buf = new StringBuilder();
|
||||
if ((modifiers & InputEvent.META_DOWN_MASK) != 0)
|
||||
|
||||
@@ -25,7 +25,9 @@
|
||||
package net.runelite.client.config;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import net.runelite.api.Constants;
|
||||
import net.runelite.client.ui.FontManager;
|
||||
import net.runelite.client.ui.ContainableFrame;
|
||||
|
||||
@ConfigGroup("runelite")
|
||||
@@ -176,8 +178,8 @@ public interface RuneLiteConfig extends Config
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "flashNotification",
|
||||
name = "Flash notification",
|
||||
keyName = "notificationFlash",
|
||||
name = "Enable flash notification",
|
||||
description = "Flashes the game frame as a notification",
|
||||
position = 24
|
||||
)
|
||||
@@ -197,6 +199,17 @@ public interface RuneLiteConfig extends Config
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "clientFont",
|
||||
name = "Font",
|
||||
description = "Configure what font is used for the client and runelite added overlays",
|
||||
position = 29
|
||||
)
|
||||
default Font clientFont()
|
||||
{
|
||||
return FontManager.getRunescapeFont();
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "fontType",
|
||||
name = "Dynamic Overlay Font",
|
||||
@@ -273,4 +286,17 @@ public interface RuneLiteConfig extends Config
|
||||
{
|
||||
return 35;
|
||||
}
|
||||
}
|
||||
|
||||
@Range(max = 100, min = 0)
|
||||
@ConfigItem(
|
||||
keyName = "volume",
|
||||
name = "Runelite Volume",
|
||||
description = "Sets the volume of custom Runelite sounds (not the client sounds)",
|
||||
position = 43
|
||||
)
|
||||
default int volume()
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2019, Zeruth <TheRealNull@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;
|
||||
|
||||
@ConfigGroup("runeliteplus")
|
||||
public interface RuneLitePlusConfig extends Config
|
||||
{
|
||||
@ConfigItem(
|
||||
keyName = "enableOpacity",
|
||||
name = "Enable opacity",
|
||||
description = "Enables opacity for the whole window.<br>NOTE: This only stays enabled if your pc supports this!",
|
||||
position = 0
|
||||
)
|
||||
default boolean enableOpacity()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Range(
|
||||
min = 15,
|
||||
max = 100
|
||||
)
|
||||
@ConfigItem(
|
||||
keyName = "opacityPercentage",
|
||||
name = "Opacity percentage",
|
||||
description = "Changes the opacity of the window if opacity is enabled",
|
||||
position = 1
|
||||
)
|
||||
default int opacityPercentage()
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "keyboardPin",
|
||||
name = "Keyboard bank pin",
|
||||
description = "Enables you to type your bank pin",
|
||||
position = 2
|
||||
)
|
||||
default boolean keyboardPin()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "enablePlugins",
|
||||
name = "Enable loading of external plugins",
|
||||
description = "Enable loading of external plugins",
|
||||
position = 3
|
||||
)
|
||||
default boolean enablePlugins()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "detachHotkey",
|
||||
name = "Detach Cam",
|
||||
description = "Detach Camera hotkey, press this and it will activate detatched camera.",
|
||||
position = 4
|
||||
)
|
||||
default Keybind detachHotkey()
|
||||
{
|
||||
return Keybind.NOT_SET;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package net.runelite.client.config;
|
||||
|
||||
public class Stub
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package net.runelite.client.database;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import javax.inject.Singleton;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import static net.runelite.client.RuneLite.RUNELITE_DIR;
|
||||
import org.h2.jdbcx.JdbcDataSource;
|
||||
import org.jooq.DSLContext;
|
||||
import org.jooq.SQLDialect;
|
||||
import org.jooq.impl.DSL;
|
||||
|
||||
@Singleton
|
||||
@Slf4j
|
||||
public class DatabaseManager
|
||||
{
|
||||
private static final String DB_URL = "jdbc:h2:" + RUNELITE_DIR + File.separator + "RunelitePlus;AUTO_SERVER=TRUE";
|
||||
|
||||
// Database credentials
|
||||
private static final String USER = "RLP";
|
||||
private static final String PASS = "";
|
||||
|
||||
private Connection connection;
|
||||
|
||||
DatabaseManager()
|
||||
{
|
||||
System.getProperties().setProperty("org.jooq.no-logo", "true");
|
||||
}
|
||||
|
||||
private void connect()
|
||||
{
|
||||
if (connection != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
JdbcDataSource ds = new JdbcDataSource();
|
||||
ds.setURL(DatabaseManager.DB_URL);
|
||||
ds.setUser(DatabaseManager.USER);
|
||||
ds.setPassword(DatabaseManager.PASS);
|
||||
|
||||
try
|
||||
{
|
||||
connection = ds.getConnection();
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
Connection getConnection()
|
||||
{
|
||||
connect();
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
||||
public DSLContext getDsl()
|
||||
{
|
||||
return DSL.using(connection, SQLDialect.H2);
|
||||
}
|
||||
|
||||
public boolean checkTableExists(String table)
|
||||
{
|
||||
boolean tableExists = false;
|
||||
|
||||
connect();
|
||||
|
||||
try
|
||||
{
|
||||
ResultSet rset = connection.getMetaData().getTables(null, null, table.toUpperCase(), null);
|
||||
if (rset.next())
|
||||
{
|
||||
tableExists = true;
|
||||
}
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return tableExists;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package net.runelite.client.database;
|
||||
|
||||
import java.sql.Connection;
|
||||
import org.jooq.codegen.GenerationTool;
|
||||
import org.jooq.meta.h2.H2Database;
|
||||
import org.jooq.meta.jaxb.Configuration;
|
||||
import org.jooq.meta.jaxb.Database;
|
||||
import org.jooq.meta.jaxb.Generator;
|
||||
import org.jooq.meta.jaxb.Target;
|
||||
|
||||
public class GenerateClasses
|
||||
{
|
||||
public static void main(String... args)
|
||||
{
|
||||
DatabaseManager databaseManager = new DatabaseManager();
|
||||
|
||||
try (Connection c = databaseManager.getConnection())
|
||||
{
|
||||
Configuration configuration = new Configuration()
|
||||
.withGenerator(new Generator()
|
||||
.withDatabase(new Database()
|
||||
.withName(H2Database.class.getCanonicalName())
|
||||
.withIncludes(".*")
|
||||
.withExcludes("")
|
||||
.withInputSchema("PUBLIC")
|
||||
)
|
||||
.withTarget(new Target()
|
||||
.withPackageName("net.runelite.client.database.data")
|
||||
.withDirectory("runelite-client/src/main/java/net/runelite/client/database/data")
|
||||
)
|
||||
);
|
||||
|
||||
GenerationTool tool = new GenerationTool();
|
||||
tool.setConnection(c);
|
||||
tool.run(configuration);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* This file is generated by jOOQ.
|
||||
*/
|
||||
package net.runelite.client.database.data;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import javax.annotation.Generated;
|
||||
import org.jooq.Schema;
|
||||
import org.jooq.impl.CatalogImpl;
|
||||
|
||||
|
||||
/**
|
||||
* This class is generated by jOOQ.
|
||||
*/
|
||||
@Generated(
|
||||
value = {
|
||||
"http://www.jooq.org",
|
||||
"jOOQ version:3.11.12"
|
||||
},
|
||||
comments = "This class is generated by jOOQ"
|
||||
)
|
||||
@SuppressWarnings({"all", "unchecked", "rawtypes"})
|
||||
public class DefaultCatalog extends CatalogImpl
|
||||
{
|
||||
|
||||
private static final long serialVersionUID = 836257769;
|
||||
|
||||
/**
|
||||
* The reference instance of <code></code>
|
||||
*/
|
||||
public static final DefaultCatalog DEFAULT_CATALOG = new DefaultCatalog();
|
||||
|
||||
/**
|
||||
* The schema <code>PUBLIC</code>.
|
||||
*/
|
||||
public final Public PUBLIC = net.runelite.client.database.data.Public.PUBLIC;
|
||||
|
||||
/**
|
||||
* No further instances allowed
|
||||
*/
|
||||
private DefaultCatalog()
|
||||
{
|
||||
super("");
|
||||
}
|
||||
|
||||
@Override
|
||||
public final List<Schema> getSchemas()
|
||||
{
|
||||
List result = new ArrayList();
|
||||
result.addAll(getSchemas0());
|
||||
return result;
|
||||
}
|
||||
|
||||
private final List<Schema> getSchemas0()
|
||||
{
|
||||
return Arrays.<Schema>asList(
|
||||
Public.PUBLIC);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* This file is generated by jOOQ.
|
||||
*/
|
||||
package net.runelite.client.database.data;
|
||||
|
||||
|
||||
import javax.annotation.Generated;
|
||||
import net.runelite.client.database.data.tables.Loottrackerevents;
|
||||
import net.runelite.client.database.data.tables.Loottrackerlink;
|
||||
import net.runelite.client.database.data.tables.Loottrackerloot;
|
||||
import net.runelite.client.database.data.tables.User;
|
||||
import org.jooq.Index;
|
||||
import org.jooq.OrderField;
|
||||
import org.jooq.impl.Internal;
|
||||
|
||||
|
||||
/**
|
||||
* A class modelling indexes of tables of the <code>PUBLIC</code> schema.
|
||||
*/
|
||||
@Generated(
|
||||
value = {
|
||||
"http://www.jooq.org",
|
||||
"jOOQ version:3.11.12"
|
||||
},
|
||||
comments = "This class is generated by jOOQ"
|
||||
)
|
||||
@SuppressWarnings({"all", "unchecked", "rawtypes"})
|
||||
public class Indexes
|
||||
{
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// INDEX definitions
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
public static final Index PRIMARY_KEY_B = Indexes0.PRIMARY_KEY_B;
|
||||
public static final Index FK_LOOTTRACKEREVENT_INDEX_6 = Indexes0.FK_LOOTTRACKEREVENT_INDEX_6;
|
||||
public static final Index FK_LOOTTRACKERLOOT_INDEX_6 = Indexes0.FK_LOOTTRACKERLOOT_INDEX_6;
|
||||
public static final Index PRIMARY_KEY_6B = Indexes0.PRIMARY_KEY_6B;
|
||||
public static final Index PRIMARY_KEY_6 = Indexes0.PRIMARY_KEY_6;
|
||||
public static final Index PRIMARY_KEY_2 = Indexes0.PRIMARY_KEY_2;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// [#1459] distribute members to avoid static initialisers > 64kb
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private static class Indexes0
|
||||
{
|
||||
public static Index PRIMARY_KEY_B = Internal.createIndex("PRIMARY_KEY_B", Loottrackerevents.LOOTTRACKEREVENTS, new OrderField[]{Loottrackerevents.LOOTTRACKEREVENTS.UNIQUEID}, true);
|
||||
public static Index FK_LOOTTRACKEREVENT_INDEX_6 = Internal.createIndex("FK_LOOTTRACKEREVENT_INDEX_6", Loottrackerlink.LOOTTRACKERLINK, new OrderField[]{Loottrackerlink.LOOTTRACKERLINK.EVENTUNIQUEID}, false);
|
||||
public static Index FK_LOOTTRACKERLOOT_INDEX_6 = Internal.createIndex("FK_LOOTTRACKERLOOT_INDEX_6", Loottrackerlink.LOOTTRACKERLINK, new OrderField[]{Loottrackerlink.LOOTTRACKERLINK.DROPUNIQUEID}, false);
|
||||
public static Index PRIMARY_KEY_6B = Internal.createIndex("PRIMARY_KEY_6B", Loottrackerlink.LOOTTRACKERLINK, new OrderField[]{Loottrackerlink.LOOTTRACKERLINK.LINKUNIQUEID}, true);
|
||||
public static Index PRIMARY_KEY_6 = Internal.createIndex("PRIMARY_KEY_6", Loottrackerloot.LOOTTRACKERLOOT, new OrderField[]{Loottrackerloot.LOOTTRACKERLOOT.UNIQUEID}, true);
|
||||
public static Index PRIMARY_KEY_2 = Internal.createIndex("PRIMARY_KEY_2", User.USER, new OrderField[]{User.USER.UNIQUEID}, true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* This file is generated by jOOQ.
|
||||
*/
|
||||
package net.runelite.client.database.data;
|
||||
|
||||
|
||||
import javax.annotation.Generated;
|
||||
import net.runelite.client.database.data.tables.Loottrackerevents;
|
||||
import net.runelite.client.database.data.tables.Loottrackerlink;
|
||||
import net.runelite.client.database.data.tables.Loottrackerloot;
|
||||
import net.runelite.client.database.data.tables.User;
|
||||
import net.runelite.client.database.data.tables.records.LoottrackereventsRecord;
|
||||
import net.runelite.client.database.data.tables.records.LoottrackerlinkRecord;
|
||||
import net.runelite.client.database.data.tables.records.LoottrackerlootRecord;
|
||||
import net.runelite.client.database.data.tables.records.UserRecord;
|
||||
import org.jooq.ForeignKey;
|
||||
import org.jooq.UniqueKey;
|
||||
import org.jooq.impl.Internal;
|
||||
|
||||
|
||||
/**
|
||||
* A class modelling foreign key relationships and constraints of tables of
|
||||
* the <code>PUBLIC</code> schema.
|
||||
*/
|
||||
@Generated(
|
||||
value = {
|
||||
"http://www.jooq.org",
|
||||
"jOOQ version:3.11.12"
|
||||
},
|
||||
comments = "This class is generated by jOOQ"
|
||||
)
|
||||
@SuppressWarnings({"all", "unchecked", "rawtypes"})
|
||||
public class Keys
|
||||
{
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// IDENTITY definitions
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// UNIQUE and PRIMARY KEY definitions
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
public static final UniqueKey<LoottrackereventsRecord> PK_EVENTUNIQUEID = UniqueKeys0.PK_EVENTUNIQUEID;
|
||||
public static final UniqueKey<LoottrackerlinkRecord> PK_LOOTTRACKERLINK = UniqueKeys0.PK_LOOTTRACKERLINK;
|
||||
public static final UniqueKey<LoottrackerlootRecord> PK_LOOTUNIQUEID = UniqueKeys0.PK_LOOTUNIQUEID;
|
||||
public static final UniqueKey<UserRecord> PK_USER = UniqueKeys0.PK_USER;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// FOREIGN KEY definitions
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
public static final ForeignKey<LoottrackerlinkRecord, LoottrackereventsRecord> FK_LOOTTRACKEREVENT = ForeignKeys0.FK_LOOTTRACKEREVENT;
|
||||
public static final ForeignKey<LoottrackerlinkRecord, LoottrackerlootRecord> FK_LOOTTRACKERLOOT = ForeignKeys0.FK_LOOTTRACKERLOOT;
|
||||
public static final ForeignKey<LoottrackerlinkRecord, UserRecord> FK_USER = ForeignKeys0.FK_USER;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// [#1459] distribute members to avoid static initialisers > 64kb
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private static class UniqueKeys0
|
||||
{
|
||||
public static final UniqueKey<LoottrackereventsRecord> PK_EVENTUNIQUEID = Internal.createUniqueKey(Loottrackerevents.LOOTTRACKEREVENTS, "PK_EVENTUNIQUEID", Loottrackerevents.LOOTTRACKEREVENTS.UNIQUEID);
|
||||
public static final UniqueKey<LoottrackerlinkRecord> PK_LOOTTRACKERLINK = Internal.createUniqueKey(Loottrackerlink.LOOTTRACKERLINK, "PK_LOOTTRACKERLINK", Loottrackerlink.LOOTTRACKERLINK.LINKUNIQUEID);
|
||||
public static final UniqueKey<LoottrackerlootRecord> PK_LOOTUNIQUEID = Internal.createUniqueKey(Loottrackerloot.LOOTTRACKERLOOT, "PK_LOOTUNIQUEID", Loottrackerloot.LOOTTRACKERLOOT.UNIQUEID);
|
||||
public static final UniqueKey<UserRecord> PK_USER = Internal.createUniqueKey(User.USER, "PK_USER", User.USER.UNIQUEID);
|
||||
}
|
||||
|
||||
private static class ForeignKeys0
|
||||
{
|
||||
public static final ForeignKey<LoottrackerlinkRecord, LoottrackereventsRecord> FK_LOOTTRACKEREVENT = Internal.createForeignKey(net.runelite.client.database.data.Keys.PK_EVENTUNIQUEID, Loottrackerlink.LOOTTRACKERLINK, "FK_LOOTTRACKEREVENT", Loottrackerlink.LOOTTRACKERLINK.EVENTUNIQUEID);
|
||||
public static final ForeignKey<LoottrackerlinkRecord, LoottrackerlootRecord> FK_LOOTTRACKERLOOT = Internal.createForeignKey(net.runelite.client.database.data.Keys.PK_LOOTUNIQUEID, Loottrackerlink.LOOTTRACKERLINK, "FK_LOOTTRACKERLOOT", Loottrackerlink.LOOTTRACKERLINK.DROPUNIQUEID);
|
||||
public static final ForeignKey<LoottrackerlinkRecord, UserRecord> FK_USER = Internal.createForeignKey(net.runelite.client.database.data.Keys.PK_USER, Loottrackerlink.LOOTTRACKERLINK, "FK_USER", Loottrackerlink.LOOTTRACKERLINK.DROPUNIQUEID);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* This file is generated by jOOQ.
|
||||
*/
|
||||
package net.runelite.client.database.data;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import javax.annotation.Generated;
|
||||
import net.runelite.client.database.data.tables.Loottrackerevents;
|
||||
import net.runelite.client.database.data.tables.Loottrackerlink;
|
||||
import net.runelite.client.database.data.tables.Loottrackerloot;
|
||||
import net.runelite.client.database.data.tables.User;
|
||||
import org.jooq.Catalog;
|
||||
import org.jooq.Table;
|
||||
import org.jooq.impl.SchemaImpl;
|
||||
|
||||
|
||||
/**
|
||||
* This class is generated by jOOQ.
|
||||
*/
|
||||
@Generated(
|
||||
value = {
|
||||
"http://www.jooq.org",
|
||||
"jOOQ version:3.11.12"
|
||||
},
|
||||
comments = "This class is generated by jOOQ"
|
||||
)
|
||||
@SuppressWarnings({"all", "unchecked", "rawtypes"})
|
||||
public class Public extends SchemaImpl
|
||||
{
|
||||
|
||||
private static final long serialVersionUID = 1499404561;
|
||||
|
||||
/**
|
||||
* The reference instance of <code>PUBLIC</code>
|
||||
*/
|
||||
public static final Public PUBLIC = new Public();
|
||||
|
||||
/**
|
||||
* The table <code>PUBLIC.LOOTTRACKEREVENTS</code>.
|
||||
*/
|
||||
public final Loottrackerevents LOOTTRACKEREVENTS = net.runelite.client.database.data.tables.Loottrackerevents.LOOTTRACKEREVENTS;
|
||||
|
||||
/**
|
||||
* The table <code>PUBLIC.LOOTTRACKERLINK</code>.
|
||||
*/
|
||||
public final Loottrackerlink LOOTTRACKERLINK = net.runelite.client.database.data.tables.Loottrackerlink.LOOTTRACKERLINK;
|
||||
|
||||
/**
|
||||
* The table <code>PUBLIC.LOOTTRACKERLOOT</code>.
|
||||
*/
|
||||
public final Loottrackerloot LOOTTRACKERLOOT = net.runelite.client.database.data.tables.Loottrackerloot.LOOTTRACKERLOOT;
|
||||
|
||||
/**
|
||||
* The table <code>PUBLIC.USER</code>.
|
||||
*/
|
||||
public final User USER = net.runelite.client.database.data.tables.User.USER;
|
||||
|
||||
/**
|
||||
* No further instances allowed
|
||||
*/
|
||||
private Public()
|
||||
{
|
||||
super("PUBLIC", null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Catalog getCatalog()
|
||||
{
|
||||
return DefaultCatalog.DEFAULT_CATALOG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final List<Table<?>> getTables()
|
||||
{
|
||||
List result = new ArrayList();
|
||||
result.addAll(getTables0());
|
||||
return result;
|
||||
}
|
||||
|
||||
private final List<Table<?>> getTables0()
|
||||
{
|
||||
return Arrays.<Table<?>>asList(
|
||||
Loottrackerevents.LOOTTRACKEREVENTS,
|
||||
Loottrackerlink.LOOTTRACKERLINK,
|
||||
Loottrackerloot.LOOTTRACKERLOOT,
|
||||
User.USER);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* This file is generated by jOOQ.
|
||||
*/
|
||||
package net.runelite.client.database.data;
|
||||
|
||||
|
||||
import javax.annotation.Generated;
|
||||
import net.runelite.client.database.data.tables.Loottrackerevents;
|
||||
import net.runelite.client.database.data.tables.Loottrackerlink;
|
||||
import net.runelite.client.database.data.tables.Loottrackerloot;
|
||||
import net.runelite.client.database.data.tables.User;
|
||||
|
||||
|
||||
/**
|
||||
* Convenience access to all tables in PUBLIC
|
||||
*/
|
||||
@Generated(
|
||||
value = {
|
||||
"http://www.jooq.org",
|
||||
"jOOQ version:3.11.12"
|
||||
},
|
||||
comments = "This class is generated by jOOQ"
|
||||
)
|
||||
@SuppressWarnings({"all", "unchecked", "rawtypes"})
|
||||
public class Tables
|
||||
{
|
||||
|
||||
/**
|
||||
* The table <code>PUBLIC.LOOTTRACKEREVENTS</code>.
|
||||
*/
|
||||
public static final Loottrackerevents LOOTTRACKEREVENTS = net.runelite.client.database.data.tables.Loottrackerevents.LOOTTRACKEREVENTS;
|
||||
|
||||
/**
|
||||
* The table <code>PUBLIC.LOOTTRACKERLINK</code>.
|
||||
*/
|
||||
public static final Loottrackerlink LOOTTRACKERLINK = net.runelite.client.database.data.tables.Loottrackerlink.LOOTTRACKERLINK;
|
||||
|
||||
/**
|
||||
* The table <code>PUBLIC.LOOTTRACKERLOOT</code>.
|
||||
*/
|
||||
public static final Loottrackerloot LOOTTRACKERLOOT = net.runelite.client.database.data.tables.Loottrackerloot.LOOTTRACKERLOOT;
|
||||
|
||||
/**
|
||||
* The table <code>PUBLIC.USER</code>.
|
||||
*/
|
||||
public static final User USER = net.runelite.client.database.data.tables.User.USER;
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* This file is generated by jOOQ.
|
||||
*/
|
||||
package net.runelite.client.database.data.tables;
|
||||
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import javax.annotation.Generated;
|
||||
import net.runelite.client.database.data.Indexes;
|
||||
import net.runelite.client.database.data.Keys;
|
||||
import net.runelite.client.database.data.Public;
|
||||
import net.runelite.client.database.data.tables.records.LoottrackereventsRecord;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.ForeignKey;
|
||||
import org.jooq.Index;
|
||||
import org.jooq.Name;
|
||||
import org.jooq.Record;
|
||||
import org.jooq.Schema;
|
||||
import org.jooq.Table;
|
||||
import org.jooq.TableField;
|
||||
import org.jooq.UniqueKey;
|
||||
import org.jooq.impl.DSL;
|
||||
import org.jooq.impl.TableImpl;
|
||||
|
||||
|
||||
/**
|
||||
* This class is generated by jOOQ.
|
||||
*/
|
||||
@Generated(
|
||||
value = {
|
||||
"http://www.jooq.org",
|
||||
"jOOQ version:3.11.12"
|
||||
},
|
||||
comments = "This class is generated by jOOQ"
|
||||
)
|
||||
@SuppressWarnings({"all", "unchecked", "rawtypes"})
|
||||
public class Loottrackerevents extends TableImpl<LoottrackereventsRecord>
|
||||
{
|
||||
|
||||
private static final long serialVersionUID = -824670812;
|
||||
|
||||
/**
|
||||
* The reference instance of <code>PUBLIC.LOOTTRACKEREVENTS</code>
|
||||
*/
|
||||
public static final Loottrackerevents LOOTTRACKEREVENTS = new Loottrackerevents();
|
||||
|
||||
/**
|
||||
* The class holding records for this type
|
||||
*/
|
||||
@Override
|
||||
public Class<LoottrackereventsRecord> getRecordType()
|
||||
{
|
||||
return LoottrackereventsRecord.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* The column <code>PUBLIC.LOOTTRACKEREVENTS.UNIQUEID</code>.
|
||||
*/
|
||||
public final TableField<LoottrackereventsRecord, UUID> UNIQUEID = createField("UNIQUEID", org.jooq.impl.SQLDataType.UUID.nullable(false), this, "");
|
||||
|
||||
/**
|
||||
* The column <code>PUBLIC.LOOTTRACKEREVENTS.EVENTID</code>.
|
||||
*/
|
||||
public final TableField<LoottrackereventsRecord, String> EVENTID = createField("EVENTID", org.jooq.impl.SQLDataType.VARCHAR(255).nullable(false), this, "");
|
||||
|
||||
/**
|
||||
* The column <code>PUBLIC.LOOTTRACKEREVENTS.TYPE</code>.
|
||||
*/
|
||||
public final TableField<LoottrackereventsRecord, String> TYPE = createField("TYPE", org.jooq.impl.SQLDataType.VARCHAR(255).nullable(false), this, "");
|
||||
|
||||
/**
|
||||
* The column <code>PUBLIC.LOOTTRACKEREVENTS.TIME</code>.
|
||||
*/
|
||||
public final TableField<LoottrackereventsRecord, Timestamp> TIME = createField("TIME", org.jooq.impl.SQLDataType.TIMESTAMP.precision(6).nullable(false), this, "");
|
||||
|
||||
/**
|
||||
* Create a <code>PUBLIC.LOOTTRACKEREVENTS</code> table reference
|
||||
*/
|
||||
public Loottrackerevents()
|
||||
{
|
||||
this(DSL.name("LOOTTRACKEREVENTS"), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an aliased <code>PUBLIC.LOOTTRACKEREVENTS</code> table reference
|
||||
*/
|
||||
public Loottrackerevents(String alias)
|
||||
{
|
||||
this(DSL.name(alias), LOOTTRACKEREVENTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an aliased <code>PUBLIC.LOOTTRACKEREVENTS</code> table reference
|
||||
*/
|
||||
public Loottrackerevents(Name alias)
|
||||
{
|
||||
this(alias, LOOTTRACKEREVENTS);
|
||||
}
|
||||
|
||||
private Loottrackerevents(Name alias, Table<LoottrackereventsRecord> aliased)
|
||||
{
|
||||
this(alias, aliased, null);
|
||||
}
|
||||
|
||||
private Loottrackerevents(Name alias, Table<LoottrackereventsRecord> aliased, Field<?>[] parameters)
|
||||
{
|
||||
super(alias, null, aliased, parameters, DSL.comment(""));
|
||||
}
|
||||
|
||||
public <O extends Record> Loottrackerevents(Table<O> child, ForeignKey<O, LoottrackereventsRecord> key)
|
||||
{
|
||||
super(child, key, LOOTTRACKEREVENTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Schema getSchema()
|
||||
{
|
||||
return Public.PUBLIC;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public List<Index> getIndexes()
|
||||
{
|
||||
return Arrays.<Index>asList(Indexes.PRIMARY_KEY_B);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public UniqueKey<LoottrackereventsRecord> getPrimaryKey()
|
||||
{
|
||||
return Keys.PK_EVENTUNIQUEID;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public List<UniqueKey<LoottrackereventsRecord>> getKeys()
|
||||
{
|
||||
return Arrays.<UniqueKey<LoottrackereventsRecord>>asList(Keys.PK_EVENTUNIQUEID);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Loottrackerevents as(String alias)
|
||||
{
|
||||
return new Loottrackerevents(DSL.name(alias), this);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Loottrackerevents as(Name alias)
|
||||
{
|
||||
return new Loottrackerevents(alias, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename this table
|
||||
*/
|
||||
@Override
|
||||
public Loottrackerevents rename(String name)
|
||||
{
|
||||
return new Loottrackerevents(DSL.name(name), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename this table
|
||||
*/
|
||||
@Override
|
||||
public Loottrackerevents rename(Name name)
|
||||
{
|
||||
return new Loottrackerevents(name, null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* This file is generated by jOOQ.
|
||||
*/
|
||||
package net.runelite.client.database.data.tables;
|
||||
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import javax.annotation.Generated;
|
||||
import net.runelite.client.database.data.Indexes;
|
||||
import net.runelite.client.database.data.Keys;
|
||||
import net.runelite.client.database.data.Public;
|
||||
import net.runelite.client.database.data.tables.records.LoottrackerlinkRecord;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.ForeignKey;
|
||||
import org.jooq.Index;
|
||||
import org.jooq.Name;
|
||||
import org.jooq.Record;
|
||||
import org.jooq.Schema;
|
||||
import org.jooq.Table;
|
||||
import org.jooq.TableField;
|
||||
import org.jooq.UniqueKey;
|
||||
import org.jooq.impl.DSL;
|
||||
import org.jooq.impl.TableImpl;
|
||||
|
||||
|
||||
/**
|
||||
* This class is generated by jOOQ.
|
||||
*/
|
||||
@Generated(
|
||||
value = {
|
||||
"http://www.jooq.org",
|
||||
"jOOQ version:3.11.12"
|
||||
},
|
||||
comments = "This class is generated by jOOQ"
|
||||
)
|
||||
@SuppressWarnings({"all", "unchecked", "rawtypes"})
|
||||
public class Loottrackerlink extends TableImpl<LoottrackerlinkRecord>
|
||||
{
|
||||
|
||||
private static final long serialVersionUID = 1145289106;
|
||||
|
||||
/**
|
||||
* The reference instance of <code>PUBLIC.LOOTTRACKERLINK</code>
|
||||
*/
|
||||
public static final Loottrackerlink LOOTTRACKERLINK = new Loottrackerlink();
|
||||
|
||||
/**
|
||||
* The class holding records for this type
|
||||
*/
|
||||
@Override
|
||||
public Class<LoottrackerlinkRecord> getRecordType()
|
||||
{
|
||||
return LoottrackerlinkRecord.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* The column <code>PUBLIC.LOOTTRACKERLINK.LINKUNIQUEID</code>.
|
||||
*/
|
||||
public final TableField<LoottrackerlinkRecord, UUID> LINKUNIQUEID = createField("LINKUNIQUEID", org.jooq.impl.SQLDataType.UUID.nullable(false), this, "");
|
||||
|
||||
/**
|
||||
* The column <code>PUBLIC.LOOTTRACKERLINK.EVENTUNIQUEID</code>.
|
||||
*/
|
||||
public final TableField<LoottrackerlinkRecord, UUID> EVENTUNIQUEID = createField("EVENTUNIQUEID", org.jooq.impl.SQLDataType.UUID.nullable(false), this, "");
|
||||
|
||||
/**
|
||||
* The column <code>PUBLIC.LOOTTRACKERLINK.DROPUNIQUEID</code>.
|
||||
*/
|
||||
public final TableField<LoottrackerlinkRecord, UUID> DROPUNIQUEID = createField("DROPUNIQUEID", org.jooq.impl.SQLDataType.UUID.nullable(false), this, "");
|
||||
|
||||
/**
|
||||
* The column <code>PUBLIC.LOOTTRACKERLINK.USERUNIQUEID</code>.
|
||||
*/
|
||||
public final TableField<LoottrackerlinkRecord, UUID> USERUNIQUEID = createField("USERUNIQUEID", org.jooq.impl.SQLDataType.UUID.nullable(false), this, "");
|
||||
|
||||
/**
|
||||
* Create a <code>PUBLIC.LOOTTRACKERLINK</code> table reference
|
||||
*/
|
||||
public Loottrackerlink()
|
||||
{
|
||||
this(DSL.name("LOOTTRACKERLINK"), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an aliased <code>PUBLIC.LOOTTRACKERLINK</code> table reference
|
||||
*/
|
||||
public Loottrackerlink(String alias)
|
||||
{
|
||||
this(DSL.name(alias), LOOTTRACKERLINK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an aliased <code>PUBLIC.LOOTTRACKERLINK</code> table reference
|
||||
*/
|
||||
public Loottrackerlink(Name alias)
|
||||
{
|
||||
this(alias, LOOTTRACKERLINK);
|
||||
}
|
||||
|
||||
private Loottrackerlink(Name alias, Table<LoottrackerlinkRecord> aliased)
|
||||
{
|
||||
this(alias, aliased, null);
|
||||
}
|
||||
|
||||
private Loottrackerlink(Name alias, Table<LoottrackerlinkRecord> aliased, Field<?>[] parameters)
|
||||
{
|
||||
super(alias, null, aliased, parameters, DSL.comment(""));
|
||||
}
|
||||
|
||||
public <O extends Record> Loottrackerlink(Table<O> child, ForeignKey<O, LoottrackerlinkRecord> key)
|
||||
{
|
||||
super(child, key, LOOTTRACKERLINK);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Schema getSchema()
|
||||
{
|
||||
return Public.PUBLIC;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public List<Index> getIndexes()
|
||||
{
|
||||
return Arrays.<Index>asList(Indexes.FK_LOOTTRACKEREVENT_INDEX_6, Indexes.FK_LOOTTRACKERLOOT_INDEX_6, Indexes.PRIMARY_KEY_6B);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public UniqueKey<LoottrackerlinkRecord> getPrimaryKey()
|
||||
{
|
||||
return Keys.PK_LOOTTRACKERLINK;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public List<UniqueKey<LoottrackerlinkRecord>> getKeys()
|
||||
{
|
||||
return Arrays.<UniqueKey<LoottrackerlinkRecord>>asList(Keys.PK_LOOTTRACKERLINK);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public List<ForeignKey<LoottrackerlinkRecord, ?>> getReferences()
|
||||
{
|
||||
return Arrays.<ForeignKey<LoottrackerlinkRecord, ?>>asList(Keys.FK_LOOTTRACKEREVENT, Keys.FK_LOOTTRACKERLOOT, Keys.FK_USER);
|
||||
}
|
||||
|
||||
public Loottrackerevents loottrackerevents()
|
||||
{
|
||||
return new Loottrackerevents(this, Keys.FK_LOOTTRACKEREVENT);
|
||||
}
|
||||
|
||||
public Loottrackerloot loottrackerloot()
|
||||
{
|
||||
return new Loottrackerloot(this, Keys.FK_LOOTTRACKERLOOT);
|
||||
}
|
||||
|
||||
public User user()
|
||||
{
|
||||
return new User(this, Keys.FK_USER);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Loottrackerlink as(String alias)
|
||||
{
|
||||
return new Loottrackerlink(DSL.name(alias), this);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Loottrackerlink as(Name alias)
|
||||
{
|
||||
return new Loottrackerlink(alias, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename this table
|
||||
*/
|
||||
@Override
|
||||
public Loottrackerlink rename(String name)
|
||||
{
|
||||
return new Loottrackerlink(DSL.name(name), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename this table
|
||||
*/
|
||||
@Override
|
||||
public Loottrackerlink rename(Name name)
|
||||
{
|
||||
return new Loottrackerlink(name, null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* This file is generated by jOOQ.
|
||||
*/
|
||||
package net.runelite.client.database.data.tables;
|
||||
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import javax.annotation.Generated;
|
||||
import net.runelite.client.database.data.Indexes;
|
||||
import net.runelite.client.database.data.Keys;
|
||||
import net.runelite.client.database.data.Public;
|
||||
import net.runelite.client.database.data.tables.records.LoottrackerlootRecord;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.ForeignKey;
|
||||
import org.jooq.Index;
|
||||
import org.jooq.Name;
|
||||
import org.jooq.Record;
|
||||
import org.jooq.Schema;
|
||||
import org.jooq.Table;
|
||||
import org.jooq.TableField;
|
||||
import org.jooq.UniqueKey;
|
||||
import org.jooq.impl.DSL;
|
||||
import org.jooq.impl.TableImpl;
|
||||
|
||||
|
||||
/**
|
||||
* This class is generated by jOOQ.
|
||||
*/
|
||||
@Generated(
|
||||
value = {
|
||||
"http://www.jooq.org",
|
||||
"jOOQ version:3.11.12"
|
||||
},
|
||||
comments = "This class is generated by jOOQ"
|
||||
)
|
||||
@SuppressWarnings({"all", "unchecked", "rawtypes"})
|
||||
public class Loottrackerloot extends TableImpl<LoottrackerlootRecord>
|
||||
{
|
||||
|
||||
private static final long serialVersionUID = 1952959378;
|
||||
|
||||
/**
|
||||
* The reference instance of <code>PUBLIC.LOOTTRACKERLOOT</code>
|
||||
*/
|
||||
public static final Loottrackerloot LOOTTRACKERLOOT = new Loottrackerloot();
|
||||
|
||||
/**
|
||||
* The class holding records for this type
|
||||
*/
|
||||
@Override
|
||||
public Class<LoottrackerlootRecord> getRecordType()
|
||||
{
|
||||
return LoottrackerlootRecord.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* The column <code>PUBLIC.LOOTTRACKERLOOT.UNIQUEID</code>.
|
||||
*/
|
||||
public final TableField<LoottrackerlootRecord, UUID> UNIQUEID = createField("UNIQUEID", org.jooq.impl.SQLDataType.UUID.nullable(false), this, "");
|
||||
|
||||
/**
|
||||
* The column <code>PUBLIC.LOOTTRACKERLOOT.ITEMID</code>.
|
||||
*/
|
||||
public final TableField<LoottrackerlootRecord, Integer> ITEMID = createField("ITEMID", org.jooq.impl.SQLDataType.INTEGER.nullable(false), this, "");
|
||||
|
||||
/**
|
||||
* The column <code>PUBLIC.LOOTTRACKERLOOT.QUANTITY</code>.
|
||||
*/
|
||||
public final TableField<LoottrackerlootRecord, Integer> QUANTITY = createField("QUANTITY", org.jooq.impl.SQLDataType.INTEGER.nullable(false), this, "");
|
||||
|
||||
/**
|
||||
* Create a <code>PUBLIC.LOOTTRACKERLOOT</code> table reference
|
||||
*/
|
||||
public Loottrackerloot()
|
||||
{
|
||||
this(DSL.name("LOOTTRACKERLOOT"), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an aliased <code>PUBLIC.LOOTTRACKERLOOT</code> table reference
|
||||
*/
|
||||
public Loottrackerloot(String alias)
|
||||
{
|
||||
this(DSL.name(alias), LOOTTRACKERLOOT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an aliased <code>PUBLIC.LOOTTRACKERLOOT</code> table reference
|
||||
*/
|
||||
public Loottrackerloot(Name alias)
|
||||
{
|
||||
this(alias, LOOTTRACKERLOOT);
|
||||
}
|
||||
|
||||
private Loottrackerloot(Name alias, Table<LoottrackerlootRecord> aliased)
|
||||
{
|
||||
this(alias, aliased, null);
|
||||
}
|
||||
|
||||
private Loottrackerloot(Name alias, Table<LoottrackerlootRecord> aliased, Field<?>[] parameters)
|
||||
{
|
||||
super(alias, null, aliased, parameters, DSL.comment(""));
|
||||
}
|
||||
|
||||
public <O extends Record> Loottrackerloot(Table<O> child, ForeignKey<O, LoottrackerlootRecord> key)
|
||||
{
|
||||
super(child, key, LOOTTRACKERLOOT);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Schema getSchema()
|
||||
{
|
||||
return Public.PUBLIC;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public List<Index> getIndexes()
|
||||
{
|
||||
return Arrays.<Index>asList(Indexes.PRIMARY_KEY_6);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public UniqueKey<LoottrackerlootRecord> getPrimaryKey()
|
||||
{
|
||||
return Keys.PK_LOOTUNIQUEID;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public List<UniqueKey<LoottrackerlootRecord>> getKeys()
|
||||
{
|
||||
return Arrays.<UniqueKey<LoottrackerlootRecord>>asList(Keys.PK_LOOTUNIQUEID);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Loottrackerloot as(String alias)
|
||||
{
|
||||
return new Loottrackerloot(DSL.name(alias), this);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Loottrackerloot as(Name alias)
|
||||
{
|
||||
return new Loottrackerloot(alias, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename this table
|
||||
*/
|
||||
@Override
|
||||
public Loottrackerloot rename(String name)
|
||||
{
|
||||
return new Loottrackerloot(DSL.name(name), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename this table
|
||||
*/
|
||||
@Override
|
||||
public Loottrackerloot rename(Name name)
|
||||
{
|
||||
return new Loottrackerloot(name, null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* This file is generated by jOOQ.
|
||||
*/
|
||||
package net.runelite.client.database.data.tables;
|
||||
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import javax.annotation.Generated;
|
||||
import net.runelite.client.database.data.Indexes;
|
||||
import net.runelite.client.database.data.Keys;
|
||||
import net.runelite.client.database.data.Public;
|
||||
import net.runelite.client.database.data.tables.records.UserRecord;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.ForeignKey;
|
||||
import org.jooq.Index;
|
||||
import org.jooq.Name;
|
||||
import org.jooq.Record;
|
||||
import org.jooq.Schema;
|
||||
import org.jooq.Table;
|
||||
import org.jooq.TableField;
|
||||
import org.jooq.UniqueKey;
|
||||
import org.jooq.impl.DSL;
|
||||
import org.jooq.impl.TableImpl;
|
||||
|
||||
|
||||
/**
|
||||
* This class is generated by jOOQ.
|
||||
*/
|
||||
@Generated(
|
||||
value = {
|
||||
"http://www.jooq.org",
|
||||
"jOOQ version:3.11.12"
|
||||
},
|
||||
comments = "This class is generated by jOOQ"
|
||||
)
|
||||
@SuppressWarnings({"all", "unchecked", "rawtypes"})
|
||||
public class User extends TableImpl<UserRecord>
|
||||
{
|
||||
|
||||
private static final long serialVersionUID = 270848699;
|
||||
|
||||
/**
|
||||
* The reference instance of <code>PUBLIC.USER</code>
|
||||
*/
|
||||
public static final User USER = new User();
|
||||
|
||||
/**
|
||||
* The class holding records for this type
|
||||
*/
|
||||
@Override
|
||||
public Class<UserRecord> getRecordType()
|
||||
{
|
||||
return UserRecord.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* The column <code>PUBLIC.USER.UNIQUEID</code>.
|
||||
*/
|
||||
public final TableField<UserRecord, UUID> UNIQUEID = createField("UNIQUEID", org.jooq.impl.SQLDataType.UUID.nullable(false), this, "");
|
||||
|
||||
/**
|
||||
* The column <code>PUBLIC.USER.USERNAME</code>.
|
||||
*/
|
||||
public final TableField<UserRecord, String> USERNAME = createField("USERNAME", org.jooq.impl.SQLDataType.VARCHAR(12).nullable(false), this, "");
|
||||
|
||||
/**
|
||||
* Create a <code>PUBLIC.USER</code> table reference
|
||||
*/
|
||||
public User()
|
||||
{
|
||||
this(DSL.name("USER"), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an aliased <code>PUBLIC.USER</code> table reference
|
||||
*/
|
||||
public User(String alias)
|
||||
{
|
||||
this(DSL.name(alias), USER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an aliased <code>PUBLIC.USER</code> table reference
|
||||
*/
|
||||
public User(Name alias)
|
||||
{
|
||||
this(alias, USER);
|
||||
}
|
||||
|
||||
private User(Name alias, Table<UserRecord> aliased)
|
||||
{
|
||||
this(alias, aliased, null);
|
||||
}
|
||||
|
||||
private User(Name alias, Table<UserRecord> aliased, Field<?>[] parameters)
|
||||
{
|
||||
super(alias, null, aliased, parameters, DSL.comment(""));
|
||||
}
|
||||
|
||||
public <O extends Record> User(Table<O> child, ForeignKey<O, UserRecord> key)
|
||||
{
|
||||
super(child, key, USER);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Schema getSchema()
|
||||
{
|
||||
return Public.PUBLIC;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public List<Index> getIndexes()
|
||||
{
|
||||
return Arrays.<Index>asList(Indexes.PRIMARY_KEY_2);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public UniqueKey<UserRecord> getPrimaryKey()
|
||||
{
|
||||
return Keys.PK_USER;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public List<UniqueKey<UserRecord>> getKeys()
|
||||
{
|
||||
return Arrays.<UniqueKey<UserRecord>>asList(Keys.PK_USER);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public User as(String alias)
|
||||
{
|
||||
return new User(DSL.name(alias), this);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public User as(Name alias)
|
||||
{
|
||||
return new User(alias, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename this table
|
||||
*/
|
||||
@Override
|
||||
public User rename(String name)
|
||||
{
|
||||
return new User(DSL.name(name), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename this table
|
||||
*/
|
||||
@Override
|
||||
public User rename(Name name)
|
||||
{
|
||||
return new User(name, null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,318 @@
|
||||
/*
|
||||
* This file is generated by jOOQ.
|
||||
*/
|
||||
package net.runelite.client.database.data.tables.records;
|
||||
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.UUID;
|
||||
import javax.annotation.Generated;
|
||||
import net.runelite.client.database.data.tables.Loottrackerevents;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.Record1;
|
||||
import org.jooq.Record4;
|
||||
import org.jooq.Row4;
|
||||
import org.jooq.impl.UpdatableRecordImpl;
|
||||
|
||||
|
||||
/**
|
||||
* This class is generated by jOOQ.
|
||||
*/
|
||||
@Generated(
|
||||
value = {
|
||||
"http://www.jooq.org",
|
||||
"jOOQ version:3.11.12"
|
||||
},
|
||||
comments = "This class is generated by jOOQ"
|
||||
)
|
||||
@SuppressWarnings({"all", "unchecked", "rawtypes"})
|
||||
public class LoottrackereventsRecord extends UpdatableRecordImpl<LoottrackereventsRecord> implements Record4<UUID, String, String, Timestamp>
|
||||
{
|
||||
|
||||
private static final long serialVersionUID = -1505143967;
|
||||
|
||||
/**
|
||||
* Setter for <code>PUBLIC.LOOTTRACKEREVENTS.UNIQUEID</code>.
|
||||
*/
|
||||
public void setUniqueid(UUID value)
|
||||
{
|
||||
set(0, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for <code>PUBLIC.LOOTTRACKEREVENTS.UNIQUEID</code>.
|
||||
*/
|
||||
public UUID getUniqueid()
|
||||
{
|
||||
return (UUID) get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for <code>PUBLIC.LOOTTRACKEREVENTS.EVENTID</code>.
|
||||
*/
|
||||
public void setEventid(String value)
|
||||
{
|
||||
set(1, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for <code>PUBLIC.LOOTTRACKEREVENTS.EVENTID</code>.
|
||||
*/
|
||||
public String getEventid()
|
||||
{
|
||||
return (String) get(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for <code>PUBLIC.LOOTTRACKEREVENTS.TYPE</code>.
|
||||
*/
|
||||
public void setType(String value)
|
||||
{
|
||||
set(2, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for <code>PUBLIC.LOOTTRACKEREVENTS.TYPE</code>.
|
||||
*/
|
||||
public String getType()
|
||||
{
|
||||
return (String) get(2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for <code>PUBLIC.LOOTTRACKEREVENTS.TIME</code>.
|
||||
*/
|
||||
public void setTime(Timestamp value)
|
||||
{
|
||||
set(3, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for <code>PUBLIC.LOOTTRACKEREVENTS.TIME</code>.
|
||||
*/
|
||||
public Timestamp getTime()
|
||||
{
|
||||
return (Timestamp) get(3);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Primary key information
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Record1<UUID> key()
|
||||
{
|
||||
return (Record1) super.key();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Record4 type implementation
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Row4<UUID, String, String, Timestamp> fieldsRow()
|
||||
{
|
||||
return (Row4) super.fieldsRow();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Row4<UUID, String, String, Timestamp> valuesRow()
|
||||
{
|
||||
return (Row4) super.valuesRow();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Field<UUID> field1()
|
||||
{
|
||||
return Loottrackerevents.LOOTTRACKEREVENTS.UNIQUEID;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Field<String> field2()
|
||||
{
|
||||
return Loottrackerevents.LOOTTRACKEREVENTS.EVENTID;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Field<String> field3()
|
||||
{
|
||||
return Loottrackerevents.LOOTTRACKEREVENTS.TYPE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Field<Timestamp> field4()
|
||||
{
|
||||
return Loottrackerevents.LOOTTRACKEREVENTS.TIME;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public UUID component1()
|
||||
{
|
||||
return getUniqueid();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String component2()
|
||||
{
|
||||
return getEventid();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String component3()
|
||||
{
|
||||
return getType();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Timestamp component4()
|
||||
{
|
||||
return getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public UUID value1()
|
||||
{
|
||||
return getUniqueid();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String value2()
|
||||
{
|
||||
return getEventid();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String value3()
|
||||
{
|
||||
return getType();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Timestamp value4()
|
||||
{
|
||||
return getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public LoottrackereventsRecord value1(UUID value)
|
||||
{
|
||||
setUniqueid(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public LoottrackereventsRecord value2(String value)
|
||||
{
|
||||
setEventid(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public LoottrackereventsRecord value3(String value)
|
||||
{
|
||||
setType(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public LoottrackereventsRecord value4(Timestamp value)
|
||||
{
|
||||
setTime(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public LoottrackereventsRecord values(UUID value1, String value2, String value3, Timestamp value4)
|
||||
{
|
||||
value1(value1);
|
||||
value2(value2);
|
||||
value3(value3);
|
||||
value4(value4);
|
||||
return this;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Constructors
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Create a detached LoottrackereventsRecord
|
||||
*/
|
||||
public LoottrackereventsRecord()
|
||||
{
|
||||
super(Loottrackerevents.LOOTTRACKEREVENTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a detached, initialised LoottrackereventsRecord
|
||||
*/
|
||||
public LoottrackereventsRecord(UUID uniqueid, String eventid, String type, Timestamp time)
|
||||
{
|
||||
super(Loottrackerevents.LOOTTRACKEREVENTS);
|
||||
|
||||
set(0, uniqueid);
|
||||
set(1, eventid);
|
||||
set(2, type);
|
||||
set(3, time);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
* This file is generated by jOOQ.
|
||||
*/
|
||||
package net.runelite.client.database.data.tables.records;
|
||||
|
||||
|
||||
import java.util.UUID;
|
||||
import javax.annotation.Generated;
|
||||
import net.runelite.client.database.data.tables.Loottrackerlink;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.Record1;
|
||||
import org.jooq.Record4;
|
||||
import org.jooq.Row4;
|
||||
import org.jooq.impl.UpdatableRecordImpl;
|
||||
|
||||
|
||||
/**
|
||||
* This class is generated by jOOQ.
|
||||
*/
|
||||
@Generated(
|
||||
value = {
|
||||
"http://www.jooq.org",
|
||||
"jOOQ version:3.11.12"
|
||||
},
|
||||
comments = "This class is generated by jOOQ"
|
||||
)
|
||||
@SuppressWarnings({"all", "unchecked", "rawtypes"})
|
||||
public class LoottrackerlinkRecord extends UpdatableRecordImpl<LoottrackerlinkRecord> implements Record4<UUID, UUID, UUID, UUID>
|
||||
{
|
||||
|
||||
private static final long serialVersionUID = 1985117517;
|
||||
|
||||
/**
|
||||
* Setter for <code>PUBLIC.LOOTTRACKERLINK.LINKUNIQUEID</code>.
|
||||
*/
|
||||
public void setLinkuniqueid(UUID value)
|
||||
{
|
||||
set(0, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for <code>PUBLIC.LOOTTRACKERLINK.LINKUNIQUEID</code>.
|
||||
*/
|
||||
public UUID getLinkuniqueid()
|
||||
{
|
||||
return (UUID) get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for <code>PUBLIC.LOOTTRACKERLINK.EVENTUNIQUEID</code>.
|
||||
*/
|
||||
public void setEventuniqueid(UUID value)
|
||||
{
|
||||
set(1, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for <code>PUBLIC.LOOTTRACKERLINK.EVENTUNIQUEID</code>.
|
||||
*/
|
||||
public UUID getEventuniqueid()
|
||||
{
|
||||
return (UUID) get(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for <code>PUBLIC.LOOTTRACKERLINK.DROPUNIQUEID</code>.
|
||||
*/
|
||||
public void setDropuniqueid(UUID value)
|
||||
{
|
||||
set(2, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for <code>PUBLIC.LOOTTRACKERLINK.DROPUNIQUEID</code>.
|
||||
*/
|
||||
public UUID getDropuniqueid()
|
||||
{
|
||||
return (UUID) get(2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for <code>PUBLIC.LOOTTRACKERLINK.USERUNIQUEID</code>.
|
||||
*/
|
||||
public void setUseruniqueid(UUID value)
|
||||
{
|
||||
set(3, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for <code>PUBLIC.LOOTTRACKERLINK.USERUNIQUEID</code>.
|
||||
*/
|
||||
public UUID getUseruniqueid()
|
||||
{
|
||||
return (UUID) get(3);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Primary key information
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Record1<UUID> key()
|
||||
{
|
||||
return (Record1) super.key();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Record4 type implementation
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Row4<UUID, UUID, UUID, UUID> fieldsRow()
|
||||
{
|
||||
return (Row4) super.fieldsRow();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Row4<UUID, UUID, UUID, UUID> valuesRow()
|
||||
{
|
||||
return (Row4) super.valuesRow();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Field<UUID> field1()
|
||||
{
|
||||
return Loottrackerlink.LOOTTRACKERLINK.LINKUNIQUEID;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Field<UUID> field2()
|
||||
{
|
||||
return Loottrackerlink.LOOTTRACKERLINK.EVENTUNIQUEID;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Field<UUID> field3()
|
||||
{
|
||||
return Loottrackerlink.LOOTTRACKERLINK.DROPUNIQUEID;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Field<UUID> field4()
|
||||
{
|
||||
return Loottrackerlink.LOOTTRACKERLINK.USERUNIQUEID;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public UUID component1()
|
||||
{
|
||||
return getLinkuniqueid();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public UUID component2()
|
||||
{
|
||||
return getEventuniqueid();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public UUID component3()
|
||||
{
|
||||
return getDropuniqueid();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public UUID component4()
|
||||
{
|
||||
return getUseruniqueid();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public UUID value1()
|
||||
{
|
||||
return getLinkuniqueid();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public UUID value2()
|
||||
{
|
||||
return getEventuniqueid();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public UUID value3()
|
||||
{
|
||||
return getDropuniqueid();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public UUID value4()
|
||||
{
|
||||
return getUseruniqueid();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public LoottrackerlinkRecord value1(UUID value)
|
||||
{
|
||||
setLinkuniqueid(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public LoottrackerlinkRecord value2(UUID value)
|
||||
{
|
||||
setEventuniqueid(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public LoottrackerlinkRecord value3(UUID value)
|
||||
{
|
||||
setDropuniqueid(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public LoottrackerlinkRecord value4(UUID value)
|
||||
{
|
||||
setUseruniqueid(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public LoottrackerlinkRecord values(UUID value1, UUID value2, UUID value3, UUID value4)
|
||||
{
|
||||
value1(value1);
|
||||
value2(value2);
|
||||
value3(value3);
|
||||
value4(value4);
|
||||
return this;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Constructors
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Create a detached LoottrackerlinkRecord
|
||||
*/
|
||||
public LoottrackerlinkRecord()
|
||||
{
|
||||
super(Loottrackerlink.LOOTTRACKERLINK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a detached, initialised LoottrackerlinkRecord
|
||||
*/
|
||||
public LoottrackerlinkRecord(UUID linkuniqueid, UUID eventuniqueid, UUID dropuniqueid, UUID useruniqueid)
|
||||
{
|
||||
super(Loottrackerlink.LOOTTRACKERLINK);
|
||||
|
||||
set(0, linkuniqueid);
|
||||
set(1, eventuniqueid);
|
||||
set(2, dropuniqueid);
|
||||
set(3, useruniqueid);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
* This file is generated by jOOQ.
|
||||
*/
|
||||
package net.runelite.client.database.data.tables.records;
|
||||
|
||||
|
||||
import java.util.UUID;
|
||||
import javax.annotation.Generated;
|
||||
import net.runelite.client.database.data.tables.Loottrackerloot;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.Record1;
|
||||
import org.jooq.Record3;
|
||||
import org.jooq.Row3;
|
||||
import org.jooq.impl.UpdatableRecordImpl;
|
||||
|
||||
|
||||
/**
|
||||
* This class is generated by jOOQ.
|
||||
*/
|
||||
@Generated(
|
||||
value = {
|
||||
"http://www.jooq.org",
|
||||
"jOOQ version:3.11.12"
|
||||
},
|
||||
comments = "This class is generated by jOOQ"
|
||||
)
|
||||
@SuppressWarnings({"all", "unchecked", "rawtypes"})
|
||||
public class LoottrackerlootRecord extends UpdatableRecordImpl<LoottrackerlootRecord> implements Record3<UUID, Integer, Integer>
|
||||
{
|
||||
|
||||
private static final long serialVersionUID = -1894768090;
|
||||
|
||||
/**
|
||||
* Setter for <code>PUBLIC.LOOTTRACKERLOOT.UNIQUEID</code>.
|
||||
*/
|
||||
public void setUniqueid(UUID value)
|
||||
{
|
||||
set(0, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for <code>PUBLIC.LOOTTRACKERLOOT.UNIQUEID</code>.
|
||||
*/
|
||||
public UUID getUniqueid()
|
||||
{
|
||||
return (UUID) get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for <code>PUBLIC.LOOTTRACKERLOOT.ITEMID</code>.
|
||||
*/
|
||||
public void setItemid(Integer value)
|
||||
{
|
||||
set(1, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for <code>PUBLIC.LOOTTRACKERLOOT.ITEMID</code>.
|
||||
*/
|
||||
public Integer getItemid()
|
||||
{
|
||||
return (Integer) get(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for <code>PUBLIC.LOOTTRACKERLOOT.QUANTITY</code>.
|
||||
*/
|
||||
public void setQuantity(Integer value)
|
||||
{
|
||||
set(2, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for <code>PUBLIC.LOOTTRACKERLOOT.QUANTITY</code>.
|
||||
*/
|
||||
public Integer getQuantity()
|
||||
{
|
||||
return (Integer) get(2);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Primary key information
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Record1<UUID> key()
|
||||
{
|
||||
return (Record1) super.key();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Record3 type implementation
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Row3<UUID, Integer, Integer> fieldsRow()
|
||||
{
|
||||
return (Row3) super.fieldsRow();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Row3<UUID, Integer, Integer> valuesRow()
|
||||
{
|
||||
return (Row3) super.valuesRow();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Field<UUID> field1()
|
||||
{
|
||||
return Loottrackerloot.LOOTTRACKERLOOT.UNIQUEID;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Field<Integer> field2()
|
||||
{
|
||||
return Loottrackerloot.LOOTTRACKERLOOT.ITEMID;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Field<Integer> field3()
|
||||
{
|
||||
return Loottrackerloot.LOOTTRACKERLOOT.QUANTITY;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public UUID component1()
|
||||
{
|
||||
return getUniqueid();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Integer component2()
|
||||
{
|
||||
return getItemid();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Integer component3()
|
||||
{
|
||||
return getQuantity();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public UUID value1()
|
||||
{
|
||||
return getUniqueid();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Integer value2()
|
||||
{
|
||||
return getItemid();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Integer value3()
|
||||
{
|
||||
return getQuantity();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public LoottrackerlootRecord value1(UUID value)
|
||||
{
|
||||
setUniqueid(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public LoottrackerlootRecord value2(Integer value)
|
||||
{
|
||||
setItemid(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public LoottrackerlootRecord value3(Integer value)
|
||||
{
|
||||
setQuantity(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public LoottrackerlootRecord values(UUID value1, Integer value2, Integer value3)
|
||||
{
|
||||
value1(value1);
|
||||
value2(value2);
|
||||
value3(value3);
|
||||
return this;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Constructors
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Create a detached LoottrackerlootRecord
|
||||
*/
|
||||
public LoottrackerlootRecord()
|
||||
{
|
||||
super(Loottrackerloot.LOOTTRACKERLOOT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a detached, initialised LoottrackerlootRecord
|
||||
*/
|
||||
public LoottrackerlootRecord(UUID uniqueid, Integer itemid, Integer quantity)
|
||||
{
|
||||
super(Loottrackerloot.LOOTTRACKERLOOT);
|
||||
|
||||
set(0, uniqueid);
|
||||
set(1, itemid);
|
||||
set(2, quantity);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* This file is generated by jOOQ.
|
||||
*/
|
||||
package net.runelite.client.database.data.tables.records;
|
||||
|
||||
|
||||
import java.util.UUID;
|
||||
import javax.annotation.Generated;
|
||||
import net.runelite.client.database.data.tables.User;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.Record1;
|
||||
import org.jooq.Record2;
|
||||
import org.jooq.Row2;
|
||||
import org.jooq.impl.UpdatableRecordImpl;
|
||||
|
||||
|
||||
/**
|
||||
* This class is generated by jOOQ.
|
||||
*/
|
||||
@Generated(
|
||||
value = {
|
||||
"http://www.jooq.org",
|
||||
"jOOQ version:3.11.12"
|
||||
},
|
||||
comments = "This class is generated by jOOQ"
|
||||
)
|
||||
@SuppressWarnings({"all", "unchecked", "rawtypes"})
|
||||
public class UserRecord extends UpdatableRecordImpl<UserRecord> implements Record2<UUID, String>
|
||||
{
|
||||
|
||||
private static final long serialVersionUID = 628808107;
|
||||
|
||||
/**
|
||||
* Setter for <code>PUBLIC.USER.UNIQUEID</code>.
|
||||
*/
|
||||
public void setUniqueid(UUID value)
|
||||
{
|
||||
set(0, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for <code>PUBLIC.USER.UNIQUEID</code>.
|
||||
*/
|
||||
public UUID getUniqueid()
|
||||
{
|
||||
return (UUID) get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for <code>PUBLIC.USER.USERNAME</code>.
|
||||
*/
|
||||
public void setUsername(String value)
|
||||
{
|
||||
set(1, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for <code>PUBLIC.USER.USERNAME</code>.
|
||||
*/
|
||||
public String getUsername()
|
||||
{
|
||||
return (String) get(1);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Primary key information
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Record1<UUID> key()
|
||||
{
|
||||
return (Record1) super.key();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Record2 type implementation
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Row2<UUID, String> fieldsRow()
|
||||
{
|
||||
return (Row2) super.fieldsRow();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Row2<UUID, String> valuesRow()
|
||||
{
|
||||
return (Row2) super.valuesRow();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Field<UUID> field1()
|
||||
{
|
||||
return User.USER.UNIQUEID;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Field<String> field2()
|
||||
{
|
||||
return User.USER.USERNAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public UUID component1()
|
||||
{
|
||||
return getUniqueid();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String component2()
|
||||
{
|
||||
return getUsername();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public UUID value1()
|
||||
{
|
||||
return getUniqueid();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String value2()
|
||||
{
|
||||
return getUsername();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public UserRecord value1(UUID value)
|
||||
{
|
||||
setUniqueid(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public UserRecord value2(String value)
|
||||
{
|
||||
setUsername(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public UserRecord values(UUID value1, String value2)
|
||||
{
|
||||
value1(value1);
|
||||
value2(value2);
|
||||
return this;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Constructors
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Create a detached UserRecord
|
||||
*/
|
||||
public UserRecord()
|
||||
{
|
||||
super(User.USER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a detached, initialised UserRecord
|
||||
*/
|
||||
public UserRecord(UUID uniqueid, String username)
|
||||
{
|
||||
super(User.USER);
|
||||
|
||||
set(0, uniqueid);
|
||||
set(1, username);
|
||||
}
|
||||
}
|
||||
@@ -195,7 +195,7 @@ public class DiscordService implements AutoCloseable
|
||||
{
|
||||
log.info("Discord RPC service is ready with user {}.", user.username);
|
||||
currentUser = user;
|
||||
eventBus.post(new DiscordReady(
|
||||
eventBus.post(DiscordReady.class, new DiscordReady(
|
||||
user.userId,
|
||||
user.username,
|
||||
user.discriminator,
|
||||
@@ -204,28 +204,28 @@ public class DiscordService implements AutoCloseable
|
||||
|
||||
private void disconnected(int errorCode, String message)
|
||||
{
|
||||
eventBus.post(new DiscordDisconnected(errorCode, message));
|
||||
eventBus.post(DiscordDisconnected.class, new DiscordDisconnected(errorCode, message));
|
||||
}
|
||||
|
||||
private void errored(int errorCode, String message)
|
||||
{
|
||||
log.warn("Discord error: {} - {}", errorCode, message);
|
||||
eventBus.post(new DiscordErrored(errorCode, message));
|
||||
eventBus.post(DiscordErrored.class, new DiscordErrored(errorCode, message));
|
||||
}
|
||||
|
||||
private void joinGame(String joinSecret)
|
||||
{
|
||||
eventBus.post(new DiscordJoinGame(joinSecret));
|
||||
eventBus.post(DiscordJoinGame.class, new DiscordJoinGame(joinSecret));
|
||||
}
|
||||
|
||||
private void spectateGame(String spectateSecret)
|
||||
{
|
||||
eventBus.post(new DiscordSpectateGame(spectateSecret));
|
||||
eventBus.post(DiscordSpectateGame.class, new DiscordSpectateGame(spectateSecret));
|
||||
}
|
||||
|
||||
private void joinRequest(DiscordUser user)
|
||||
{
|
||||
eventBus.post(new DiscordJoinRequest(
|
||||
eventBus.post(DiscordJoinRequest.class, new DiscordJoinRequest(
|
||||
user.userId,
|
||||
user.username,
|
||||
user.discriminator,
|
||||
|
||||
@@ -25,12 +25,13 @@
|
||||
package net.runelite.client.discord.events;
|
||||
|
||||
import lombok.Value;
|
||||
import net.runelite.api.events.Event;
|
||||
|
||||
/**
|
||||
* Called when the RPC connection has been severed
|
||||
*/
|
||||
@Value
|
||||
public class DiscordDisconnected
|
||||
public class DiscordDisconnected implements Event
|
||||
{
|
||||
/**
|
||||
* Discord error code
|
||||
|
||||
@@ -25,12 +25,13 @@
|
||||
package net.runelite.client.discord.events;
|
||||
|
||||
import lombok.Value;
|
||||
import net.runelite.api.events.Event;
|
||||
|
||||
/**
|
||||
* Called when an internal error is caught within the SDK
|
||||
*/
|
||||
@Value
|
||||
public class DiscordErrored
|
||||
public class DiscordErrored implements Event
|
||||
{
|
||||
/**
|
||||
* Discord error code.
|
||||
|
||||
@@ -25,12 +25,13 @@
|
||||
package net.runelite.client.discord.events;
|
||||
|
||||
import lombok.Value;
|
||||
import net.runelite.api.events.Event;
|
||||
|
||||
/**
|
||||
* Called when the logged in user joined a game
|
||||
*/
|
||||
@Value
|
||||
public class DiscordJoinGame
|
||||
public class DiscordJoinGame implements Event
|
||||
{
|
||||
/**
|
||||
* Obfuscated data of your choosing used as join secret
|
||||
|
||||
@@ -25,12 +25,13 @@
|
||||
package net.runelite.client.discord.events;
|
||||
|
||||
import lombok.Value;
|
||||
import net.runelite.api.events.Event;
|
||||
|
||||
/**
|
||||
* Called when another discord user wants to join the game of the logged in user
|
||||
*/
|
||||
@Value
|
||||
public class DiscordJoinRequest
|
||||
public class DiscordJoinRequest implements Event
|
||||
{
|
||||
/**
|
||||
* The userId for the user that requests to join
|
||||
|
||||
@@ -25,12 +25,13 @@
|
||||
package net.runelite.client.discord.events;
|
||||
|
||||
import lombok.Value;
|
||||
import net.runelite.api.events.Event;
|
||||
|
||||
/**
|
||||
* Called when the RPC connection has been established
|
||||
*/
|
||||
@Value
|
||||
public class DiscordReady
|
||||
public class DiscordReady implements Event
|
||||
{
|
||||
/**
|
||||
* The userId for the active user
|
||||
|
||||
@@ -25,12 +25,13 @@
|
||||
package net.runelite.client.discord.events;
|
||||
|
||||
import lombok.Value;
|
||||
import net.runelite.api.events.Event;
|
||||
|
||||
/**
|
||||
* Called when the logged in user joined to spectate a game
|
||||
*/
|
||||
@Value
|
||||
public class DiscordSpectateGame
|
||||
public class DiscordSpectateGame implements Event
|
||||
{
|
||||
/**
|
||||
* Obfuscated data of your choosing used as spectate secret
|
||||
|
||||
@@ -1,249 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
|
||||
* 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.eventbus;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import java.lang.invoke.CallSite;
|
||||
import java.lang.invoke.LambdaMetafactory;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.function.Consumer;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Value;
|
||||
import com.jakewharton.rxrelay2.PublishRelay;
|
||||
import com.jakewharton.rxrelay2.Relay;
|
||||
import io.reactivex.annotations.NonNull;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
import io.reactivex.functions.Consumer;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import javax.inject.Singleton;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.events.Event;
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@ThreadSafe
|
||||
public class EventBus
|
||||
@Singleton
|
||||
public class EventBus implements EventBusInterface
|
||||
{
|
||||
@FunctionalInterface
|
||||
public interface SubscriberMethod
|
||||
private Map<Object, Object> subscriptionList = new HashMap<>();
|
||||
private Map<Class<?>, Relay<Object>> subjectList = new HashMap<>();
|
||||
private Map<Object, CompositeDisposable> subscriptionsMap = new HashMap<>();
|
||||
|
||||
@NonNull
|
||||
private <T> Relay<Object> getSubject(Class<T> eventClass)
|
||||
{
|
||||
void invoke(Object event);
|
||||
return subjectList.computeIfAbsent(eventClass, k -> PublishRelay.create().toSerialized());
|
||||
}
|
||||
|
||||
@Value
|
||||
private static class Subscriber
|
||||
@NonNull
|
||||
private CompositeDisposable getCompositeDisposable(@NonNull Object object)
|
||||
{
|
||||
private final Object object;
|
||||
private final Method method;
|
||||
@EqualsAndHashCode.Exclude
|
||||
private final SubscriberMethod lamda;
|
||||
|
||||
void invoke(final Object arg) throws Exception
|
||||
CompositeDisposable compositeDisposable = subscriptionsMap.get(object);
|
||||
if (compositeDisposable == null)
|
||||
{
|
||||
if (lamda != null)
|
||||
{
|
||||
lamda.invoke(arg);
|
||||
}
|
||||
else
|
||||
{
|
||||
method.invoke(object, arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final Consumer<Throwable> exceptionHandler;
|
||||
private ImmutableMultimap<Class, Subscriber> subscribers = ImmutableMultimap.of();
|
||||
|
||||
/**
|
||||
* Instantiates EventBus with default exception handler
|
||||
*/
|
||||
public EventBus()
|
||||
{
|
||||
this((e) -> log.warn("Uncaught exception in event subscriber", e));
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers subscriber to EventBus. All methods in subscriber and it's parent classes are checked for
|
||||
* {@link Subscribe} annotation and then added to map of subscriptions.
|
||||
*
|
||||
* @param object subscriber to register
|
||||
* @throws IllegalArgumentException in case subscriber method name is wrong (correct format is 'on' + EventName
|
||||
*/
|
||||
public synchronized void register(@Nonnull final Object object)
|
||||
{
|
||||
final ImmutableMultimap.Builder<Class, Subscriber> builder = ImmutableMultimap.builder();
|
||||
|
||||
if (subscribers != null)
|
||||
{
|
||||
builder.putAll(subscribers);
|
||||
compositeDisposable = new CompositeDisposable();
|
||||
subscriptionsMap.put(object, compositeDisposable);
|
||||
}
|
||||
|
||||
for (Class<?> clazz = object.getClass(); clazz != null; clazz = clazz.getSuperclass())
|
||||
{
|
||||
for (final Method method : clazz.getDeclaredMethods())
|
||||
{
|
||||
final Subscribe sub = method.getAnnotation(Subscribe.class);
|
||||
|
||||
if (sub == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Preconditions.checkArgument(method.getReturnType() == Void.TYPE, "@Subscribed method \"" + method + "\" cannot return a value");
|
||||
Preconditions.checkArgument(method.getParameterCount() == 1, "@Subscribed method \"" + method + "\" must take exactly 1 argument");
|
||||
Preconditions.checkArgument(!Modifier.isStatic(method.getModifiers()), "@Subscribed method \"" + method + "\" cannot be static");
|
||||
|
||||
final Class<?> parameterClazz = method.getParameterTypes()[0];
|
||||
|
||||
Preconditions.checkArgument(!parameterClazz.isPrimitive(), "@Subscribed method \"" + method + "\" cannot subscribe to primitives");
|
||||
Preconditions.checkArgument((parameterClazz.getModifiers() & (Modifier.ABSTRACT | Modifier.INTERFACE)) == 0, "@Subscribed method \"" + method + "\" cannot subscribe to polymorphic classes");
|
||||
|
||||
for (Class<?> psc = parameterClazz.getSuperclass(); psc != null; psc = psc.getSuperclass())
|
||||
{
|
||||
if (subscribers.containsKey(psc))
|
||||
{
|
||||
throw new IllegalArgumentException("@Subscribed method \"" + method + "\" cannot subscribe to class which inherits from subscribed class \"" + psc + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
final String preferredName = "on" + parameterClazz.getSimpleName();
|
||||
Preconditions.checkArgument(method.getName().equals(preferredName), "Subscribed method " + method + " should be named " + preferredName);
|
||||
|
||||
method.setAccessible(true);
|
||||
SubscriberMethod lambda = null;
|
||||
|
||||
try
|
||||
{
|
||||
final MethodHandles.Lookup caller = privateLookupIn(clazz);
|
||||
final MethodType subscription = MethodType.methodType(void.class, parameterClazz);
|
||||
final MethodHandle target = caller.findVirtual(clazz, method.getName(), subscription);
|
||||
final CallSite site = LambdaMetafactory.metafactory(
|
||||
caller,
|
||||
"invoke",
|
||||
MethodType.methodType(SubscriberMethod.class, clazz),
|
||||
subscription.changeParameterType(0, Object.class),
|
||||
target,
|
||||
subscription);
|
||||
|
||||
final MethodHandle factory = site.getTarget();
|
||||
lambda = (SubscriberMethod) factory.bindTo(object).invokeExact();
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
log.warn("Unable to create lambda for method {}", method, e);
|
||||
}
|
||||
|
||||
final Subscriber subscriber = new Subscriber(object, method, lambda);
|
||||
builder.put(parameterClazz, subscriber);
|
||||
log.debug("Registering {} - {}", parameterClazz, subscriber);
|
||||
}
|
||||
}
|
||||
|
||||
subscribers = builder.build();
|
||||
return compositeDisposable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters all subscribed methods from provided subscriber object.
|
||||
*
|
||||
* @param object object to unsubscribe from
|
||||
*/
|
||||
public synchronized void unregister(@Nonnull final Object object)
|
||||
@Override
|
||||
// Subscribe on lifecycle (for example from plugin startUp -> shutdown)
|
||||
public <T> void subscribe(Class<T> eventClass, @NonNull Object lifecycle, @NonNull Consumer<T> action)
|
||||
{
|
||||
if (subscribers == null)
|
||||
if (subscriptionList.containsKey(lifecycle) && eventClass.equals(subscriptionList.get(lifecycle)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final Multimap<Class, Subscriber> map = HashMultimap.create();
|
||||
map.putAll(subscribers);
|
||||
|
||||
for (Class<?> clazz = object.getClass(); clazz != null; clazz = clazz.getSuperclass())
|
||||
{
|
||||
for (final Method method : clazz.getDeclaredMethods())
|
||||
Disposable disposable = getSubject(eventClass)
|
||||
.filter(Objects::nonNull) // Filter out null objects, better safe than sorry
|
||||
.cast(eventClass) // Cast it for easier usage
|
||||
.subscribe(action, error ->
|
||||
{
|
||||
final Subscribe sub = method.getAnnotation(Subscribe.class);
|
||||
log.error("Error in eventbus: {}", error.getMessage());
|
||||
log.error(ExceptionUtils.getStackTrace(error));
|
||||
});
|
||||
|
||||
if (sub == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
final Class<?> parameterClazz = method.getParameterTypes()[0];
|
||||
map.remove(parameterClazz, new Subscriber(object, method, null));
|
||||
}
|
||||
}
|
||||
|
||||
subscribers = ImmutableMultimap.copyOf(map);
|
||||
getCompositeDisposable(lifecycle).add(disposable);
|
||||
subscriptionList.put(lifecycle, eventClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Posts provided event to all registered subscribers. Subscriber calls are invoked immediately and in order
|
||||
* in which subscribers were registered.
|
||||
*
|
||||
* @param event event to post
|
||||
*/
|
||||
public void post(@Nonnull final Object event)
|
||||
@Override
|
||||
public void unregister(@NonNull Object lifecycle)
|
||||
{
|
||||
for (final Subscriber subscriber : subscribers.get(event.getClass()))
|
||||
//We have to remove the composition from the map, because once you dispose it can't be used anymore
|
||||
CompositeDisposable compositeDisposable = subscriptionsMap.remove(lifecycle);
|
||||
subscriptionList.remove(lifecycle);
|
||||
if (compositeDisposable != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
subscriber.invoke(event);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
exceptionHandler.accept(e);
|
||||
}
|
||||
compositeDisposable.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private static MethodHandles.Lookup privateLookupIn(Class clazz) throws IllegalAccessException, NoSuchFieldException, InvocationTargetException
|
||||
@Override
|
||||
public <T> void post(Class<T> eventClass, @NonNull Event event)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Java 9+ has privateLookupIn method on MethodHandles, but since we are shipping and using Java 8
|
||||
// we need to access it via reflection. This is preferred way because it's Java 9+ public api and is
|
||||
// likely to not change
|
||||
final Method privateLookupIn = MethodHandles.class.getMethod("privateLookupIn", Class.class, MethodHandles.Lookup.class);
|
||||
return (MethodHandles.Lookup) privateLookupIn.invoke(null, clazz, MethodHandles.lookup());
|
||||
}
|
||||
catch (NoSuchMethodException e)
|
||||
{
|
||||
// In Java 8 we first do standard lookupIn class
|
||||
final MethodHandles.Lookup lookupIn = MethodHandles.lookup().in(clazz);
|
||||
|
||||
// and then we mark it as trusted for private lookup via reflection on private field
|
||||
final Field modes = MethodHandles.Lookup.class.getDeclaredField("allowedModes");
|
||||
modes.setAccessible(true);
|
||||
modes.setInt(lookupIn, -1); // -1 == TRUSTED
|
||||
return lookupIn;
|
||||
}
|
||||
getSubject(eventClass).accept(event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package net.runelite.client.eventbus;
|
||||
|
||||
import io.reactivex.annotations.NonNull;
|
||||
import io.reactivex.functions.Consumer;
|
||||
import net.runelite.api.events.Event;
|
||||
|
||||
public interface EventBusInterface
|
||||
{
|
||||
<T> void subscribe(Class<T> eventClass, @NonNull Object lifecycle, @NonNull Consumer<T> action);
|
||||
|
||||
void unregister(@NonNull Object lifecycle);
|
||||
|
||||
<T> void post(Class<T> eventClass, @NonNull Event event);
|
||||
}
|
||||
@@ -25,10 +25,11 @@
|
||||
package net.runelite.client.events;
|
||||
|
||||
import lombok.Value;
|
||||
import net.runelite.api.events.Event;
|
||||
import net.runelite.client.ui.NavigationButton;
|
||||
|
||||
@Value
|
||||
public class NavigationButtonAdded
|
||||
public class NavigationButtonAdded implements Event
|
||||
{
|
||||
private NavigationButton button;
|
||||
}
|
||||
|
||||
@@ -25,10 +25,11 @@
|
||||
package net.runelite.client.events;
|
||||
|
||||
import lombok.Value;
|
||||
import net.runelite.api.events.Event;
|
||||
import net.runelite.client.ui.NavigationButton;
|
||||
|
||||
@Value
|
||||
public class NavigationButtonRemoved
|
||||
public class NavigationButtonRemoved implements Event
|
||||
{
|
||||
private NavigationButton button;
|
||||
}
|
||||
|
||||
@@ -27,10 +27,11 @@ package net.runelite.client.events;
|
||||
import java.util.Collection;
|
||||
import lombok.Value;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.events.Event;
|
||||
import net.runelite.client.game.ItemStack;
|
||||
|
||||
@Value
|
||||
public class NpcLootReceived
|
||||
public class NpcLootReceived implements Event
|
||||
{
|
||||
private final NPC npc;
|
||||
private final Collection<ItemStack> items;
|
||||
|
||||
@@ -26,6 +26,7 @@ package net.runelite.client.events;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import net.runelite.api.events.Event;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayMenuEntry;
|
||||
|
||||
@@ -34,7 +35,7 @@ import net.runelite.client.ui.overlay.OverlayMenuEntry;
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class OverlayMenuClicked
|
||||
public class OverlayMenuClicked implements Event
|
||||
{
|
||||
private OverlayMenuEntry entry;
|
||||
private Overlay overlay;
|
||||
|
||||
@@ -26,9 +26,10 @@ package net.runelite.client.events;
|
||||
|
||||
import java.util.UUID;
|
||||
import lombok.Value;
|
||||
import net.runelite.api.events.Event;
|
||||
|
||||
@Value
|
||||
public class PartyChanged
|
||||
public class PartyChanged implements Event
|
||||
{
|
||||
private final UUID partyId;
|
||||
}
|
||||
|
||||
@@ -27,10 +27,11 @@ package net.runelite.client.events;
|
||||
import java.util.Collection;
|
||||
import lombok.Value;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.events.Event;
|
||||
import net.runelite.client.game.ItemStack;
|
||||
|
||||
@Value
|
||||
public class PlayerLootReceived
|
||||
public class PlayerLootReceived implements Event
|
||||
{
|
||||
private final Player player;
|
||||
private final Collection<ItemStack> items;
|
||||
|
||||
@@ -25,10 +25,11 @@
|
||||
package net.runelite.client.events;
|
||||
|
||||
import lombok.Data;
|
||||
import net.runelite.api.events.Event;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
|
||||
@Data
|
||||
public class PluginChanged
|
||||
public class PluginChanged implements Event
|
||||
{
|
||||
private final Plugin plugin;
|
||||
private final boolean loaded;
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
package net.runelite.client.events;
|
||||
|
||||
import lombok.Data;
|
||||
import net.runelite.api.events.Event;
|
||||
|
||||
/**
|
||||
* An event where a new RuneLite account session has been closed,
|
||||
@@ -34,7 +35,7 @@ import lombok.Data;
|
||||
* it has nothing to do with whether an account is being logged out.
|
||||
*/
|
||||
@Data
|
||||
public class SessionClose
|
||||
public class SessionClose implements Event
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
package net.runelite.client.events;
|
||||
|
||||
import lombok.Data;
|
||||
import net.runelite.api.events.Event;
|
||||
|
||||
/**
|
||||
* An event where a new RuneLite account session has been opened
|
||||
@@ -34,7 +35,7 @@ import lombok.Data;
|
||||
* it has nothing to do with whether an account is being logged in.
|
||||
*/
|
||||
@Data
|
||||
public class SessionOpen
|
||||
public class SessionOpen implements Event
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2019, Zeruth <TheRealNull@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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
Modified java.awt.Robot for use with RuneLitePlus. Hopefully we can make it stand far apart.
|
||||
Uses
|
||||
https://github.com/JoonasVali/NaturalMouseMotion
|
||||
for mouse motion.
|
||||
*/
|
||||
|
||||
package net.runelite.client.flexo;
|
||||
|
||||
import com.github.joonasvali.naturalmouse.api.MouseMotionFactory;
|
||||
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.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
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;
|
||||
|
||||
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 final int fixedWidth = Constants.GAME_FIXED_WIDTH;
|
||||
public static final int fixedHeight = Constants.GAME_FIXED_HEIGHT;
|
||||
public static boolean isStretched;
|
||||
public static int minDelay = 45;
|
||||
public static MouseMotionFactory currentMouseMotionFactory;
|
||||
public boolean pausedIndefinitely = false;
|
||||
private Robot peer;
|
||||
|
||||
public Flexo() throws AWTException
|
||||
{
|
||||
if (GraphicsEnvironment.isHeadless())
|
||||
{
|
||||
throw new AWTException("headless environment");
|
||||
}
|
||||
init(GraphicsEnvironment.getLocalGraphicsEnvironment()
|
||||
.getDefaultScreenDevice());
|
||||
}
|
||||
|
||||
private void init(GraphicsDevice screen) throws AWTException
|
||||
{
|
||||
try
|
||||
{
|
||||
peer = new Robot();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
client.getLogger().error("Flexo not supported on this system configuration.");
|
||||
}
|
||||
}
|
||||
|
||||
private transient Object anchor = new Object();
|
||||
|
||||
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 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 mouseMove(Point p)
|
||||
{
|
||||
mouseMove((int) p.getX(), (int) p.getY());
|
||||
try
|
||||
{
|
||||
Thread.sleep(150);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@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());
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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());
|
||||
}
|
||||
|
||||
@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 holdKeyIndefinitely(int keycode)
|
||||
{
|
||||
Thread 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 Color getPixelColor(int x, int y)
|
||||
{
|
||||
return peer.getPixelColor(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delay(int ms)
|
||||
{
|
||||
pauseMS(ms);
|
||||
}
|
||||
|
||||
public int determineHorizontalOffset()
|
||||
{
|
||||
return clientUI.getCanvasOffset().getX();
|
||||
}
|
||||
|
||||
public int determineVerticalOffset()
|
||||
{
|
||||
return clientUI.getCanvasOffset().getY();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,225 @@
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2019, Zeruth <TheRealNull@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.flexo;
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
/*
|
||||
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.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())
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
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();
|
||||
|
||||
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(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;
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,18 @@
|
||||
package net.runelite.client.game;
|
||||
|
||||
import lombok.Getter;
|
||||
import static net.runelite.api.NullObjectID.*;
|
||||
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.*;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
|
||||
@@ -74,8 +85,8 @@ public enum AgilityShortcut
|
||||
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),
|
||||
@@ -86,7 +97,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),
|
||||
@@ -143,7 +154,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, TRIPWIRE_3921),
|
||||
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),
|
||||
ELVEN_OVERPASS_CLIFF_SCRAMBLE_PRIFDDINAS(59, "Rocks", new WorldPoint(3369, 6052, 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),
|
||||
@@ -173,16 +184,16 @@ 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),
|
||||
|
||||
@@ -36,6 +36,7 @@ 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);
|
||||
|
||||
@@ -45,7 +45,7 @@ import net.runelite.api.IndexedSprite;
|
||||
import net.runelite.api.SpriteID;
|
||||
import net.runelite.api.events.ClanChanged;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.util.ImageUtil;
|
||||
import net.runelite.client.util.Text;
|
||||
|
||||
@@ -98,10 +98,17 @@ public class ClanManager
|
||||
private int offset;
|
||||
|
||||
@Inject
|
||||
private ClanManager(Client client, SpriteManager spriteManager)
|
||||
private ClanManager(
|
||||
final Client client,
|
||||
final SpriteManager spriteManager,
|
||||
final EventBus eventbus
|
||||
)
|
||||
{
|
||||
this.client = client;
|
||||
this.spriteManager = spriteManager;
|
||||
|
||||
eventbus.subscribe(GameStateChanged.class, this, this::onGameStateChanged);
|
||||
eventbus.subscribe(ClanChanged.class, this, this::onClanChanged);
|
||||
}
|
||||
|
||||
public ClanMemberRank getRank(String playerName)
|
||||
@@ -125,8 +132,7 @@ public class ClanManager
|
||||
return offset + clanMemberRank.ordinal() - 1;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameStateChanged(GameStateChanged gameStateChanged)
|
||||
private void onGameStateChanged(GameStateChanged gameStateChanged)
|
||||
{
|
||||
if (gameStateChanged.getGameState() == GameState.LOGIN_SCREEN && offset == 0)
|
||||
{
|
||||
@@ -134,8 +140,7 @@ public class ClanManager
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onClanChanged(ClanChanged clanChanged)
|
||||
private void onClanChanged(ClanChanged clanChanged)
|
||||
{
|
||||
clanRanksCache.invalidateAll();
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import static net.runelite.client.game.HiscoreManager.NONE;
|
||||
import net.runelite.http.api.hiscore.HiscoreClient;
|
||||
import net.runelite.http.api.hiscore.HiscoreEndpoint;
|
||||
import net.runelite.http.api.hiscore.HiscoreResult;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@Slf4j
|
||||
class HiscoreLoader extends CacheLoader<HiscoreManager.HiscoreKey, HiscoreResult>
|
||||
@@ -50,7 +51,7 @@ class HiscoreLoader extends CacheLoader<HiscoreManager.HiscoreKey, HiscoreResult
|
||||
}
|
||||
|
||||
@Override
|
||||
public HiscoreResult load(HiscoreManager.HiscoreKey hiscoreKey) throws Exception
|
||||
public HiscoreResult load(@NotNull HiscoreManager.HiscoreKey hiscoreKey) throws Exception
|
||||
{
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
@@ -28,9 +28,14 @@ import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import java.awt.Color;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -47,50 +52,25 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Constants;
|
||||
import static net.runelite.api.Constants.CLIENT_DEFAULT_ZOOM;
|
||||
import static net.runelite.api.Constants.HIGH_ALCHEMY_MULTIPLIER;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.ItemComposition;
|
||||
import net.runelite.api.ItemDefinition;
|
||||
import net.runelite.api.ItemID;
|
||||
import static net.runelite.api.ItemID.*;
|
||||
import net.runelite.api.SpritePixels;
|
||||
import net.runelite.api.Sprite;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.PostItemComposition;
|
||||
import net.runelite.api.events.PostItemDefinition;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.http.api.item.ItemClient;
|
||||
import net.runelite.http.api.item.ItemPrice;
|
||||
import net.runelite.http.api.item.ItemStats;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@Singleton
|
||||
@Slf4j
|
||||
public class ItemManager
|
||||
{
|
||||
@Value
|
||||
private static class ImageKey
|
||||
{
|
||||
private final int itemId;
|
||||
private final int itemQuantity;
|
||||
private final boolean stackable;
|
||||
}
|
||||
|
||||
@Value
|
||||
private static class OutlineKey
|
||||
{
|
||||
private final int itemId;
|
||||
private final int itemQuantity;
|
||||
private final Color outlineColor;
|
||||
}
|
||||
|
||||
private final Client client;
|
||||
private final ScheduledExecutorService scheduledExecutorService;
|
||||
private final ClientThread clientThread;
|
||||
|
||||
private final ItemClient itemClient = new ItemClient();
|
||||
private Map<Integer, ItemPrice> itemPrices = Collections.emptyMap();
|
||||
private Map<Integer, ItemStats> itemStats = Collections.emptyMap();
|
||||
private final LoadingCache<ImageKey, AsyncBufferedImage> itemImages;
|
||||
private final LoadingCache<Integer, ItemComposition> itemCompositions;
|
||||
private final LoadingCache<OutlineKey, BufferedImage> itemOutlines;
|
||||
|
||||
// Worn items with weight reducing property have a different worn and inventory ItemID
|
||||
private static final ImmutableMap<Integer, Integer> WORN_ITEMS = ImmutableMap.<Integer, Integer>builder().
|
||||
put(BOOTS_OF_LIGHTNESS_89, BOOTS_OF_LIGHTNESS).
|
||||
@@ -153,9 +133,24 @@ public class ItemManager
|
||||
put(AGILITY_CAPET_13341, AGILITY_CAPET).
|
||||
put(AGILITY_CAPE_13340, AGILITY_CAPE).
|
||||
build();
|
||||
private final Client client;
|
||||
private final ScheduledExecutorService scheduledExecutorService;
|
||||
private final ClientThread clientThread;
|
||||
private final ItemClient itemClient = new ItemClient();
|
||||
private final ImmutableMap<Integer, ItemStats> itemStatMap;
|
||||
private final LoadingCache<ImageKey, AsyncBufferedImage> itemImages;
|
||||
private final LoadingCache<Integer, ItemDefinition> itemDefinitions;
|
||||
private final LoadingCache<OutlineKey, BufferedImage> itemOutlines;
|
||||
private Map<Integer, ItemPrice> itemPrices = Collections.emptyMap();
|
||||
private Map<Integer, ItemStats> itemStats = Collections.emptyMap();
|
||||
|
||||
@Inject
|
||||
public ItemManager(Client client, ScheduledExecutorService executor, ClientThread clientThread)
|
||||
public ItemManager(
|
||||
Client client,
|
||||
ScheduledExecutorService executor,
|
||||
ClientThread clientThread,
|
||||
EventBus eventbus
|
||||
)
|
||||
{
|
||||
this.client = client;
|
||||
this.scheduledExecutorService = executor;
|
||||
@@ -170,19 +165,19 @@ public class ItemManager
|
||||
.build(new CacheLoader<ImageKey, AsyncBufferedImage>()
|
||||
{
|
||||
@Override
|
||||
public AsyncBufferedImage load(ImageKey key) throws Exception
|
||||
public AsyncBufferedImage load(@NotNull ImageKey key) throws Exception
|
||||
{
|
||||
return loadImage(key.itemId, key.itemQuantity, key.stackable);
|
||||
}
|
||||
});
|
||||
|
||||
itemCompositions = CacheBuilder.newBuilder()
|
||||
itemDefinitions = CacheBuilder.newBuilder()
|
||||
.maximumSize(1024L)
|
||||
.expireAfterAccess(1, TimeUnit.HOURS)
|
||||
.build(new CacheLoader<Integer, ItemComposition>()
|
||||
.build(new CacheLoader<Integer, ItemDefinition>()
|
||||
{
|
||||
@Override
|
||||
public ItemComposition load(Integer key) throws Exception
|
||||
public ItemDefinition load(@NotNull Integer key) throws Exception
|
||||
{
|
||||
return client.getItemDefinition(key);
|
||||
}
|
||||
@@ -194,77 +189,88 @@ public class ItemManager
|
||||
.build(new CacheLoader<OutlineKey, BufferedImage>()
|
||||
{
|
||||
@Override
|
||||
public BufferedImage load(OutlineKey key) throws Exception
|
||||
public BufferedImage load(@NotNull OutlineKey key) throws Exception
|
||||
{
|
||||
return loadItemOutline(key.itemId, key.itemQuantity, key.outlineColor);
|
||||
}
|
||||
});
|
||||
|
||||
final Gson gson = new Gson();
|
||||
|
||||
final Type typeToken = new TypeToken<Map<Integer, ItemStats>>()
|
||||
{
|
||||
}.getType();
|
||||
|
||||
final InputStream statsFile = getClass().getResourceAsStream("/item_stats.json");
|
||||
final Map<Integer, ItemStats> stats = gson.fromJson(new InputStreamReader(statsFile), typeToken);
|
||||
itemStatMap = ImmutableMap.copyOf(stats);
|
||||
|
||||
eventbus.subscribe(GameStateChanged.class, this, this::onGameStateChanged);
|
||||
eventbus.subscribe(PostItemDefinition.class, this, this::onPostItemDefinition);
|
||||
}
|
||||
|
||||
private void loadPrices()
|
||||
{
|
||||
try
|
||||
{
|
||||
ItemPrice[] prices = itemClient.getPrices();
|
||||
if (prices != null)
|
||||
{
|
||||
ImmutableMap.Builder<Integer, ItemPrice> map = ImmutableMap.builderWithExpectedSize(prices.length);
|
||||
for (ItemPrice price : prices)
|
||||
itemClient.getPrices()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(
|
||||
(prices) ->
|
||||
{
|
||||
map.put(price.getId(), price);
|
||||
}
|
||||
itemPrices = map.build();
|
||||
}
|
||||
if (prices != null)
|
||||
{
|
||||
ImmutableMap.Builder<Integer, ItemPrice> map = ImmutableMap.builderWithExpectedSize(prices.length);
|
||||
for (ItemPrice price : prices)
|
||||
{
|
||||
map.put(price.getId(), price);
|
||||
}
|
||||
itemPrices = map.build();
|
||||
}
|
||||
|
||||
log.debug("Loaded {} prices", itemPrices.size());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
log.warn("error loading prices!", e);
|
||||
}
|
||||
log.debug("Loaded {} prices", itemPrices.size());
|
||||
},
|
||||
(e) -> log.warn("error loading prices!", e)
|
||||
);
|
||||
}
|
||||
|
||||
private void loadStats()
|
||||
{
|
||||
try
|
||||
{
|
||||
final Map<Integer, ItemStats> stats = itemClient.getStats();
|
||||
if (stats != null)
|
||||
{
|
||||
itemStats = ImmutableMap.copyOf(stats);
|
||||
}
|
||||
itemClient.getStats()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(
|
||||
(stats) ->
|
||||
{
|
||||
if (stats != null)
|
||||
{
|
||||
itemStats = ImmutableMap.copyOf(stats);
|
||||
}
|
||||
|
||||
log.debug("Loaded {} stats", itemStats.size());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
log.warn("error loading stats!", e);
|
||||
}
|
||||
log.debug("Loaded {} stats", itemStats.size());
|
||||
},
|
||||
(e) -> log.warn("error loading stats!", e)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Subscribe
|
||||
public void onGameStateChanged(final GameStateChanged event)
|
||||
private void onGameStateChanged(final GameStateChanged event)
|
||||
{
|
||||
if (event.getGameState() == GameState.HOPPING || event.getGameState() == GameState.LOGIN_SCREEN)
|
||||
{
|
||||
itemCompositions.invalidateAll();
|
||||
itemDefinitions.invalidateAll();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onPostItemComposition(PostItemComposition event)
|
||||
private void onPostItemDefinition(PostItemDefinition event)
|
||||
{
|
||||
itemCompositions.put(event.getItemComposition().getId(), event.getItemComposition());
|
||||
itemDefinitions.put(event.getItemDefinition().getId(), event.getItemDefinition());
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates internal item manager item composition cache (but not client item composition cache)
|
||||
* @see Client#getItemCompositionCache()
|
||||
*
|
||||
* @see Client#getItemDefinitionCache()
|
||||
*/
|
||||
public void invalidateItemCompositionCache()
|
||||
public void invalidateItemDefinitionCache()
|
||||
{
|
||||
itemCompositions.invalidateAll();
|
||||
itemDefinitions.invalidateAll();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -281,7 +287,7 @@ public class ItemManager
|
||||
/**
|
||||
* Look up an item's price
|
||||
*
|
||||
* @param itemID item id
|
||||
* @param itemID item id
|
||||
* @param ignoreUntradeableMap should the price returned ignore the {@link UntradeableItemMapping}
|
||||
* @return item price
|
||||
*/
|
||||
@@ -318,22 +324,63 @@ public class ItemManager
|
||||
return price;
|
||||
}
|
||||
|
||||
public int getAlchValue(ItemDefinition composition)
|
||||
{
|
||||
if (composition.getId() == ItemID.COINS_995)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (composition.getId() == ItemID.PLATINUM_TOKEN)
|
||||
{
|
||||
return 1000;
|
||||
}
|
||||
|
||||
return (int) Math.max(1, composition.getPrice() * HIGH_ALCHEMY_MULTIPLIER);
|
||||
}
|
||||
|
||||
public int getAlchValue(int itemID)
|
||||
{
|
||||
if (itemID == ItemID.COINS_995)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (itemID == ItemID.PLATINUM_TOKEN)
|
||||
{
|
||||
return 1000;
|
||||
}
|
||||
|
||||
return (int) Math.max(1, getItemDefinition(itemID).getPrice() * HIGH_ALCHEMY_MULTIPLIER);
|
||||
}
|
||||
|
||||
public int getBrokenValue(int itemId)
|
||||
{
|
||||
PvPValueBrokenItem b = PvPValueBrokenItem.of(itemId);
|
||||
|
||||
if (b != null)
|
||||
{
|
||||
return (int) (b.getValue() * (75.0f / 100.0f));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up an item's stats
|
||||
*
|
||||
* @param itemId item id
|
||||
* @return item stats
|
||||
*/
|
||||
@Nullable
|
||||
public ItemStats getItemStats(int itemId, boolean allowNote)
|
||||
{
|
||||
ItemComposition itemComposition = getItemComposition(itemId);
|
||||
ItemDefinition itemDefinition = getItemDefinition(itemId);
|
||||
|
||||
if (itemComposition == null || itemComposition.getName() == null || (!allowNote && itemComposition.getNote() != -1))
|
||||
if (itemDefinition.getName() == null || !allowNote && itemDefinition.getNote() != -1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return itemStats.get(canonicalize(itemId));
|
||||
return itemStatMap.get(canonicalize(itemId));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -365,10 +412,10 @@ public class ItemManager
|
||||
* @return item composition
|
||||
*/
|
||||
@Nonnull
|
||||
public ItemComposition getItemComposition(int itemId)
|
||||
public ItemDefinition getItemDefinition(int itemId)
|
||||
{
|
||||
assert client.isClientThread() : "getItemComposition must be called on client thread";
|
||||
return itemCompositions.getUnchecked(itemId);
|
||||
assert client.isClientThread() : "getItemDefinition must be called on client thread";
|
||||
return itemDefinitions.getUnchecked(itemId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -376,16 +423,16 @@ public class ItemManager
|
||||
*/
|
||||
public int canonicalize(int itemID)
|
||||
{
|
||||
ItemComposition itemComposition = getItemComposition(itemID);
|
||||
ItemDefinition itemDefinition = getItemDefinition(itemID);
|
||||
|
||||
if (itemComposition.getNote() != -1)
|
||||
if (itemDefinition.getNote() != -1)
|
||||
{
|
||||
return itemComposition.getLinkedNoteId();
|
||||
return itemDefinition.getLinkedNoteId();
|
||||
}
|
||||
|
||||
if (itemComposition.getPlaceholderTemplateId() != -1)
|
||||
if (itemDefinition.getPlaceholderTemplateId() != -1)
|
||||
{
|
||||
return itemComposition.getPlaceholderId();
|
||||
return itemDefinition.getPlaceholderId();
|
||||
}
|
||||
|
||||
return WORN_ITEMS.getOrDefault(itemID, itemID);
|
||||
@@ -406,7 +453,7 @@ public class ItemManager
|
||||
{
|
||||
return false;
|
||||
}
|
||||
SpritePixels sprite = client.createItemSprite(itemId, quantity, 1, SpritePixels.DEFAULT_SHADOW_COLOR,
|
||||
Sprite sprite = client.createItemSprite(itemId, quantity, 1, Sprite.DEFAULT_SHADOW_COLOR,
|
||||
stackable ? 1 : 0, false, CLIENT_DEFAULT_ZOOM);
|
||||
if (sprite == null)
|
||||
{
|
||||
@@ -460,21 +507,21 @@ public class ItemManager
|
||||
/**
|
||||
* Create item sprite and applies an outline.
|
||||
*
|
||||
* @param itemId item id
|
||||
* @param itemId item id
|
||||
* @param itemQuantity item quantity
|
||||
* @param outlineColor outline color
|
||||
* @return image
|
||||
*/
|
||||
private BufferedImage loadItemOutline(final int itemId, final int itemQuantity, final Color outlineColor)
|
||||
{
|
||||
final SpritePixels itemSprite = client.createItemSprite(itemId, itemQuantity, 1, 0, 0, true, 710);
|
||||
final Sprite itemSprite = client.createItemSprite(itemId, itemQuantity, 1, 0, 0, true, 710);
|
||||
return itemSprite.toBufferedOutline(outlineColor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get item outline with a specific color.
|
||||
*
|
||||
* @param itemId item id
|
||||
* @param itemId item id
|
||||
* @param itemQuantity item quantity
|
||||
* @param outlineColor outline color
|
||||
* @return image
|
||||
@@ -490,4 +537,20 @@ public class ItemManager
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Value
|
||||
private static class ImageKey
|
||||
{
|
||||
private final int itemId;
|
||||
private final int itemQuantity;
|
||||
private final boolean stackable;
|
||||
}
|
||||
|
||||
@Value
|
||||
private static class OutlineKey
|
||||
{
|
||||
private final int itemId;
|
||||
private final int itemQuantity;
|
||||
private final Color outlineColor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,4 +286,9 @@ public enum ItemMapping
|
||||
|
||||
return mapping.iterator().next();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isMapped(int itemId)
|
||||
{
|
||||
return MAPPINGS.containsValue(itemId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package net.runelite.client.game;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
@Value
|
||||
public class ItemStat
|
||||
{
|
||||
private int slot;
|
||||
|
||||
private int astab;
|
||||
private int aslash;
|
||||
private int acrush;
|
||||
private int amagic;
|
||||
private int arange;
|
||||
|
||||
private int dstab;
|
||||
private int dslash;
|
||||
private int dcrush;
|
||||
private int dmagic;
|
||||
private int drange;
|
||||
|
||||
private int str;
|
||||
private int rstr;
|
||||
private int mdmg;
|
||||
private int prayer;
|
||||
private int aspeed;
|
||||
}
|
||||
@@ -54,7 +54,6 @@ import net.runelite.api.events.ItemSpawned;
|
||||
import net.runelite.api.events.NpcDespawned;
|
||||
import net.runelite.api.events.PlayerDespawned;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.events.NpcLootReceived;
|
||||
import net.runelite.client.events.PlayerLootReceived;
|
||||
|
||||
@@ -74,14 +73,24 @@ public class LootManager
|
||||
private WorldPoint krakenPlayerLocation;
|
||||
|
||||
@Inject
|
||||
private LootManager(EventBus eventBus, Client client)
|
||||
private LootManager(
|
||||
final EventBus eventBus,
|
||||
final Client client
|
||||
)
|
||||
{
|
||||
this.eventBus = eventBus;
|
||||
this.client = client;
|
||||
|
||||
eventBus.subscribe(GameTick.class, this, this::onGameTick);
|
||||
eventBus.subscribe(NpcDespawned.class, this, this::onNpcDespawned);
|
||||
eventBus.subscribe(PlayerDespawned.class, this, this::onPlayerDespawned);
|
||||
eventBus.subscribe(ItemSpawned.class, this, this::onItemSpawned);
|
||||
eventBus.subscribe(ItemDespawned.class, this, this::onItemDespawned);
|
||||
eventBus.subscribe(ItemQuantityChanged.class, this, this::onItemQuantityChanged);
|
||||
eventBus.subscribe(AnimationChanged.class, this, this::onAnimationChanged);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onNpcDespawned(NpcDespawned npcDespawned)
|
||||
private void onNpcDespawned(NpcDespawned npcDespawned)
|
||||
{
|
||||
final NPC npc = npcDespawned.getNpc();
|
||||
if (!npc.isDead())
|
||||
@@ -123,8 +132,7 @@ public class LootManager
|
||||
processNpcLoot(npc);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onPlayerDespawned(PlayerDespawned playerDespawned)
|
||||
private void onPlayerDespawned(PlayerDespawned playerDespawned)
|
||||
{
|
||||
final Player player = playerDespawned.getPlayer();
|
||||
// Only care about dead Players
|
||||
@@ -150,11 +158,10 @@ public class LootManager
|
||||
}
|
||||
|
||||
killPoints.add(location);
|
||||
eventBus.post(new PlayerLootReceived(player, items));
|
||||
eventBus.post(PlayerLootReceived.class, new PlayerLootReceived(player, items));
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onItemSpawned(ItemSpawned itemSpawned)
|
||||
private void onItemSpawned(ItemSpawned itemSpawned)
|
||||
{
|
||||
final TileItem item = itemSpawned.getItem();
|
||||
final Tile tile = itemSpawned.getTile();
|
||||
@@ -164,16 +171,14 @@ public class LootManager
|
||||
log.debug("Item spawn {} ({}) location {}", item.getId(), item.getQuantity(), location);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onItemDespawned(ItemDespawned itemDespawned)
|
||||
private void onItemDespawned(ItemDespawned itemDespawned)
|
||||
{
|
||||
final TileItem item = itemDespawned.getItem();
|
||||
final LocalPoint location = itemDespawned.getTile().getLocalLocation();
|
||||
log.debug("Item despawn {} ({}) location {}", item.getId(), item.getQuantity(), location);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onItemQuantityChanged(ItemQuantityChanged itemQuantityChanged)
|
||||
private void onItemQuantityChanged(ItemQuantityChanged itemQuantityChanged)
|
||||
{
|
||||
final TileItem item = itemQuantityChanged.getItem();
|
||||
final Tile tile = itemQuantityChanged.getTile();
|
||||
@@ -189,8 +194,7 @@ public class LootManager
|
||||
itemSpawns.put(packed, new ItemStack(item.getId(), diff, location));
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onAnimationChanged(AnimationChanged e)
|
||||
private void onAnimationChanged(AnimationChanged e)
|
||||
{
|
||||
if (!(e.getActor() instanceof NPC))
|
||||
{
|
||||
@@ -219,8 +223,7 @@ public class LootManager
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameTick(GameTick gameTick)
|
||||
private void onGameTick(GameTick gameTick)
|
||||
{
|
||||
playerLocationLastTick = client.getLocalPlayer().getWorldLocation();
|
||||
itemSpawns.clear();
|
||||
@@ -237,7 +240,7 @@ public class LootManager
|
||||
|
||||
final int x = location.getSceneX();
|
||||
final int y = location.getSceneY();
|
||||
final int size = npc.getComposition().getSize();
|
||||
final int size = npc.getDefinition().getSize();
|
||||
|
||||
// Some NPCs drop items onto multiple tiles
|
||||
final List<ItemStack> allItems = new ArrayList<>();
|
||||
@@ -257,7 +260,7 @@ public class LootManager
|
||||
}
|
||||
|
||||
killPoints.add(location);
|
||||
eventBus.post(new NpcLootReceived(npc, allItems));
|
||||
eventBus.post(NpcLootReceived.class, new NpcLootReceived(npc, allItems));
|
||||
}
|
||||
|
||||
private WorldPoint getDropLocation(NPC npc, WorldPoint worldLocation)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Adam <Adam@sigterm.info>
|
||||
* Copyright (c) 2019, TheStonedTurtle <https://github.com/TheStonedTurtle>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -24,6 +25,7 @@
|
||||
*/
|
||||
package net.runelite.client.game;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import java.io.InputStream;
|
||||
@@ -33,33 +35,88 @@ import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@Singleton
|
||||
public class NPCManager
|
||||
{
|
||||
private final Map<String, Integer> healthMap;
|
||||
private final ImmutableMap<Integer, NPCStats> statsMap;
|
||||
|
||||
@Inject
|
||||
private NPCManager()
|
||||
{
|
||||
final Gson gson = new Gson();
|
||||
final Type typeToken = new TypeToken<Map<String, Integer>>()
|
||||
|
||||
final Type typeToken = new TypeToken<Map<Integer, NPCStats>>()
|
||||
{
|
||||
}.getType();
|
||||
|
||||
final InputStream healthFile = getClass().getResourceAsStream("/npc_health.json");
|
||||
healthMap = gson.fromJson(new InputStreamReader(healthFile), typeToken);
|
||||
final InputStream statsFile = getClass().getResourceAsStream("/npc_stats.json");
|
||||
final Map<Integer, NPCStats> stats = gson.fromJson(new InputStreamReader(statsFile), typeToken);
|
||||
statsMap = ImmutableMap.copyOf(stats);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* Returns the {@link NPCStats} for target NPC id
|
||||
*
|
||||
* @param npcId NPC id
|
||||
* @return the {@link NPCStats} or null if unknown
|
||||
*/
|
||||
@Nullable
|
||||
public Integer getHealth(final String name, final int combatLevel)
|
||||
public NPCStats getStats(final int npcId)
|
||||
{
|
||||
return healthMap.get(name + "_" + combatLevel);
|
||||
return statsMap.get(npcId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns health for target NPC ID
|
||||
*
|
||||
* @param npcId NPC id
|
||||
* @return health or null if unknown
|
||||
*/
|
||||
public int getHealth(final int npcId)
|
||||
{
|
||||
final NPCStats s = statsMap.get(npcId);
|
||||
if (s == null || s.getHitpoints() == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return s.getHitpoints();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the attack speed for target NPC ID.
|
||||
*
|
||||
* @param npcId NPC id
|
||||
* @return attack speed in game ticks for NPC ID.
|
||||
*/
|
||||
public int getAttackSpeed(final int npcId)
|
||||
{
|
||||
final NPCStats s = statsMap.get(npcId);
|
||||
if (s == null || s.getAttackSpeed() == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return s.getAttackSpeed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the exp modifier for target NPC ID based on its stats.
|
||||
*
|
||||
* @param npcId NPC id
|
||||
* @return npcs exp modifier. Assumes default xp rate if npc stats are unknown (returns 1)
|
||||
*/
|
||||
public double getXpModifier(final int npcId)
|
||||
{
|
||||
final NPCStats s = statsMap.get(npcId);
|
||||
if (s == null)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return s.calculateXpModifier();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 2019, TheStonedTurtle <https://github.com/TheStonedTurtle>
|
||||
* 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 lombok.Value;
|
||||
|
||||
@Value
|
||||
public class NPCStats
|
||||
{
|
||||
private final String name;
|
||||
|
||||
private final int hitpoints;
|
||||
private final int combatLevel;
|
||||
private final int slayerLevel;
|
||||
private final int attackSpeed;
|
||||
|
||||
private final int attackLevel;
|
||||
private final int strengthLevel;
|
||||
private final int defenceLevel;
|
||||
private final int rangeLevel;
|
||||
private final int magicLevel;
|
||||
|
||||
private final int stab;
|
||||
private final int slash;
|
||||
private final int crush;
|
||||
private final int range;
|
||||
private final int magic;
|
||||
|
||||
private final int stabDef;
|
||||
private final int slashDef;
|
||||
private final int crushDef;
|
||||
private final int rangeDef;
|
||||
private final int magicDef;
|
||||
|
||||
private final int bonusAttack;
|
||||
private final int bonusStrength;
|
||||
private final int bonusRangeStrength;
|
||||
private final int bonusMagicDamage;
|
||||
|
||||
private final boolean poisonImmune;
|
||||
private final boolean venomImmune;
|
||||
|
||||
private final boolean dragon;
|
||||
private final boolean demon;
|
||||
private final boolean undead;
|
||||
|
||||
/**
|
||||
* Based off the formula found here: http://services.runescape.com/m=forum/c=PLuJ4cy6gtA/forums.ws?317,318,712,65587452,209,337584542#209
|
||||
* @return bonus XP modifier
|
||||
*/
|
||||
public double calculateXpModifier()
|
||||
{
|
||||
final double averageLevel = Math.floor((attackLevel + strengthLevel + defenceLevel + hitpoints) / 4);
|
||||
final double averageDefBonus = Math.floor((stabDef + slashDef + crushDef) / 3);
|
||||
|
||||
return (1 + Math.floor(averageLevel * (averageDefBonus + bonusStrength + bonusAttack) / 5120) / 40);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (c) 2018, TheStonedTurtle <https://github.com/TheStonedTurtle>
|
||||
* 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.ImmutableMap;
|
||||
import javax.annotation.Nullable;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.ItemID;
|
||||
|
||||
/**
|
||||
* Some non tradeable items are kept on death inside low level wilderness (1-20) but are turned into a broken variant.
|
||||
* <p>
|
||||
* The non-broken variant will be shown inside the interface.
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum PvPValueBrokenItem
|
||||
{
|
||||
// Capes
|
||||
FIRE_CAPE(ItemID.FIRE_CAPE, 50000),
|
||||
FIRE_MAX_CAPE(ItemID.FIRE_MAX_CAPE, 50000),
|
||||
INFERNAL_CAPE(ItemID.INFERNAL_CAPE, 50000),
|
||||
INFERNAL_MAX_CAPE(ItemID.INFERNAL_MAX_CAPE, 50000),
|
||||
AVAS_ASSEMBLER(ItemID.AVAS_ASSEMBLER, 75000),
|
||||
ASSEMBLER_MAX_CAPE(ItemID.ASSEMBLER_MAX_CAPE, 75000),
|
||||
|
||||
// Defenders
|
||||
BRONZE_DEFENDER(ItemID.BRONZE_DEFENDER, 1000),
|
||||
IRON_DEFENDER(ItemID.IRON_DEFENDER, 2000),
|
||||
STEEL_DEFENDER(ItemID.STEEL_DEFENDER, 2500),
|
||||
BLACK_DEFENDER(ItemID.BLACK_DEFENDER, 5000),
|
||||
MITHRIL_DEFENDER(ItemID.MITHRIL_DEFENDER, 15000),
|
||||
ADAMANT_DEFENDER(ItemID.ADAMANT_DEFENDER, 25000),
|
||||
RUNE_DEFENDER(ItemID.RUNE_DEFENDER, 35000),
|
||||
DRAGON_DEFENDER(ItemID.DRAGON_DEFENDER, 40000),
|
||||
AVERNIC_DEFENDER(ItemID.AVERNIC_DEFENDER, 1000000),
|
||||
|
||||
// Void
|
||||
VOID_MAGE_HELM(ItemID.VOID_MAGE_HELM, 40000),
|
||||
VOID_RANGER_HELM(ItemID.VOID_RANGER_HELM, 40000),
|
||||
VOID_MELEE_HELM(ItemID.VOID_MELEE_HELM, 40000),
|
||||
VOID_KNIGHT_TOP(ItemID.VOID_KNIGHT_TOP, 45000),
|
||||
VOID_KNIGHT_ROBE(ItemID.VOID_KNIGHT_ROBE, 45000),
|
||||
VOID_KNIGHT_GLOVES(ItemID.VOID_KNIGHT_GLOVES, 30000),
|
||||
ELITE_VOID_TOP(ItemID.ELITE_VOID_TOP, 50000),
|
||||
ELITE_VOID_ROBE(ItemID.ELITE_VOID_ROBE, 50000),
|
||||
|
||||
// Barb Assault
|
||||
FIGHTER_HAT(ItemID.FIGHTER_HAT, 45000),
|
||||
RANGER_HAT(ItemID.RANGER_HAT, 45000),
|
||||
HEALER_HAT(ItemID.HEALER_HAT, 45000),
|
||||
FIGHTER_TORSO(ItemID.FIGHTER_TORSO, 50000),
|
||||
PENANCE_SKIRT(ItemID.PENANCE_SKIRT, 20000),
|
||||
|
||||
// Castle Wars
|
||||
SARADOMIN_HALO(ItemID.SARADOMIN_HALO, 25000),
|
||||
ZAMORAK_HALO(ItemID.ZAMORAK_HALO, 25000),
|
||||
GUTHIX_HALO(ItemID.GUTHIX_HALO, 25000),
|
||||
DECORATIVE_MAGIC_HAT(ItemID.DECORATIVE_ARMOUR_11898, 5000),
|
||||
DECORATIVE_MAGIC_ROBE_TOP(ItemID.DECORATIVE_ARMOUR_11896, 5000),
|
||||
DECORATIVE_MAGIC_ROBE_LEGS(ItemID.DECORATIVE_ARMOUR_11897, 5000),
|
||||
DECORATIVE_RANGE_TOP(ItemID.DECORATIVE_ARMOUR_11899, 5000),
|
||||
DECORATIVE_RANGE_BOTTOM(ItemID.DECORATIVE_ARMOUR_11900, 5000),
|
||||
DECORATIVE_RANGE_QUIVER(ItemID.DECORATIVE_ARMOUR_11901, 5000),
|
||||
GOLD_DECORATIVE_HELM(ItemID.DECORATIVE_HELM_4511, 5000),
|
||||
GOLD_DECORATIVE_BODY(ItemID.DECORATIVE_ARMOUR_4509, 5000),
|
||||
GOLD_DECORATIVE_LEGS(ItemID.DECORATIVE_ARMOUR_4510, 5000),
|
||||
GOLD_DECORATIVE_SKIRT(ItemID.DECORATIVE_ARMOUR_11895, 5000),
|
||||
GOLD_DECORATIVE_SHIELD(ItemID.DECORATIVE_SHIELD_4512, 5000),
|
||||
GOLD_DECORATIVE_SWORD(ItemID.DECORATIVE_SWORD_4508, 5000);
|
||||
|
||||
private static final ImmutableMap<Integer, PvPValueBrokenItem> idMap;
|
||||
|
||||
static
|
||||
{
|
||||
ImmutableMap.Builder<Integer, PvPValueBrokenItem> builder = ImmutableMap.builder();
|
||||
|
||||
for (PvPValueBrokenItem items : values())
|
||||
{
|
||||
builder.put(items.itemID, items);
|
||||
}
|
||||
|
||||
idMap = builder.build();
|
||||
}
|
||||
|
||||
private final int itemID;
|
||||
private final int value;
|
||||
|
||||
@Nullable
|
||||
public static PvPValueBrokenItem of(int itemId)
|
||||
{
|
||||
return idMap.get(itemId);
|
||||
}
|
||||
|
||||
public static boolean breaksOnDeath(int itemId)
|
||||
{
|
||||
return idMap.containsKey(itemId);
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,7 @@ public class SkillIconManager
|
||||
public BufferedImage getSkillImage(Skill skill, boolean small)
|
||||
{
|
||||
int skillIdx = skill.ordinal() + (small ? Skill.values().length : 0);
|
||||
BufferedImage skillImage = null;
|
||||
BufferedImage skillImage;
|
||||
|
||||
if (imgCache[skillIdx] != null)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package net.runelite.client.game;
|
||||
|
||||
public enum Sound
|
||||
{
|
||||
FIFTEEN_SECONDS(1, "net/runelite/client/game/sounds/15seconds.wav"),
|
||||
FIVE_SECONDS(2, "net/runelite/client/game/sounds/5seconds.wav"),
|
||||
ATTACK_WITH_MAGIC(3, "net/runelite/client/game/sounds/attackmagic.wav"),
|
||||
ATTACK_WITH_MELEE(4, "net/runelite/client/game/sounds/attackmelee.wav"),
|
||||
ATTACK_WITH_RANGED(5, "net/runelite/client/game/sounds/attackranged.wav"),
|
||||
INCOMING(6, "net/runelite/client/game/sounds/incoming.wav"),
|
||||
MOVE(7, "net/runelite/client/game/sounds/move.wav"),
|
||||
PRAY_MAGIC(8, "net/runelite/client/game/sounds/praymagic.wav"),
|
||||
PRAY_MELEE(9, "net/runelite/client/game/sounds/praymelee.wav"),
|
||||
PRAY_RANGED(10, "net/runelite/client/game/sounds/prayranged.wav"),
|
||||
REENABLE_PRAYER(11, "net/runelite/client/game/sounds/reenableprayer.wav"),
|
||||
RUNAWAY(12, "net/runelite/client/game/sounds/runaway.wav"),
|
||||
LOW_HEATLH(13, "net/runelite/client/game/sounds/lowhealth.wav"),
|
||||
LOW_PRAYER(14, "net/runelite/client/game/sounds/lowprayer.wav"),
|
||||
OUT_OF_COMBAT(15, "net/runelite/client/game/sounds/outofcombat.wav"),
|
||||
RESTORED_SPECIAL_ATTACK(16, "net/runelite/client/game/sounds/restorespec.wav"),
|
||||
IDLE(17, "net/runelite/client/game/sounds/idle.wav"),
|
||||
BREAK(18, "net/runelite/client/game/sounds/break.wav");
|
||||
|
||||
private final String filePath;
|
||||
private final int id;
|
||||
|
||||
Sound(int id, String filePath)
|
||||
{
|
||||
this.id = id;
|
||||
this.filePath = filePath;
|
||||
}
|
||||
|
||||
public String getFilePath()
|
||||
{
|
||||
return this.filePath;
|
||||
}
|
||||
|
||||
public int getId()
|
||||
{
|
||||
return this.id;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package net.runelite.client.game;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.io.IOException;
|
||||
import javax.inject.Singleton;
|
||||
import javax.sound.sampled.AudioFormat;
|
||||
import javax.sound.sampled.AudioInputStream;
|
||||
import javax.sound.sampled.AudioSystem;
|
||||
import javax.sound.sampled.BooleanControl;
|
||||
import javax.sound.sampled.DataLine;
|
||||
import javax.sound.sampled.FloatControl;
|
||||
import javax.sound.sampled.LineUnavailableException;
|
||||
import javax.sound.sampled.SourceDataLine;
|
||||
import javax.sound.sampled.UnsupportedAudioFileException;
|
||||
import net.runelite.client.config.RuneLiteConfig;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@Singleton
|
||||
public class SoundManager
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(SoundManager.class);
|
||||
private final RuneLiteConfig runeliteConfig;
|
||||
|
||||
@Inject
|
||||
private SoundManager(RuneLiteConfig runeLiteConfig)
|
||||
{
|
||||
this.runeliteConfig = runeLiteConfig;
|
||||
}
|
||||
|
||||
public void playSound(final Sound sound)
|
||||
{
|
||||
new Thread(new Runnable()
|
||||
{
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
AudioInputStream in = AudioSystem.getAudioInputStream(this.getClass().getClassLoader().getResource(sound.getFilePath()));
|
||||
AudioFormat outFormat = SoundManager.this.getOutFormat(in.getFormat());
|
||||
DataLine.Info info = new DataLine.Info(SourceDataLine.class, outFormat);
|
||||
SourceDataLine line = (SourceDataLine)AudioSystem.getLine(info);
|
||||
if (line != null)
|
||||
{
|
||||
line.open(outFormat, 2200);
|
||||
if (line.isControlSupported(FloatControl.Type.MASTER_GAIN))
|
||||
{
|
||||
int volume = SoundManager.this.runeliteConfig.volume();
|
||||
FloatControl gainControl = (FloatControl)line.getControl(FloatControl.Type.MASTER_GAIN);
|
||||
BooleanControl muteControl = (BooleanControl)line.getControl(BooleanControl.Type.MUTE);
|
||||
if (volume == 0)
|
||||
{
|
||||
muteControl.setValue(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
muteControl.setValue(false);
|
||||
gainControl.setValue((float)(Math.log((double)volume / 100.0) / Math.log(10.0) * 20.0));
|
||||
}
|
||||
}
|
||||
line.start();
|
||||
SoundManager.this.stream(AudioSystem.getAudioInputStream(outFormat, in), line);
|
||||
line.drain();
|
||||
line.stop();
|
||||
}
|
||||
}
|
||||
catch (IOException | LineUnavailableException | UnsupportedAudioFileException e)
|
||||
{
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
private AudioFormat getOutFormat(AudioFormat inFormat)
|
||||
{
|
||||
int ch = inFormat.getChannels();
|
||||
float rate = inFormat.getSampleRate();
|
||||
return new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, rate, 16, ch, ch * 2, rate, false);
|
||||
}
|
||||
|
||||
private void stream(AudioInputStream in, SourceDataLine line) throws IOException
|
||||
{
|
||||
byte[] buffer = new byte[2200];
|
||||
int n = 0;
|
||||
while (n != -1)
|
||||
{
|
||||
line.write(buffer, 0, n);
|
||||
n = in.read(buffer, 0, buffer.length);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -39,7 +39,7 @@ import javax.swing.JLabel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.SpritePixels;
|
||||
import net.runelite.api.Sprite;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.ui.overlay.infobox.InfoBox;
|
||||
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
|
||||
@@ -78,7 +78,7 @@ public class SpriteManager
|
||||
return cached;
|
||||
}
|
||||
|
||||
SpritePixels[] sp = client.getSprites(client.getIndexSprites(), archive, 0);
|
||||
Sprite[] sp = client.getSprites(client.getIndexSprites(), archive, 0);
|
||||
if (sp == null)
|
||||
{
|
||||
return null;
|
||||
@@ -127,12 +127,8 @@ public class SpriteManager
|
||||
public void addSpriteTo(JButton c, int archive, int file)
|
||||
{
|
||||
getSpriteAsync(archive, file, img ->
|
||||
{
|
||||
SwingUtilities.invokeLater(() ->
|
||||
{
|
||||
c.setIcon(new ImageIcon(img));
|
||||
});
|
||||
});
|
||||
c.setIcon(new ImageIcon(img))));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -141,12 +137,8 @@ public class SpriteManager
|
||||
public void addSpriteTo(JLabel c, int archive, int file)
|
||||
{
|
||||
getSpriteAsync(archive, file, img ->
|
||||
{
|
||||
SwingUtilities.invokeLater(() ->
|
||||
{
|
||||
c.setIcon(new ImageIcon(img));
|
||||
});
|
||||
});
|
||||
c.setIcon(new ImageIcon(img))));
|
||||
}
|
||||
|
||||
public void addSpriteOverrides(SpriteOverride[] add)
|
||||
@@ -158,12 +150,12 @@ public class SpriteManager
|
||||
|
||||
clientThread.invokeLater(() ->
|
||||
{
|
||||
Map<Integer, SpritePixels> overrides = client.getSpriteOverrides();
|
||||
Map<Integer, Sprite> overrides = client.getSpriteOverrides();
|
||||
Class<?> owner = add[0].getClass();
|
||||
for (SpriteOverride o : add)
|
||||
{
|
||||
BufferedImage image = ImageUtil.getResourceStreamFromClass(owner, o.getFileName());
|
||||
SpritePixels sp = ImageUtil.getImageSpritePixels(image, client);
|
||||
Sprite sp = ImageUtil.getImageSprite(image, client);
|
||||
overrides.put(o.getSpriteId(), sp);
|
||||
}
|
||||
});
|
||||
@@ -173,7 +165,7 @@ public class SpriteManager
|
||||
{
|
||||
clientThread.invokeLater(() ->
|
||||
{
|
||||
Map<Integer, SpritePixels> overrides = client.getSpriteOverrides();
|
||||
Map<Integer, Sprite> overrides = client.getSpriteOverrides();
|
||||
for (SpriteOverride o : remove)
|
||||
{
|
||||
overrides.remove(o.getSpriteId());
|
||||
|
||||
@@ -24,14 +24,10 @@
|
||||
*/
|
||||
package net.runelite.client.game;
|
||||
|
||||
import net.runelite.api.SpriteID;
|
||||
|
||||
public interface SpriteOverride
|
||||
{
|
||||
/**
|
||||
* An ID for a sprite. Negative numbers are used by RuneLite specific sprites
|
||||
*
|
||||
* @see SpriteID
|
||||
*/
|
||||
int getSpriteId();
|
||||
|
||||
|
||||
@@ -0,0 +1,335 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2019 RuneLitePlus
|
||||
* Redistributions and modifications of this software are permitted as long as this notice remains in its original unmodified state at the top of this file.
|
||||
* If there are any questions comments, or feedback about this software, please direct all inquiries directly to the file authors:
|
||||
* ST0NEWALL#9112
|
||||
* RuneLitePlus Discord: https://discord.gg/Q7wFtCe
|
||||
* RuneLitePlus website: https://runelitepl.us
|
||||
******************************************************************************/
|
||||
|
||||
package net.runelite.client.game;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.coords.WorldArea;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.client.util.PvPUtil;
|
||||
|
||||
public enum WorldLocation
|
||||
{
|
||||
// Non-Wilderness Locations
|
||||
AGILITY_PYRAMID("Agility Pyramid", new Location(3334, 2864, 3386, 2819), 0),
|
||||
AL_KHARID_BANK("Al Kharid Bank", new Location(3265, 3173, 3272, 3161), 0),
|
||||
AL_KHARID_GLIDER("Al Kharid_Glider", new Location(3276, 3214, 3283, 3209), 0),
|
||||
AL_KHARID_PALACE("Al Kharid Palace", new Location(3281, 3177, 3304, 3158), 0),
|
||||
ZUL_ANDRA("Zul-Andra", new Location(2182, 3070, 2214, 3042), 0),
|
||||
APE_ATOLL_TEMPLE("Ape Atoll Temple", new Location(2784, 2802, 2810, 2770), 0),
|
||||
ARDY_CASTLE("Ardy Castle", new Location(2567, 3311, 2591, 3283), 0),
|
||||
ARDY_DOCKS("Ardy Docks", new Location(2660, 3284, 2689, 3264), 0),
|
||||
ARDY_NORTH_BANK("Ardy North Bank", new Location(2611, 3336, 2622, 3329), 0),
|
||||
ARDY_SOUTH_BANK("Ardy South Bank", new Location(2645, 3288, 2659, 3279), 0),
|
||||
ARDY_STALLS("Ardy Stalls", new Location(2651, 3318, 2673, 3293), 0),
|
||||
ARDY_ZOO("Ardy Zoo", new Location(2598, 3288, 2640, 3261), 0),
|
||||
BARB_VILLAGE("Barb Village", new Location(3071, 3448, 3092, 3405), 0),
|
||||
BARROWS("Barrows", new Location(3546, 3314, 3583, 3268), 0),
|
||||
BEDABIN_CAMP("Bedabin Camp", new Location(3157, 3052, 3188, 3019), 0),
|
||||
CAMELOT_CASTLE("Camelot Castle", new Location(2743, 3481, 2775, 3468), 0),
|
||||
CASTLE_WARS("Castle Wars", new Location(2435, 3127, 2474, 3074), 0),
|
||||
CATHERBY("Catherby", new Location(2791, 3457, 2833, 3436), 0),
|
||||
CATHERBY_DOCKS("Catherby Docks", new Location(2790, 3432, 2808, 3409), 0),
|
||||
CATHERBY_EAST("Catherby East", new Location(2834, 3441, 2862, 3425), 0),
|
||||
CATHERBY_NORTH("Catherby North", new Location(2791, 3472, 2833, 3458), 0),
|
||||
CLAN_WARS("Clan Wars", new Location(3344, 3176, 3391, 3142), 0),
|
||||
COOKS_GUILD("Cooks Guild", new Location(3135, 3455, 3155, 3427), 0),
|
||||
COX("CoX", new Location(1226, 3574, 1270, 3559), 0),
|
||||
CRAB_CLAW_ISLE("Crab Claw Isle", new Location(1745, 3449, 1795, 3399), 0),
|
||||
DESERT_BANDIT_CAMP("Desert Bandit Camp", new Location(3154, 2993, 3189, 2963), 0),
|
||||
DIGSITE_NORTHWEST("Digsite NorthWest", new Location(3325, 3445, 3353, 3420), 0),
|
||||
DIGSITE_NORTHEAST("Digsite NorthEast", new Location(3354, 3445, 3382, 3420), 0),
|
||||
DIGSITE_SOUTHEAST("Digsite SouthEast", new Location(3354, 3419, 3382, 3393), 0),
|
||||
DIGSITE_SOUTHWEST("Digsite SouthWest", new Location(3325, 3419, 3353, 3393), 0),
|
||||
DRYANOR_VILLAGE("Dryanor Village", new Location(3074, 3283, 3112, 3241), 0),
|
||||
DUEL_ARENA_ENTRANCE("Duel Arena Entrance", new Location(3311, 3247, 3328, 3223), 0),
|
||||
DUEL_ARENA_NORTH("Duel Arena North", new Location(3329, 3266, 3388, 3264), 0),
|
||||
DUEL_ARENA_NORTH_WEST("Duel Arena North West", new Location(3322, 3266, 3328, 3248), 0),
|
||||
EDGE_BANK("Edge Bank", new Location(3090, 3499, 3099, 3487), 0),
|
||||
FALADOR_PARTYROOM("Falador Partyroom", new Location(3035, 3386, 3056, 3370), 0),
|
||||
FALLY_BANK("Fally Bank", new Location(2943, 3372, 2949, 3358), 0),
|
||||
FALLY_CENTER("Fally Center", new Location(2959, 3385, 2972, 3374), 0),
|
||||
FALLY_EAST_BANK("Fally East Bank", new Location(3008, 3358, 3021, 3353), 0),
|
||||
FALLY_PARK("Fally Park", new Location(2982, 3390, 3025, 3368), 0),
|
||||
FALLY_RESPAWN("Fally Respawn", new Location(2957, 3355, 2998, 3325), 0),
|
||||
GNOME_AGILITY("Gnome Agility", new Location(2469, 3441, 2489, 3412), 0),
|
||||
GNOME_BALL("Gnome Ball", new Location(2384, 3495, 2408, 3479), 0),
|
||||
GRAND_EXCHANGE_NORTHEAST("Grand Exchange NorthEast", new Location(3165, 3516, 3197, 3490), 0),
|
||||
GRAND_EXCHANGE_NORTHWEST("Grand Exchange NorthWest", new Location(3139, 3516, 3164, 3490), 0),
|
||||
GRAND_EXCHANGE_SOUTHEAST("Grand Exchange SouthEast", new Location(3165, 3489, 3189, 3468), 0),
|
||||
GRAND_EXCHANGE_SOUTHWEST("Grand Exchange SouthWest", new Location(3139, 3489, 3164, 3467), 0),
|
||||
GRAND_TREE("Grand Tree", new Location(2442, 3515, 2490, 3478), 0),
|
||||
ICE_MOUNTAIN("Ice Mountain", new Location(3001, 3508, 3024, 3463), 0),
|
||||
TRAINING_GROUND("Training Ground", new Location(2501, 3387, 2534, 3358), 0),
|
||||
LUMBRIDGE_CASTLE("Lumbridge Castle", new Location(3201, 3235, 3225, 3201), 0),
|
||||
LUMBY_SWAMP("Lumby Swamp", new Location(3135, 3203, 3245, 3140), 0),
|
||||
LUNAR_ISLE_CENTRAL("Lunar Isle Central", new Location(2055, 3933, 2112, 3888), 0),
|
||||
LUNAR_ISLE_EAST("Lunar Isle East", new Location(2113, 3921, 2185, 3888), 0),
|
||||
LUNAR_ISLE_NORTH("Lunar Isle North", new Location(2063, 3958, 2112, 3934), 0),
|
||||
LUNAR_ISLE_NORTH_EAST("Lunar Isle North East", new Location(2113, 3958, 2185, 3922), 0),
|
||||
LUNAR_ISLE_SOUTH("Lunar Isle South", new Location(2057, 3887, 2112, 3843), 0),
|
||||
LUNAR_ISLE_SOUTHEAST("Lunar Isle SouthEast", new Location(2113, 3887, 2185, 3843), 0),
|
||||
MONASTERY("Monastery", new Location(3044, 3507, 3060, 3471), 0),
|
||||
NARDAH_NORTH("Nardah North", new Location(3397, 2942, 3453, 2915), 0),
|
||||
NARDAH_SOUTH("Nardah South", new Location(3397, 2914, 3453, 2882), 0),
|
||||
NIEVE("Nieve", new Location(2430, 3425, 2435, 3419), 0),
|
||||
NIGHTMARE_ZONE("Nightmare Zone", new Location(2599, 3119, 2614, 3111), 0),
|
||||
NORTH_MARIM("North Marim", new Location(2731, 2804, 2783, 2786), 0),
|
||||
PEST_CONTROL("Pest Control", new Location(2630, 2679, 2682, 2627), 0),
|
||||
POLLNIVNEACH_NORTH("Pollnivneach North", new Location(3331, 3004, 3379, 2974), 0),
|
||||
POLLNIVNEACH_SOUTH("Pollnivneach South", new Location(3331, 2973, 3379, 2941), 0),
|
||||
PORT_KHAZARD("Port Khazard", new Location(2624, 3182, 2680, 3143), 0),
|
||||
PORT_SARIM("Port Sarim", new Location(3009, 3261, 3060, 3194), 0),
|
||||
RELLEKA_SOUTH_WEST("Relleka South West", new Location(2609, 3678, 2649, 3644), 0),
|
||||
RELLEKKA_NORTH_EAST("Rellekka North East", new Location(2650, 3712, 2690, 3679), 0),
|
||||
RELLEKKA_NORTH_WEST("Rellekka North West", new Location(2609, 3712, 2649, 3679), 0),
|
||||
RELLEKKA_SOUTH_EAST("Rellekka South East", new Location(2650, 3678, 2690, 3644), 0),
|
||||
RIMMINGTON_PORTAL("Rimmington Portal", new Location(2946, 3228, 2960, 3218), 0),
|
||||
ROCK_CRABS_EAST("Rock Crabs East", new Location(2691, 3738, 2730, 3713), 0),
|
||||
ROCK_CRABS_WEST("Rock Crabs West", new Location(2650, 3738, 2690, 3713), 0),
|
||||
SANDCRABS_CENTRAL("SandCrabs Central", new Location(1850, 3529, 1884, 3465), 0),
|
||||
SANDCRABS_NORTH("SandCrabs North", new Location(1848, 3572, 1884, 3532), 0),
|
||||
SANDCRABS_SOUTH("SandCrabs South", new Location(1796, 3468, 1849, 3436), 0),
|
||||
SEERS_VILLAGE("Seers Village", new Location(2688, 3498, 2742, 3468), 0),
|
||||
SHANTAY_PASS("Shantay Pass", new Location(3293, 3137, 3312, 3116), 0),
|
||||
SHILO_VILLAGE_NORTH("Shilo Village North", new Location(2817, 3006, 2878, 2973), 0),
|
||||
SHILO_VILLAGE_SOUTH("Shilo Village South", new Location(2816, 2972, 2879, 2944), 0),
|
||||
SOUTH_MARIM("South Marim", new Location(2731, 2785, 2783, 2762), 0),
|
||||
SOUTH_OF_GRAND_EXCHANGE("South of Grand Exchange", new Location(3156, 3466, 3190, 3448), 0),
|
||||
TREEGOME_VILLAGE("TreeGome Village", new Location(2514, 3175, 2547, 3158), 0),
|
||||
VARROCK_CENTRE("Varrock Centre", new Location(3201, 3444, 3229, 3412), 0),
|
||||
VARROCK_EAST("Varrock East", new Location(3228, 3450, 3241, 3438), 0),
|
||||
VARROCK_WEST("Varrock West", new Location(3172, 3447, 3200, 3427), 0),
|
||||
WATERBIRTH_ISLAND("Waterbirth Island", new Location(2494, 3774, 2562, 3710), 0),
|
||||
WEST_ARDY("West Ardy", new Location(2452, 3336, 2557, 3265), 0),
|
||||
WINDERTODT_SOUTH_EAST("Windertodt South East", new Location(1630, 4007, 1651, 3987), 0),
|
||||
WINTERTODT_CAMP("Wintertodt Camp", new Location(1616, 3963, 1645, 3932), 0),
|
||||
WINTERTODT_ENTRANCE("Wintertodt Entrance", new Location(1617, 3986, 1641, 3964), 0),
|
||||
WINTERTODT_NORTHEAST("Wintertodt NorthEast", new Location(1630, 4027, 1651, 4008), 0),
|
||||
WINTERTODT_NORTHWEST("Wintertodt NorthWest", new Location(1608, 4028, 1629, 4008), 0),
|
||||
WINTERTODT_SOUTHWEST("Wintertodt SouthWest", new Location(1608, 4007, 1629, 3987), 0),
|
||||
WIZARDS_GUILD("Wizards Guild", new Location(2585, 3092, 2596, 3082), 0),
|
||||
WIZARDS_TOWER("Wizards Tower", new Location(3093, 3171, 3121, 3146), 0),
|
||||
YANILE_BANK("Yanile Bank", new Location(2608, 3097, 2616, 3087), 0),
|
||||
YANILLE_EAST("Yanille East", new Location(2576, 3110, 2621, 3071), 0),
|
||||
YANILLE_PORTAL("Yanille Portal", new Location(2537, 3108, 2551, 3091), 0),
|
||||
YANILLE_WEST("Yanille West", new Location(2532, 3110, 2575, 3071), 0),
|
||||
AXE_HUT("Axe Hut", new Location(3187, 3962, 3194, 3957), 0),
|
||||
BANDIT_CAMP("Bandit Camp", new Location(3017, 3712, 3059, 3681), 0),
|
||||
CALLISTO("Callisto", new Location(3266, 3863, 3315, 3827), 0),
|
||||
CEMETERY("Cemetery", new Location(2956, 3767, 2996, 3736), 0),
|
||||
CHAOS_FANATIC("Chaos Fanatic", new Location(2971, 3854, 2992, 3834), 0),
|
||||
CHAOS_TEMPLE("Chaos Temple", new Location(3220, 3632, 3255, 3593), 0),
|
||||
CHINS("Chins", new Location(3128, 3792, 3160, 3754), 0),
|
||||
CORP_CAVE("Corp Cave", new Location(3201, 3684, 3219, 3672), 0),
|
||||
CRAZY_ARCHAEOLOGIST("Crazy Archaeologist", new Location(2952, 3709, 2985, 3678), 0),
|
||||
DARK_WARRIORS("Dark Warriors", new Location(3014, 3648, 3046, 3616), 0),
|
||||
DWARVES("Dwarves", new Location(3230, 3805, 3264, 3779), 0),
|
||||
EAST_DRAGS("East Drags", new Location(3326, 3704, 3365, 3671), 0),
|
||||
ENTS("Ents", new Location(3300, 3627, 3320, 3584), 0),
|
||||
FIFTY_PORTS("50 ports", new Location(3301, 3923, 3315, 3909), 0),
|
||||
FIRE_GIANT_ENTRANCE("Fire Giant Entrance", new Location(3042, 3929, 3051, 3920), 0),
|
||||
GAP("Gap", new Location(3238, 3855, 3258, 3841), 0),
|
||||
GDZ("Gdz", new Location(3279, 3895, 3296, 3875), 0),
|
||||
GHORROCK("44s", new Location(2973, 3870, 2987, 3859), 0),
|
||||
GLORY_HILL("Glory Hill", new Location(3331, 3890, 3348, 3866), 0),
|
||||
GLORY_HOLE("Glory Hole", new Location(3352, 3897, 3386, 3869), 0),
|
||||
GRAVES("Graves", new Location(3128, 3686, 3181, 3658), 0),
|
||||
GRAVEYARD_DRAGS("Graveyard Drags", new Location(3129, 3717, 3172, 3691), 0),
|
||||
GOD_WARS_DUNGEON("God Wars Dungeon", new Location(3010, 3745, 3027, 3727), 0),
|
||||
HIGH_ALTAR("High Altar", new Location(2945, 3826, 2970, 3813), 0),
|
||||
HILL_GIANTS("Hill Giants", new Location(3282, 3687, 3300, 3674), 0),
|
||||
HOB_OBELISK("35 Obelisk", new Location(3097, 3804, 3115, 3785), 0),
|
||||
HOBGOBLINS("Hobgoblins", new Location(3073, 3775, 3104, 3745), 0),
|
||||
ICE_GATE("Ice Gate", new Location(2945, 3913, 2978, 3878), 0),
|
||||
ICE_ROCK("Ice Rock", new Location(2957, 3942, 2984, 3929), 0),
|
||||
KBD_CAGE("KBD CAGE", new Location(3007, 3855, 3021, 3839), 0),
|
||||
LAVA_DRAGS("Lava Drags", new Location(3175, 3857, 3221, 3805), 0),
|
||||
LAVA_MAZE_TELE("Lava Maze Tele", new Location(3019, 3842, 3044, 3812), 0),
|
||||
LEVER("Lever", new Location(3149, 3933, 3162, 3917), 0),
|
||||
MAGE_ARENA("Mage Arena", new Location(3088, 3949, 3123, 3919), 0),
|
||||
MAGE_BANK("Mage Bank", new Location(3082, 3960, 3103, 3952), 0),
|
||||
NEW_GATE("New Gate", new Location(3345, 3957, 3390, 3916), 0),
|
||||
PORTS_19("19s", new Location(3220, 3672, 3234, 3660), 0),
|
||||
OLD_GATE("Old Gate", new Location(3211, 3906, 3238, 3882), 0),
|
||||
PIRATE_HUT("Pirate Hut", new Location(3037, 3959, 3045, 3948), 0),
|
||||
RESOURCE_ARENA("Resource Arena", new Location(3174, 3946, 3195, 3923), 0),
|
||||
REV_BLACK_DRAGS("Rev Black Drags", new Location(3223, 10216, 3254, 10190), 0),
|
||||
REV_CAVE("Rev Cave", new Location(3128, 10232, 3225, 10059), 0),
|
||||
REV_DARK_BEAST("Rev Dark Beast", new Location(3243, 10154, 3264, 10136), 0),
|
||||
REV_ENTRANCE("Rev Entrance", new Location(3118, 3837, 3142, 3818), 0),
|
||||
INSIDE_REV_ENT("Inside Rev Ent.", new Location(3238, 10236, 3243, 10231), 0),
|
||||
MAIN_REV_CHAMBER("Main Rev Chamber", new Location(3227, 10187, 3261, 10157), 0),
|
||||
ROGUE_CASTLE("Rogue Castle", new Location(3275, 3947, 3299, 3920), 0),
|
||||
RUNE_ROCKS("Rune Rocks", new Location(3055, 3890, 3072, 3876), 0),
|
||||
SCORPIA("Scorpia", new Location(3216, 3949, 3248, 3935), 0),
|
||||
SINGLE_STRIP("Single Strip", new Location(3333, 3842, 3348, 3774), 0),
|
||||
LVL_18_REV_ENT("Lvl 18 Rev Ent", new Location(3071, 3660, 3092, 3645), 0),
|
||||
SPIDER_HILL("Spider Hill", new Location(3156, 3896, 3182, 3871), 0),
|
||||
PORTAL_13S("13s", new Location(3145, 3628, 3168, 3609), 0),
|
||||
VENENATIS("Venenatis", new Location(3298, 3759, 3353, 3722), 0),
|
||||
VETTION("Vet'tion", new Location(3183, 3796, 3227, 3765), 0),
|
||||
VOLCANO("Volcano", new Location(3345, 3957, 3390, 3916), 0),
|
||||
WEB("Web", new Location(3153, 3961, 3163, 3948), 0),
|
||||
WEST_DRAGS("West Drags", new Location(2960, 3627, 2992, 3598), 0),
|
||||
WILDY_AGILITY_COURSE("Wildy Agility Course", new Location(2988, 3967, 3008, 3906), 0);
|
||||
|
||||
|
||||
@Getter
|
||||
private final String name;
|
||||
@Getter
|
||||
private final WorldArea worldArea;
|
||||
@Getter
|
||||
private final Location location;
|
||||
|
||||
/**
|
||||
* Creates a location used to get the name of a location by a WorldPoint
|
||||
*
|
||||
* @param name - The name that is used to represent the area in overlays etc
|
||||
* @param location - A Location made out of 4 points on the world map
|
||||
* @param plane - The plane of the World Area
|
||||
*/
|
||||
WorldLocation(String name, Location location, int plane)
|
||||
{
|
||||
this.name = name;
|
||||
this.location = location;
|
||||
this.worldArea = new WorldArea(location.x, location.y, location.width, location.height, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all locations that aren't in the wild
|
||||
* @return - A Collection of non-wilderness WorldLocations
|
||||
*/
|
||||
public static Collection<WorldLocation> getNonWildernessLocations()
|
||||
{
|
||||
return Arrays.stream(WorldLocation.values()).filter(loc ->
|
||||
PvPUtil.getWildernessLevelFrom(loc.worldArea.toWorldPoint()) < 0).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns only the WorldLocations that are in the wilderness
|
||||
* @return - A Collection of WorldLocations in the wilderness
|
||||
*/
|
||||
public static Collection<WorldLocation> getWildernessLocations()
|
||||
{
|
||||
return Arrays.stream(WorldLocation.values()).filter(loc ->
|
||||
PvPUtil.getWildernessLevelFrom(loc.worldArea.toWorldPoint()) > 0).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static Map<WorldArea, String> getLocationMap()
|
||||
{
|
||||
Map<WorldArea, String> hashMap = new HashMap<>();
|
||||
Arrays.stream(values()).forEach(worldLocation ->
|
||||
hashMap.put(worldLocation.getWorldArea(), worldLocation.getName()));
|
||||
return hashMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the WorldLocation that a WorldPoint is in, or the closest WorldLocation to the point
|
||||
* @param worldPoint - the WorldPoint to find the WorldLocation of
|
||||
* @return - Containing location or closest location if it isn't in any
|
||||
*/
|
||||
public static String location(WorldPoint worldPoint)
|
||||
{
|
||||
final Map<WorldArea, String> locationMap = getLocationMap();
|
||||
int dist = 10000;
|
||||
String s = "";
|
||||
WorldArea closestArea = null;
|
||||
for (Map.Entry<WorldArea, String> entry : locationMap.entrySet())
|
||||
{
|
||||
WorldArea worldArea = entry.getKey();
|
||||
|
||||
if (worldArea.toWorldPointList().contains(worldPoint))
|
||||
{
|
||||
s = entry.getValue();
|
||||
return s;
|
||||
}
|
||||
int distTo = worldArea.distanceTo(worldPoint);
|
||||
if (distTo < dist)
|
||||
{
|
||||
dist = distTo;
|
||||
closestArea = worldArea;
|
||||
}
|
||||
}
|
||||
if (worldPoint.getY() > (Objects.requireNonNull(closestArea).toWorldPoint().getY() + closestArea.getHeight()))
|
||||
{
|
||||
s = s + "N";
|
||||
}
|
||||
if (worldPoint.getY() < closestArea.toWorldPoint().getY())
|
||||
{
|
||||
s = s + "S";
|
||||
}
|
||||
if (worldPoint.getX() < closestArea.toWorldPoint().getX())
|
||||
{
|
||||
s = s + "W";
|
||||
}
|
||||
if (worldPoint.getX() > (closestArea.toWorldPoint().getX() + closestArea.getWidth()))
|
||||
{
|
||||
s = s + "E";
|
||||
}
|
||||
s = s + " of ";
|
||||
s = s + locationMap.get(closestArea);
|
||||
if (s.startsWith(" of "))
|
||||
{
|
||||
s = s.substring(3);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
public static class Location
|
||||
{
|
||||
@Getter
|
||||
private final int x;
|
||||
@Getter
|
||||
private final int y;
|
||||
@Getter
|
||||
private final int x1;
|
||||
@Getter
|
||||
private final int y1;
|
||||
final int width;
|
||||
final int height;
|
||||
|
||||
Location(int x, int y, int x1, int y1)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.x1 = x1;
|
||||
this.y1 = y1;
|
||||
this.width = x1 - x;
|
||||
this.height = y - y1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "Location{" +
|
||||
"x=" + x +
|
||||
", y=" + y +
|
||||
", width=" + width +
|
||||
", height=" + height +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "WorldLocation{" +
|
||||
"name='" + name + '\'' +
|
||||
", worldArea=" + worldArea +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -27,13 +27,13 @@ package net.runelite.client.game.chatbox;
|
||||
/**
|
||||
* A modal input that lives in the chatbox panel.
|
||||
*/
|
||||
public abstract class ChatboxInput
|
||||
abstract class ChatboxInput
|
||||
{
|
||||
protected void open()
|
||||
void open()
|
||||
{
|
||||
}
|
||||
|
||||
protected void close()
|
||||
void close()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ import java.util.function.Consumer;
|
||||
import javax.inject.Singleton;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.ItemComposition;
|
||||
import net.runelite.api.ItemDefinition;
|
||||
import net.runelite.api.widgets.ItemQuantityMode;
|
||||
import net.runelite.api.widgets.JavaScriptCallback;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
@@ -59,7 +59,7 @@ public class ChatboxItemSearch extends ChatboxTextInput
|
||||
private final ItemManager itemManager;
|
||||
private final Client client;
|
||||
|
||||
private Map<Integer, ItemComposition> results = new LinkedHashMap<>();
|
||||
private Map<Integer, ItemDefinition> results = new LinkedHashMap<>();
|
||||
private String tooltipText;
|
||||
private int index = -1;
|
||||
|
||||
@@ -121,7 +121,7 @@ public class ChatboxItemSearch extends ChatboxTextInput
|
||||
int x = PADDING;
|
||||
int y = PADDING * 3;
|
||||
int idx = 0;
|
||||
for (ItemComposition itemComposition : results.values())
|
||||
for (ItemDefinition itemDefinition : results.values())
|
||||
{
|
||||
Widget item = container.createChild(-1, WidgetType.GRAPHIC);
|
||||
item.setXPositionMode(WidgetPositionMode.ABSOLUTE_LEFT);
|
||||
@@ -130,8 +130,8 @@ public class ChatboxItemSearch extends ChatboxTextInput
|
||||
item.setOriginalY(y + FONT_SIZE * 2);
|
||||
item.setOriginalHeight(ICON_HEIGHT);
|
||||
item.setOriginalWidth(ICON_WIDTH);
|
||||
item.setName("<col=ff9040>" + itemComposition.getName());
|
||||
item.setItemId(itemComposition.getId());
|
||||
item.setName("<col=ff9040>" + itemDefinition.getName());
|
||||
item.setItemId(itemDefinition.getId());
|
||||
item.setItemQuantity(10000);
|
||||
item.setItemQuantityMode(ItemQuantityMode.NEVER);
|
||||
item.setBorderType(1);
|
||||
@@ -152,7 +152,7 @@ public class ChatboxItemSearch extends ChatboxTextInput
|
||||
{
|
||||
if (onItemSelected != null)
|
||||
{
|
||||
onItemSelected.accept(itemComposition.getId());
|
||||
onItemSelected.accept(itemDefinition.getId());
|
||||
}
|
||||
|
||||
chatboxPanelManager.close();
|
||||
@@ -289,7 +289,7 @@ public class ChatboxItemSearch extends ChatboxTextInput
|
||||
|
||||
for (int i = 0; i < client.getItemCount() && results.size() < MAX_RESULTS; i++)
|
||||
{
|
||||
ItemComposition itemComposition = itemManager.getItemComposition(itemManager.canonicalize(i));
|
||||
ItemDefinition itemComposition = itemManager.getItemDefinition(itemManager.canonicalize(i));
|
||||
String name = itemComposition.getName().toLowerCase();
|
||||
// The client assigns "null" to item names of items it doesn't know about
|
||||
if (!name.equals("null") && name.contains(search))
|
||||
|
||||
@@ -41,7 +41,6 @@ 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;
|
||||
@@ -67,8 +66,8 @@ public class ChatboxPanelManager
|
||||
|
||||
@Inject
|
||||
private ChatboxPanelManager(EventBus eventBus, Client client, ClientThread clientThread,
|
||||
KeyManager keyManager, MouseManager mouseManager,
|
||||
Provider<ChatboxTextMenuInput> chatboxTextMenuInputProvider, Provider<ChatboxTextInput> chatboxTextInputProvider)
|
||||
KeyManager keyManager, MouseManager mouseManager,
|
||||
Provider<ChatboxTextMenuInput> chatboxTextMenuInputProvider, Provider<ChatboxTextInput> chatboxTextInputProvider)
|
||||
{
|
||||
this.client = client;
|
||||
this.clientThread = clientThread;
|
||||
@@ -79,6 +78,10 @@ public class ChatboxPanelManager
|
||||
|
||||
this.chatboxTextMenuInputProvider = chatboxTextMenuInputProvider;
|
||||
this.chatboxTextInputProvider = chatboxTextInputProvider;
|
||||
|
||||
|
||||
eventBus.subscribe(ScriptCallbackEvent.class, this, this::onScriptCallbackEvent);
|
||||
eventBus.subscribe(GameStateChanged.class, this, this::onGameStateChanged);
|
||||
}
|
||||
|
||||
public void close()
|
||||
@@ -103,7 +106,7 @@ public class ChatboxPanelManager
|
||||
{
|
||||
client.runScript(ScriptID.MESSAGE_LAYER_OPEN, 0);
|
||||
|
||||
eventBus.register(input);
|
||||
// eventBus.register(input);
|
||||
if (input instanceof KeyListener)
|
||||
{
|
||||
keyManager.registerKeyListener((KeyListener) input);
|
||||
@@ -150,8 +153,7 @@ public class ChatboxPanelManager
|
||||
.prompt(prompt);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onScriptCallbackEvent(ScriptCallbackEvent ev)
|
||||
private void onScriptCallbackEvent(ScriptCallbackEvent ev)
|
||||
{
|
||||
if (currentInput != null && "resetChatboxInput".equals(ev.getEventName()))
|
||||
{
|
||||
@@ -159,7 +161,6 @@ public class ChatboxPanelManager
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
private void onGameStateChanged(GameStateChanged ev)
|
||||
{
|
||||
if (currentInput != null && ev.getGameState() == GameState.LOGIN_SCREEN)
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
package net.runelite.client.game.chatbox;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.primitives.Ints;
|
||||
import com.google.inject.Inject;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
@@ -58,6 +57,7 @@ import net.runelite.api.widgets.WidgetType;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.input.KeyListener;
|
||||
import net.runelite.client.input.MouseListener;
|
||||
import net.runelite.client.util.MiscUtils;
|
||||
import net.runelite.client.util.Text;
|
||||
|
||||
@Slf4j
|
||||
@@ -156,12 +156,12 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse
|
||||
return this;
|
||||
}
|
||||
|
||||
public ChatboxTextInput cursorAt(int index)
|
||||
private ChatboxTextInput cursorAt(int index)
|
||||
{
|
||||
return cursorAt(index, index);
|
||||
}
|
||||
|
||||
public ChatboxTextInput cursorAt(int indexA, int indexB)
|
||||
private ChatboxTextInput cursorAt(int indexA, int indexB)
|
||||
{
|
||||
if (indexA < 0)
|
||||
{
|
||||
@@ -349,8 +349,8 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse
|
||||
|
||||
if (isStartLine || isEndLine || (cursorEnd > line.end && cursorStart < line.start))
|
||||
{
|
||||
final int cIdx = Ints.constrainToRange(cursorStart - line.start, 0, len);
|
||||
final int ceIdx = Ints.constrainToRange(cursorEnd - line.start, 0, len);
|
||||
final int cIdx = MiscUtils.clamp(cursorStart - line.start, 0, len);
|
||||
final int ceIdx = MiscUtils.clamp(cursorEnd - line.start, 0, len);
|
||||
|
||||
lt = Text.escapeJagex(text.substring(0, cIdx));
|
||||
mt = Text.escapeJagex(text.substring(cIdx, ceIdx));
|
||||
@@ -452,7 +452,7 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse
|
||||
int cx = p.x - ccl.getX() - ox;
|
||||
int cy = p.y - ccl.getY() - oy;
|
||||
|
||||
int currentLine = Ints.constrainToRange(cy / oh, 0, editLines.size() - 1);
|
||||
int currentLine = MiscUtils.clamp(cy / oh, 0, editLines.size() - 1);
|
||||
|
||||
final Line line = editLines.get(currentLine);
|
||||
final String tsValue = line.text;
|
||||
@@ -489,7 +489,7 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse
|
||||
break;
|
||||
}
|
||||
|
||||
charIndex = Ints.constrainToRange(charIndex, 0, tsValue.length());
|
||||
charIndex = MiscUtils.clamp(charIndex, 0, tsValue.length());
|
||||
return line.start + charIndex;
|
||||
};
|
||||
|
||||
@@ -722,9 +722,6 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse
|
||||
newPos++;
|
||||
break;
|
||||
case KeyEvent.VK_UP:
|
||||
ev.consume();
|
||||
newPos = getLineOffset.applyAsInt(code);
|
||||
break;
|
||||
case KeyEvent.VK_DOWN:
|
||||
ev.consume();
|
||||
newPos = getLineOffset.applyAsInt(code);
|
||||
|
||||
@@ -32,12 +32,12 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
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.api.widgets.WidgetType;
|
||||
import net.runelite.client.input.KeyListener;
|
||||
|
||||
public class ChatboxTextMenuInput extends ChatboxInput implements KeyListener
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.graphics;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Value;
|
||||
|
||||
@Value
|
||||
@RequiredArgsConstructor
|
||||
class PixelDistanceAlpha
|
||||
{
|
||||
private final int outerAlpha;
|
||||
private final int distArrayPos;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package net.runelite.client.menus;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.runelite.api.MenuEntry;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode
|
||||
public abstract class AbstractComparableEntry
|
||||
{
|
||||
String option = null;
|
||||
|
||||
String target = null;
|
||||
|
||||
int id = -1;
|
||||
|
||||
int type = -1;
|
||||
|
||||
boolean strictOption = true;
|
||||
|
||||
boolean strictTarget = true;
|
||||
|
||||
@EqualsAndHashCode.Exclude
|
||||
private int priority = 0;
|
||||
|
||||
public abstract boolean matches(MenuEntry entry);
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Lucas <https://github.com/Lucwousin>
|
||||
* 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 javax.annotation.Nonnull;
|
||||
import joptsimple.internal.Strings;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import net.runelite.api.MenuEntry;
|
||||
import net.runelite.client.util.Text;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class BaseComparableEntry extends AbstractComparableEntry
|
||||
{
|
||||
/**
|
||||
* If two entries are both suppose to be left click,
|
||||
* the entry with the higher priority will be selected.
|
||||
* This only effects left click priority entries.
|
||||
*/
|
||||
|
||||
public BaseComparableEntry(String option, String target, int id, int type, boolean strictOption, boolean strictTarget)
|
||||
{
|
||||
super.option = Text.standardize(option);
|
||||
super.target = Text.standardize(target);
|
||||
super.id = id;
|
||||
super.type = type;
|
||||
super.strictOption = strictOption;
|
||||
super.strictTarget = strictTarget;
|
||||
}
|
||||
|
||||
public boolean matches(@Nonnull MenuEntry entry)
|
||||
{
|
||||
String opt = entry.getOption();
|
||||
|
||||
if (strictOption && !StringUtils.equalsIgnoreCase(opt, option) || !strictOption && !StringUtils.containsIgnoreCase(opt, option))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strictTarget || !Strings.isNullOrEmpty(target))
|
||||
{
|
||||
String tgt = entry.getStandardizedTarget();
|
||||
|
||||
if (strictTarget && !tgt.equals(target) || !strictTarget && !tgt.contains(target))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (id != -1)
|
||||
{
|
||||
int id = entry.getIdentifier();
|
||||
|
||||
if (this.id != id)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (type != -1)
|
||||
{
|
||||
int type = entry.getOpcode();
|
||||
|
||||
if (this.type != type)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package net.runelite.client.menus;
|
||||
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.client.plugins.menuentryswapper.BankComparableEntry;
|
||||
|
||||
public interface ComparableEntries
|
||||
{
|
||||
/**
|
||||
* BaseComparableEntries should only be used if there's
|
||||
* no better ComparableEntry available.
|
||||
*
|
||||
* @param option has to equal entry option
|
||||
* @param target has to equal entry option
|
||||
*
|
||||
* @return a new BaseComparableEntry
|
||||
*/
|
||||
static BaseComparableEntry newBaseComparableEntry(String option, String target)
|
||||
{
|
||||
return new BaseComparableEntry(option, target, -1, -1, true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* BaseComparableEntries should only be used if there's
|
||||
* no better ComparableEntry available.
|
||||
*
|
||||
* @param option has to equal option
|
||||
* @param target equal or contains depending on strictTarget
|
||||
* @param strictTarget read up one line
|
||||
*
|
||||
* @return a new BaseComparableEntry
|
||||
*/
|
||||
static BaseComparableEntry newBaseComparableEntry(String option, String target, boolean strictTarget)
|
||||
{
|
||||
return new BaseComparableEntry(option, target, -1, -1, true, strictTarget);
|
||||
}
|
||||
|
||||
/**
|
||||
* BaseComparableEntries should only be used if there's
|
||||
* no better ComparableEntry available.
|
||||
*
|
||||
* @param option equal or contains depending on strictOption
|
||||
* @param target equal or contains depending on strictTarget
|
||||
* @param id has to be the same, or -1 to skip checking
|
||||
* @param type has to be the same, or -1 to skip checking
|
||||
* @param strictOption strict option or nah
|
||||
* @param strictTarget strict target or nah
|
||||
*
|
||||
* @return a new BaseComparableEntry
|
||||
*/
|
||||
static BaseComparableEntry newBaseComparableEntry(String option, String target, int id, int type, boolean strictOption, boolean strictTarget)
|
||||
{
|
||||
return new BaseComparableEntry(option, target, id, type, strictOption, strictTarget);
|
||||
}
|
||||
|
||||
/**
|
||||
* This comparable finds all items with itemName
|
||||
* in their name. It then checks the ItemDefinition
|
||||
* for each of them, to see if it's possible for
|
||||
* the item to have option as one of their options.
|
||||
*
|
||||
* This has to be ran on the clientthread!
|
||||
*/
|
||||
static ItemComparableEntry newInvItemComparableEntry(Client client, String option, String itemName)
|
||||
{
|
||||
return new ItemComparableEntry.InvItemComparableEntry(client, option, itemName);
|
||||
}
|
||||
|
||||
/**
|
||||
* This will only match items in the bank or in
|
||||
* your inventory if the bank is open. Withdraw-x anyone?
|
||||
*/
|
||||
static BankComparableEntry newBankComparableEntry(String option, String itemName)
|
||||
{
|
||||
return new BankComparableEntry(option, itemName, false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package net.runelite.client.menus;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.ItemDefinition;
|
||||
import net.runelite.api.MenuEntry;
|
||||
import net.runelite.client.util.Text;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Getter
|
||||
@Setter
|
||||
abstract class ItemComparableEntry extends AbstractComparableEntry
|
||||
{
|
||||
@EqualsAndHashCode.Exclude
|
||||
short[] itemIds;
|
||||
@EqualsAndHashCode.Exclude
|
||||
short itemCount;
|
||||
|
||||
public abstract boolean matches(MenuEntry entry);
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
static class InvItemComparableEntry extends ItemComparableEntry
|
||||
{
|
||||
public InvItemComparableEntry(Client client, String option, String itemName)
|
||||
{
|
||||
assert client.isClientThread() : "You can only create these on the clientthread";
|
||||
|
||||
this.target = Text.standardize(itemName);
|
||||
this.option = option;
|
||||
|
||||
short[] tmp = this.itemIds = new short[16];
|
||||
|
||||
final int itemCount = client.getItemCount();
|
||||
short found = 0;
|
||||
|
||||
for (short i = 0; i < itemCount; i++)
|
||||
{
|
||||
ItemDefinition def = client.getItemDefinition(i);
|
||||
if (def.getNote() != -1 || !StringUtils.containsIgnoreCase(def.getName(), target))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
boolean notValid = true;
|
||||
for (String opt : def.getInventoryActions())
|
||||
{
|
||||
if (opt != null && StringUtils.containsIgnoreCase(opt, option))
|
||||
{
|
||||
notValid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (notValid && !"use".equals(this.option))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (found >= tmp.length)
|
||||
{
|
||||
short[] rlyTmp = new short[found * 2];
|
||||
System.arraycopy(tmp, 0, rlyTmp, 0, found);
|
||||
tmp = rlyTmp;
|
||||
}
|
||||
|
||||
tmp[found++] = i;
|
||||
}
|
||||
|
||||
this.itemIds = new short[itemCount];
|
||||
this.itemCount = found;
|
||||
System.arraycopy(tmp, 0, this.itemIds, 0, found);
|
||||
}
|
||||
|
||||
public boolean matches(MenuEntry entry)
|
||||
{
|
||||
if (!StringUtils.containsIgnoreCase(entry.getOption(), this.option))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int entryId = entry.getIdentifier();
|
||||
for (short i = 0; i < itemCount; i++)
|
||||
{
|
||||
if (entryId == itemIds[i])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Robin <robin.weymans@gmail.com>
|
||||
* Copyright (c) 2019, Lucas <https://github.com/Lucwousin>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -26,29 +27,42 @@ package net.runelite.client.menus;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Multimap;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.MenuAction;
|
||||
import net.runelite.api.MenuEntry;
|
||||
import net.runelite.api.NPCComposition;
|
||||
import net.runelite.api.MenuOpcode;
|
||||
import static net.runelite.api.MenuOpcode.MENU_ACTION_DEPRIORITIZE_OFFSET;
|
||||
import net.runelite.api.NPCDefinition;
|
||||
import net.runelite.api.events.BeforeRender;
|
||||
import net.runelite.api.events.MenuEntryAdded;
|
||||
import net.runelite.api.events.MenuOpened;
|
||||
import net.runelite.api.events.MenuOptionClicked;
|
||||
import net.runelite.api.events.NpcActionChanged;
|
||||
import net.runelite.api.events.PlayerMenuOptionClicked;
|
||||
import net.runelite.api.events.PlayerMenuOptionsChanged;
|
||||
import net.runelite.api.events.WidgetMenuOptionClicked;
|
||||
import net.runelite.api.events.WidgetPressed;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import static net.runelite.client.menus.ComparableEntries.newBaseComparableEntry;
|
||||
import net.runelite.client.util.Text;
|
||||
|
||||
@Singleton
|
||||
@@ -69,12 +83,28 @@ public class MenuManager
|
||||
//Used to manage custom non-player menu options
|
||||
private final Multimap<Integer, WidgetMenuOption> managedMenuOptions = HashMultimap.create();
|
||||
private final Set<String> npcMenuOptions = new HashSet<>();
|
||||
private final HashSet<AbstractComparableEntry> priorityEntries = new HashSet<>();
|
||||
private LinkedHashMap<MenuEntry, AbstractComparableEntry> currentPriorityEntries = new LinkedHashMap<>();
|
||||
private final HashSet<AbstractComparableEntry> hiddenEntries = new HashSet<>();
|
||||
private final HashMap<AbstractComparableEntry, AbstractComparableEntry> swaps = new HashMap<>();
|
||||
|
||||
private MenuEntry leftClickEntry = null;
|
||||
private MenuEntry firstEntry = null;
|
||||
|
||||
@Inject
|
||||
private MenuManager(Client client, EventBus eventBus)
|
||||
{
|
||||
this.client = client;
|
||||
this.eventBus = eventBus;
|
||||
|
||||
|
||||
eventBus.subscribe(MenuOpened.class, this, this::onMenuOpened);
|
||||
eventBus.subscribe(MenuEntryAdded.class, this, this::onMenuEntryAdded);
|
||||
eventBus.subscribe(BeforeRender.class, this, this::onBeforeRender);
|
||||
eventBus.subscribe(PlayerMenuOptionsChanged.class, this, this::onPlayerMenuOptionsChanged);
|
||||
eventBus.subscribe(NpcActionChanged.class, this, this::onNpcActionChanged);
|
||||
eventBus.subscribe(WidgetPressed.class, this, this::onWidgetPressed);
|
||||
eventBus.subscribe(MenuOptionClicked.class, this, this::onMenuOptionClicked);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -114,30 +144,183 @@ public class MenuManager
|
||||
return false;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onMenuEntryAdded(MenuEntryAdded event)
|
||||
private void onMenuOpened(MenuOpened event)
|
||||
{
|
||||
currentPriorityEntries.clear();
|
||||
|
||||
// Need to reorder the list to normal, then rebuild with swaps
|
||||
MenuEntry[] oldEntries = event.getMenuEntries();
|
||||
|
||||
firstEntry = null;
|
||||
|
||||
List<MenuEntry> newEntries = Lists.newArrayList(oldEntries);
|
||||
|
||||
boolean shouldDeprioritize = false;
|
||||
|
||||
prioritizer:
|
||||
for (MenuEntry entry : oldEntries)
|
||||
{
|
||||
for (AbstractComparableEntry p : priorityEntries)
|
||||
{
|
||||
// Create list of priority entries, and remove from menus
|
||||
if (p.matches(entry))
|
||||
{
|
||||
// Other entries need to be deprioritized if their types are lower than 1000
|
||||
if (entry.getOpcode() >= 1000 && !shouldDeprioritize)
|
||||
{
|
||||
shouldDeprioritize = true;
|
||||
}
|
||||
currentPriorityEntries.put(entry, p);
|
||||
newEntries.remove(entry);
|
||||
continue prioritizer;
|
||||
}
|
||||
}
|
||||
|
||||
if (newEntries.size() > 0)
|
||||
{
|
||||
// Swap first matching entry to top
|
||||
for (AbstractComparableEntry src : swaps.keySet())
|
||||
{
|
||||
if (!src.matches(entry))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
MenuEntry swapFrom = null;
|
||||
|
||||
AbstractComparableEntry from = swaps.get(src);
|
||||
|
||||
for (MenuEntry e : newEntries)
|
||||
{
|
||||
if (from.matches(e))
|
||||
{
|
||||
swapFrom = e;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Do not need to swap with itself or if the swapFrom is already the first entry
|
||||
if (swapFrom != null && swapFrom != entry && swapFrom != Iterables.getLast(newEntries))
|
||||
{
|
||||
// Deprioritize entries if the swaps are not in similar opcode groups
|
||||
if ((swapFrom.getOpcode() >= 1000 && entry.getOpcode() < 1000) || (entry.getOpcode() >= 1000 && swapFrom.getOpcode() < 1000) && !shouldDeprioritize)
|
||||
{
|
||||
shouldDeprioritize = true;
|
||||
}
|
||||
|
||||
int indexFrom = newEntries.indexOf(swapFrom);
|
||||
int indexTo = newEntries.indexOf(entry);
|
||||
|
||||
Collections.swap(newEntries, indexFrom, indexTo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldDeprioritize)
|
||||
{
|
||||
for (MenuEntry entry : newEntries)
|
||||
{
|
||||
if (entry.getOpcode() <= MENU_ACTION_DEPRIORITIZE_OFFSET)
|
||||
{
|
||||
entry.setOpcode(entry.getOpcode() + MENU_ACTION_DEPRIORITIZE_OFFSET);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!currentPriorityEntries.isEmpty())
|
||||
{
|
||||
newEntries.addAll(currentPriorityEntries.entrySet().stream()
|
||||
.sorted(Comparator.comparingInt(e -> e.getValue().getPriority()))
|
||||
.map(Map.Entry::getKey)
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
MenuEntry[] arrayEntries = newEntries.toArray(new MenuEntry[0]);
|
||||
|
||||
// Need to set the event entries to prevent conflicts
|
||||
event.setMenuEntries(arrayEntries);
|
||||
client.setMenuEntries(arrayEntries);
|
||||
}
|
||||
|
||||
private void onMenuEntryAdded(MenuEntryAdded event)
|
||||
{
|
||||
for (AbstractComparableEntry e : hiddenEntries)
|
||||
{
|
||||
if (e.matches(event.getMenuEntry()))
|
||||
{
|
||||
client.setMenuOptionCount(client.getMenuOptionCount() - 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int widgetId = event.getActionParam1();
|
||||
Collection<WidgetMenuOption> options = managedMenuOptions.get(widgetId);
|
||||
MenuEntry[] menuEntries = client.getMenuEntries();
|
||||
|
||||
for (WidgetMenuOption currentMenu : options)
|
||||
{
|
||||
if (!menuContainsCustomMenu(currentMenu))//Don't add if we have already added it to this widget
|
||||
{
|
||||
MenuEntry[] menuEntries = client.getMenuEntries();
|
||||
menuEntries = Arrays.copyOf(menuEntries, menuEntries.length + 1);
|
||||
|
||||
MenuEntry menuEntry = menuEntries[menuEntries.length - 1] = new MenuEntry();
|
||||
menuEntry.setOption(currentMenu.getMenuOption());
|
||||
menuEntry.setParam1(widgetId);
|
||||
menuEntry.setTarget(currentMenu.getMenuTarget());
|
||||
menuEntry.setType(MenuAction.RUNELITE.getId());
|
||||
menuEntry.setOpcode(MenuOpcode.RUNELITE.getId());
|
||||
|
||||
client.setMenuEntries(menuEntries);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onBeforeRender(BeforeRender event)
|
||||
{
|
||||
rebuildLeftClickMenu();
|
||||
}
|
||||
|
||||
private MenuEntry rebuildLeftClickMenu()
|
||||
{
|
||||
if (client.isMenuOpen())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int menuOptionCount = client.getMenuOptionCount();
|
||||
if (menuOptionCount <= 2)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
client.sortMenuEntries();
|
||||
|
||||
firstEntry = null;
|
||||
MenuEntry[] entries = new MenuEntry[menuOptionCount + priorityEntries.size()];
|
||||
System.arraycopy(client.getMenuEntries(), 0, entries, 0, menuOptionCount);
|
||||
|
||||
if (!priorityEntries.isEmpty())
|
||||
{
|
||||
indexPriorityEntries(entries, menuOptionCount);
|
||||
}
|
||||
|
||||
if (firstEntry == null && !swaps.isEmpty())
|
||||
{
|
||||
indexSwapEntries(entries, menuOptionCount);
|
||||
}
|
||||
|
||||
|
||||
if (firstEntry == null)
|
||||
{
|
||||
// stop being null smh
|
||||
firstEntry = entries[menuOptionCount - 1];
|
||||
}
|
||||
|
||||
client.setMenuEntries(entries);
|
||||
|
||||
return firstEntry;
|
||||
}
|
||||
|
||||
public void addPlayerMenuItem(String menuText)
|
||||
{
|
||||
Preconditions.checkNotNull(menuText);
|
||||
@@ -164,8 +347,7 @@ public class MenuManager
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onPlayerMenuOptionsChanged(PlayerMenuOptionsChanged event)
|
||||
private void onPlayerMenuOptionsChanged(PlayerMenuOptionsChanged event)
|
||||
{
|
||||
int idx = event.getIndex();
|
||||
|
||||
@@ -189,17 +371,16 @@ public class MenuManager
|
||||
addPlayerMenuItem(newIdx, menuText);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onNpcActionChanged(NpcActionChanged event)
|
||||
private void onNpcActionChanged(NpcActionChanged event)
|
||||
{
|
||||
NPCComposition composition = event.getNpcComposition();
|
||||
NPCDefinition composition = event.getNpcDefinition();
|
||||
for (String npcOption : npcMenuOptions)
|
||||
{
|
||||
addNpcOption(composition, npcOption);
|
||||
}
|
||||
}
|
||||
|
||||
private void addNpcOption(NPCComposition composition, String npcOption)
|
||||
private void addNpcOption(NPCDefinition composition, String npcOption)
|
||||
{
|
||||
String[] actions = composition.getActions();
|
||||
int unused = -1;
|
||||
@@ -221,7 +402,7 @@ public class MenuManager
|
||||
actions[unused] = npcOption;
|
||||
}
|
||||
|
||||
private void removeNpcOption(NPCComposition composition, String npcOption)
|
||||
private void removeNpcOption(NPCDefinition composition, String npcOption)
|
||||
{
|
||||
String[] actions = composition.getActions();
|
||||
|
||||
@@ -239,49 +420,67 @@ public class MenuManager
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onMenuOptionClicked(MenuOptionClicked event)
|
||||
private void onWidgetPressed(WidgetPressed event)
|
||||
{
|
||||
if (event.getMenuAction() != MenuAction.RUNELITE)
|
||||
leftClickEntry = rebuildLeftClickMenu();
|
||||
}
|
||||
|
||||
private void onMenuOptionClicked(MenuOptionClicked event)
|
||||
{
|
||||
if (!client.isMenuOpen() && event.isAuthentic())
|
||||
{
|
||||
if (event.getMouseButton() != 0)
|
||||
{
|
||||
leftClickEntry = rebuildLeftClickMenu();
|
||||
}
|
||||
|
||||
if (leftClickEntry != null)
|
||||
{
|
||||
event.setMenuEntry(leftClickEntry);
|
||||
leftClickEntry = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (event.getMenuOpcode() != MenuOpcode.RUNELITE)
|
||||
{
|
||||
return; // not a player menu
|
||||
}
|
||||
|
||||
int widgetId = event.getWidgetId();
|
||||
int widgetId = event.getActionParam1();
|
||||
Collection<WidgetMenuOption> options = managedMenuOptions.get(widgetId);
|
||||
|
||||
for (WidgetMenuOption curMenuOption : options)
|
||||
{
|
||||
if (curMenuOption.getMenuTarget().equals(event.getMenuTarget())
|
||||
&& curMenuOption.getMenuOption().equals(event.getMenuOption()))
|
||||
if (curMenuOption.getMenuTarget().equals(event.getTarget())
|
||||
&& curMenuOption.getMenuOption().equals(event.getOption()))
|
||||
{
|
||||
WidgetMenuOptionClicked customMenu = new WidgetMenuOptionClicked();
|
||||
customMenu.setMenuOption(event.getMenuOption());
|
||||
customMenu.setMenuTarget(event.getMenuTarget());
|
||||
customMenu.setMenuOption(event.getOption());
|
||||
customMenu.setMenuTarget(event.getTarget());
|
||||
customMenu.setWidget(curMenuOption.getWidget());
|
||||
eventBus.post(customMenu);
|
||||
eventBus.post(WidgetMenuOptionClicked.class, customMenu);
|
||||
return; // don't continue because it's not a player option
|
||||
}
|
||||
}
|
||||
|
||||
String target = event.getMenuTarget();
|
||||
String target = event.getTarget();
|
||||
|
||||
// removes tags and level from player names for example:
|
||||
// <col=ffffff>username<col=40ff00> (level-42) or <col=ffffff><img=2>username</col>
|
||||
String username = Text.removeTags(target).split("[(]")[0].trim();
|
||||
|
||||
PlayerMenuOptionClicked playerMenuOptionClicked = new PlayerMenuOptionClicked();
|
||||
playerMenuOptionClicked.setMenuOption(event.getMenuOption());
|
||||
playerMenuOptionClicked.setMenuOption(event.getOption());
|
||||
playerMenuOptionClicked.setMenuTarget(username);
|
||||
|
||||
eventBus.post(playerMenuOptionClicked);
|
||||
eventBus.post(PlayerMenuOptionClicked.class, playerMenuOptionClicked);
|
||||
}
|
||||
|
||||
private void addPlayerMenuItem(int playerOptionIndex, String menuText)
|
||||
{
|
||||
client.getPlayerOptions()[playerOptionIndex] = menuText;
|
||||
client.getPlayerOptionsPriorities()[playerOptionIndex] = true;
|
||||
client.getPlayerMenuTypes()[playerOptionIndex] = MenuAction.RUNELITE.getId();
|
||||
client.getPlayerMenuTypes()[playerOptionIndex] = MenuOpcode.RUNELITE.getId();
|
||||
|
||||
playerMenuIndexMap.put(playerOptionIndex, menuText);
|
||||
}
|
||||
@@ -307,4 +506,402 @@ public class MenuManager
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds to the set of menu entries which when present, will remove all entries except for this one
|
||||
*/
|
||||
public AbstractComparableEntry addPriorityEntry(String option, String target)
|
||||
{
|
||||
option = Text.standardize(option);
|
||||
target = Text.standardize(target);
|
||||
|
||||
AbstractComparableEntry entry = newBaseComparableEntry(option, target);
|
||||
|
||||
priorityEntries.add(entry);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
public void removePriorityEntry(String option, String target)
|
||||
{
|
||||
option = Text.standardize(option);
|
||||
target = Text.standardize(target);
|
||||
|
||||
AbstractComparableEntry entry = newBaseComparableEntry(option, target);
|
||||
|
||||
priorityEntries.removeIf(entry::equals);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds to the set of menu entries which when present, will remove all entries except for this one
|
||||
* This method will add one with strict option, but not-strict target (contains for target, equals for option)
|
||||
*/
|
||||
public AbstractComparableEntry addPriorityEntry(String option)
|
||||
{
|
||||
option = Text.standardize(option);
|
||||
|
||||
AbstractComparableEntry entry = newBaseComparableEntry(option, "", false);
|
||||
|
||||
priorityEntries.add(entry);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
public AbstractComparableEntry addPriorityEntry(String option, boolean strictOption)
|
||||
{
|
||||
option = Text.standardize(option);
|
||||
|
||||
AbstractComparableEntry entry =
|
||||
newBaseComparableEntry(option, "", -1, -1, false, strictOption);
|
||||
|
||||
priorityEntries.add(entry);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
public AbstractComparableEntry addPriorityEntry(AbstractComparableEntry entry)
|
||||
{
|
||||
priorityEntries.add(entry);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
public void removePriorityEntry(AbstractComparableEntry entry)
|
||||
{
|
||||
priorityEntries.removeIf(entry::equals);
|
||||
}
|
||||
|
||||
public void removePriorityEntry(String option)
|
||||
{
|
||||
option = Text.standardize(option);
|
||||
|
||||
AbstractComparableEntry entry = newBaseComparableEntry(option, "", false);
|
||||
|
||||
priorityEntries.removeIf(entry::equals);
|
||||
}
|
||||
|
||||
public void removePriorityEntry(String option, boolean strictOption)
|
||||
{
|
||||
option = Text.standardize(option);
|
||||
|
||||
AbstractComparableEntry entry =
|
||||
newBaseComparableEntry(option, "", -1, -1, false, strictOption);
|
||||
|
||||
priorityEntries.removeIf(entry::equals);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds to the map of swaps. Strict options, not strict target but target1=target2
|
||||
*/
|
||||
public void addSwap(String option, String target, String option2)
|
||||
{
|
||||
addSwap(option, target, option2, target, true, false);
|
||||
}
|
||||
|
||||
public void removeSwap(String option, String target, String option2)
|
||||
{
|
||||
removeSwap(option, target, option2, target, true, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds to the map of swaps.
|
||||
*/
|
||||
public void addSwap(String option, String target, String option2, String target2, boolean strictOption, boolean strictTarget)
|
||||
{
|
||||
option = Text.standardize(option);
|
||||
target = Text.standardize(target);
|
||||
|
||||
option2 = Text.standardize(option2);
|
||||
target2 = Text.standardize(target2);
|
||||
|
||||
AbstractComparableEntry swapFrom = newBaseComparableEntry(option, target, -1, -1, strictOption, strictTarget);
|
||||
AbstractComparableEntry swapTo = newBaseComparableEntry(option2, target2, -1, -1, strictOption, strictTarget);
|
||||
|
||||
if (swapTo.equals(swapFrom))
|
||||
{
|
||||
log.warn("You shouldn't try swapping an entry for itself");
|
||||
return;
|
||||
}
|
||||
|
||||
swaps.put(swapFrom, swapTo);
|
||||
}
|
||||
|
||||
|
||||
public void removeSwap(String option, String target, String option2, String target2, boolean strictOption, boolean strictTarget)
|
||||
{
|
||||
option = Text.standardize(option);
|
||||
target = Text.standardize(target);
|
||||
|
||||
option2 = Text.standardize(option2);
|
||||
target2 = Text.standardize(target2);
|
||||
|
||||
AbstractComparableEntry swapFrom = newBaseComparableEntry(option, target, -1, -1, strictOption, strictTarget);
|
||||
AbstractComparableEntry swapTo = newBaseComparableEntry(option2, target2, -1, -1, strictOption, strictTarget);
|
||||
|
||||
removeSwap(swapFrom, swapTo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds to the map of swaps. - Strict option + target
|
||||
*/
|
||||
public void addSwap(String option, String target, String option2, String target2)
|
||||
{
|
||||
addSwap(option, target, option2, target2, false, false);
|
||||
}
|
||||
|
||||
public void removeSwap(String option, String target, String option2, String target2)
|
||||
{
|
||||
removeSwap(option, target, option2, target2, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds to the map of swaps - Pre-baked entry
|
||||
*/
|
||||
public void addSwap(AbstractComparableEntry swapFrom, AbstractComparableEntry swapTo)
|
||||
{
|
||||
if (swapTo.equals(swapFrom))
|
||||
{
|
||||
log.warn("You shouldn't try swapping an entry for itself");
|
||||
return;
|
||||
}
|
||||
|
||||
swaps.put(swapFrom, swapTo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds to the map of swaps - Non-strict option/target, but with opcode & id
|
||||
* ID's of -1 are ignored in matches()!
|
||||
*/
|
||||
public void addSwap(String option, String target, int id, int type, String option2, String target2, int id2, int type2)
|
||||
{
|
||||
option = Text.standardize(option);
|
||||
target = Text.standardize(target);
|
||||
|
||||
option2 = Text.standardize(option2);
|
||||
target2 = Text.standardize(target2);
|
||||
|
||||
AbstractComparableEntry swapFrom = newBaseComparableEntry(option, target, id, type, false, false);
|
||||
AbstractComparableEntry swapTo = newBaseComparableEntry(option2, target2, id2, type2, false, false);
|
||||
|
||||
if (swapTo.equals(swapFrom))
|
||||
{
|
||||
log.warn("You shouldn't try swapping an entry for itself");
|
||||
return;
|
||||
}
|
||||
|
||||
swaps.put(swapFrom, swapTo);
|
||||
}
|
||||
|
||||
public void removeSwap(String option, String target, int id, int type, String option2, String target2, int id2, int type2)
|
||||
{
|
||||
option = Text.standardize(option);
|
||||
target = Text.standardize(target);
|
||||
|
||||
option2 = Text.standardize(option2);
|
||||
target2 = Text.standardize(target2);
|
||||
|
||||
AbstractComparableEntry swapFrom = newBaseComparableEntry(option, target, id, type, false, false);
|
||||
AbstractComparableEntry swapTo = newBaseComparableEntry(option2, target2, id2, type2, false, false);
|
||||
|
||||
swaps.entrySet().removeIf(e -> e.getKey().equals(swapFrom) && e.getValue().equals(swapTo));
|
||||
}
|
||||
|
||||
public void removeSwap(AbstractComparableEntry swapFrom, AbstractComparableEntry swapTo)
|
||||
{
|
||||
swaps.entrySet().removeIf(e -> e.getKey().equals(swapFrom) && e.getValue().equals(swapTo));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all swaps with target
|
||||
*/
|
||||
public void removeSwaps(String withTarget)
|
||||
{
|
||||
final String target = Text.standardize(withTarget);
|
||||
|
||||
swaps.keySet().removeIf(e -> e.getTarget().equals(target));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds to the set of menu entries which when present, will be hidden from the menu
|
||||
*/
|
||||
public void addHiddenEntry(String option, String target)
|
||||
{
|
||||
option = Text.standardize(option);
|
||||
target = Text.standardize(target);
|
||||
|
||||
AbstractComparableEntry entry = newBaseComparableEntry(option, target);
|
||||
|
||||
hiddenEntries.add(entry);
|
||||
}
|
||||
|
||||
public void removeHiddenEntry(String option, String target)
|
||||
{
|
||||
option = Text.standardize(option);
|
||||
target = Text.standardize(target);
|
||||
|
||||
AbstractComparableEntry entry = newBaseComparableEntry(option, target);
|
||||
|
||||
hiddenEntries.removeIf(entry::equals);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds to the set of menu entries which when present, will be hidden from the menu
|
||||
* This method will add one with strict option, but not-strict target (contains for target, equals for option)
|
||||
*/
|
||||
public void addHiddenEntry(String option)
|
||||
{
|
||||
option = Text.standardize(option);
|
||||
|
||||
AbstractComparableEntry entry = newBaseComparableEntry(option, "", false);
|
||||
|
||||
hiddenEntries.add(entry);
|
||||
}
|
||||
|
||||
public void removeHiddenEntry(String option)
|
||||
{
|
||||
option = Text.standardize(option);
|
||||
|
||||
AbstractComparableEntry entry = newBaseComparableEntry(option, "", false);
|
||||
|
||||
hiddenEntries.removeIf(entry::equals);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds to the set of hidden entries.
|
||||
*/
|
||||
public void addHiddenEntry(String option, String target, boolean strictOption, boolean strictTarget)
|
||||
{
|
||||
option = Text.standardize(option);
|
||||
target = Text.standardize(target);
|
||||
|
||||
AbstractComparableEntry entry = newBaseComparableEntry(option, target, -1, -1, strictOption, strictTarget);
|
||||
|
||||
hiddenEntries.add(entry);
|
||||
}
|
||||
|
||||
public void removeHiddenEntry(String option, String target, boolean strictOption, boolean strictTarget)
|
||||
{
|
||||
option = Text.standardize(option);
|
||||
target = Text.standardize(target);
|
||||
|
||||
AbstractComparableEntry entry = newBaseComparableEntry(option, target, -1, -1, strictOption, strictTarget);
|
||||
|
||||
hiddenEntries.remove(entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds to the set of hidden entries - Pre-baked Comparable entry
|
||||
*/
|
||||
public void addHiddenEntry(AbstractComparableEntry entry)
|
||||
{
|
||||
hiddenEntries.add(entry);
|
||||
}
|
||||
|
||||
public void removeHiddenEntry(AbstractComparableEntry entry)
|
||||
{
|
||||
hiddenEntries.remove(entry);
|
||||
}
|
||||
|
||||
// This could use some optimization
|
||||
private void indexPriorityEntries(MenuEntry[] entries, int menuOptionCount)
|
||||
{
|
||||
// create a array of priority entries so we can sort those
|
||||
final SortMapping[] prios = new SortMapping[entries.length - menuOptionCount];
|
||||
|
||||
int prioAmt = 0;
|
||||
for (int i = 0; i < menuOptionCount; i++)
|
||||
{
|
||||
final MenuEntry entry = entries[i];
|
||||
for (AbstractComparableEntry prio : priorityEntries)
|
||||
{
|
||||
if (!prio.matches(entry))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
final SortMapping map = new SortMapping(prio.getPriority(), entry);
|
||||
prios[prioAmt++] = map;
|
||||
entries[i] = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (prioAmt == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Sort em!
|
||||
Arrays.sort(prios, 0, prioAmt);
|
||||
int i;
|
||||
|
||||
// Just place them after the standard entries. clientmixin ignores null entries
|
||||
for (i = 0; i < prioAmt; i++)
|
||||
{
|
||||
entries[menuOptionCount + i] = prios[i].entry;
|
||||
}
|
||||
|
||||
firstEntry = entries[menuOptionCount + i - 1];
|
||||
|
||||
}
|
||||
|
||||
private void indexSwapEntries(MenuEntry[] entries, int menuOptionCount)
|
||||
{
|
||||
// firstEntry was null, so it's the entry at count - 1
|
||||
final MenuEntry first = entries[menuOptionCount - 1];
|
||||
if (first == null)
|
||||
{
|
||||
log.debug("First entry is null");
|
||||
return;
|
||||
}
|
||||
|
||||
Set<AbstractComparableEntry> values = new HashSet<>();
|
||||
|
||||
for (Map.Entry<AbstractComparableEntry, AbstractComparableEntry> pair : swaps.entrySet())
|
||||
{
|
||||
if (pair.getKey().matches(first))
|
||||
{
|
||||
values.add(pair.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
if (values.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Backwards so we swap with the otherwise highest one
|
||||
// Count - 2 so we don't compare the entry against itself
|
||||
outer:
|
||||
for (int i = menuOptionCount - 2; i > 0; i--)
|
||||
{
|
||||
final MenuEntry entry = entries[i];
|
||||
for (AbstractComparableEntry swap : values)
|
||||
{
|
||||
if (!swap.matches(entry))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
entries[i] = first;
|
||||
entries[menuOptionCount - 1] = entry;
|
||||
firstEntry = entry;
|
||||
break outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
private class SortMapping implements Comparable<SortMapping>
|
||||
{
|
||||
private final int priority;
|
||||
private final MenuEntry entry;
|
||||
|
||||
@Override
|
||||
public int compareTo(@Nonnull SortMapping mapping)
|
||||
{
|
||||
return Integer.compare(this.priority, mapping.priority);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,24 +24,23 @@
|
||||
*/
|
||||
package net.runelite.client.menus;
|
||||
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
|
||||
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"
|
||||
* The left hand text to be displayed on the menu option. Ex. the option 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"
|
||||
* The right hand text to be displayed on the menu option Ex. the target 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.
|
||||
* The color that the target should be. Defaults to the brownish color that most menu options have.
|
||||
*/
|
||||
private Color color = JagexColors.MENU_TARGET;
|
||||
|
||||
@@ -60,7 +59,7 @@ public final class WidgetMenuOption
|
||||
public WidgetMenuOption(String menuOption, String menuTarget, WidgetInfo widget)
|
||||
{
|
||||
this.menuOption = menuOption;
|
||||
setMenuTarget(menuTarget);
|
||||
this.menuTarget = menuTarget;
|
||||
this.widget = widget;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,11 +27,15 @@ package net.runelite.client.plugins;
|
||||
import com.google.inject.Binder;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Module;
|
||||
import java.io.File;
|
||||
|
||||
public abstract class Plugin implements Module
|
||||
{
|
||||
protected Injector injector;
|
||||
|
||||
public File file;
|
||||
public PluginClassLoader loader;
|
||||
|
||||
@Override
|
||||
public void configure(Binder binder)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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.plugins;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
|
||||
/**
|
||||
* A classloader for external plugins
|
||||
*
|
||||
* @author Adam
|
||||
*/
|
||||
public class PluginClassLoader extends URLClassLoader
|
||||
{
|
||||
private final ClassLoader parent;
|
||||
|
||||
public PluginClassLoader(File plugin, ClassLoader parent) throws MalformedURLException
|
||||
{
|
||||
super(
|
||||
new URL[]
|
||||
{
|
||||
plugin.toURI().toURL()
|
||||
},
|
||||
null // null or else class path scanning includes everything from the main class loader
|
||||
);
|
||||
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> loadClass(String name) throws ClassNotFoundException
|
||||
{
|
||||
try
|
||||
{
|
||||
return super.loadClass(name);
|
||||
}
|
||||
catch (ClassNotFoundException ex)
|
||||
{
|
||||
// fall back to main class loader
|
||||
return parent.loadClass(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -58,4 +58,6 @@ public @interface PluginDescriptor
|
||||
boolean developerPlugin() default false;
|
||||
|
||||
boolean loadWhenOutdated() default false;
|
||||
|
||||
PluginType type() default PluginType.GENERAL_USE;
|
||||
}
|
||||
|
||||
@@ -43,12 +43,18 @@ import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
@@ -57,20 +63,19 @@ import javax.inject.Singleton;
|
||||
import javax.swing.SwingUtilities;
|
||||
import lombok.Setter;
|
||||
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.Config;
|
||||
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.PluginChanged;
|
||||
import net.runelite.client.events.SessionClose;
|
||||
import net.runelite.client.events.SessionOpen;
|
||||
import net.runelite.client.task.Schedule;
|
||||
import net.runelite.client.task.ScheduledMethod;
|
||||
import net.runelite.client.task.Scheduler;
|
||||
import net.runelite.client.ui.SplashScreen;
|
||||
import net.runelite.client.ui.RuneLiteSplashScreen;
|
||||
import net.runelite.client.util.GameEventManager;
|
||||
|
||||
@Singleton
|
||||
@@ -91,7 +96,10 @@ public class PluginManager
|
||||
private final List<Plugin> plugins = new CopyOnWriteArrayList<>();
|
||||
private final List<Plugin> activePlugins = new CopyOnWriteArrayList<>();
|
||||
private final String runeliteGroupName = RuneLiteConfig.class
|
||||
.getAnnotation(ConfigGroup.class).value();
|
||||
.getAnnotation(ConfigGroup.class).value();
|
||||
|
||||
@Inject
|
||||
PluginWatcher pluginWatcher;
|
||||
|
||||
@Setter
|
||||
boolean isOutdated;
|
||||
@@ -112,16 +120,25 @@ public class PluginManager
|
||||
this.configManager = configManager;
|
||||
this.executor = executor;
|
||||
this.sceneTileManager = sceneTileManager;
|
||||
|
||||
if (eventBus != null)
|
||||
{
|
||||
eventBus.subscribe(SessionOpen.class, this, this::onSessionOpen);
|
||||
eventBus.subscribe(SessionClose.class, this, this::onSessionClose);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onSessionOpen(SessionOpen event)
|
||||
public void watch()
|
||||
{
|
||||
pluginWatcher.start();
|
||||
}
|
||||
|
||||
private void onSessionOpen(SessionOpen event)
|
||||
{
|
||||
refreshPlugins();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onSessionClose(SessionClose event)
|
||||
private void onSessionClose(SessionClose event)
|
||||
{
|
||||
refreshPlugins();
|
||||
}
|
||||
@@ -162,7 +179,7 @@ public class PluginManager
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<Config> getPluginConfigProxies()
|
||||
private List<Config> getPluginConfigProxies()
|
||||
{
|
||||
List<Injector> injectors = new ArrayList<>();
|
||||
injectors.add(RuneLite.getInjector());
|
||||
@@ -202,6 +219,7 @@ public class PluginManager
|
||||
{
|
||||
List<Plugin> scannedPlugins = new ArrayList<>(plugins);
|
||||
int loaded = 0;
|
||||
|
||||
for (Plugin plugin : scannedPlugins)
|
||||
{
|
||||
try
|
||||
@@ -215,18 +233,19 @@ public class PluginManager
|
||||
}
|
||||
|
||||
loaded++;
|
||||
SplashScreen.stage(.80, 1, null, "Starting plugins", loaded, scannedPlugins.size(), false);
|
||||
|
||||
RuneLiteSplashScreen.stage(.80, 1, "Starting plugins", loaded, scannedPlugins.size());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Plugin> scanAndInstantiate(ClassLoader classLoader, String packageName) throws IOException
|
||||
{
|
||||
SplashScreen.stage(.59, null, "Loading Plugins");
|
||||
RuneLiteSplashScreen.stage(.59, "Loading plugins");
|
||||
MutableGraph<Class<? extends Plugin>> graph = GraphBuilder
|
||||
.directed()
|
||||
.build();
|
||||
|
||||
List<Plugin> scannedPlugins = new ArrayList<>();
|
||||
ClassPath classPath = ClassPath.from(classLoader);
|
||||
|
||||
ImmutableSet<ClassInfo> classes = packageName == null ? classPath.getAllClasses()
|
||||
@@ -241,7 +260,7 @@ public class PluginManager
|
||||
if (clazz.getSuperclass() == Plugin.class)
|
||||
{
|
||||
log.warn("Class {} is a plugin, but has no plugin descriptor",
|
||||
clazz);
|
||||
clazz);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -249,7 +268,7 @@ public class PluginManager
|
||||
if (clazz.getSuperclass() != Plugin.class)
|
||||
{
|
||||
log.warn("Class {} has plugin descriptor, but is not a plugin",
|
||||
clazz);
|
||||
clazz);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -263,7 +282,7 @@ public class PluginManager
|
||||
continue;
|
||||
}
|
||||
|
||||
Class<Plugin> pluginClass = (Class<Plugin>) clazz;
|
||||
@SuppressWarnings("unchecked") Class<Plugin> pluginClass = (Class<Plugin>) clazz;
|
||||
graph.addNode(pluginClass);
|
||||
}
|
||||
|
||||
@@ -283,26 +302,52 @@ public class PluginManager
|
||||
throw new RuntimeException("Plugin dependency graph contains a cycle!");
|
||||
}
|
||||
|
||||
List<Class<? extends Plugin>> sortedPlugins = topologicalSort(graph);
|
||||
List<List<Class<? extends Plugin>>> sortedPlugins = topologicalGroupSort(graph);
|
||||
sortedPlugins = Lists.reverse(sortedPlugins);
|
||||
AtomicInteger loaded = new AtomicInteger();
|
||||
|
||||
int loaded = 0;
|
||||
for (Class<? extends Plugin> pluginClazz : sortedPlugins)
|
||||
final long start = System.currentTimeMillis();
|
||||
|
||||
// some plugins get stuck on IO, so add some extra threads
|
||||
ExecutorService exec = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2);
|
||||
|
||||
List<Plugin> scannedPlugins = new CopyOnWriteArrayList<>();
|
||||
sortedPlugins.forEach(group ->
|
||||
{
|
||||
Plugin plugin;
|
||||
try
|
||||
{
|
||||
plugin = instantiate(scannedPlugins, (Class<Plugin>) pluginClazz);
|
||||
scannedPlugins.add(plugin);
|
||||
}
|
||||
catch (PluginInstantiationException ex)
|
||||
{
|
||||
log.warn("Error instantiating plugin!", ex);
|
||||
}
|
||||
List<Future<?>> curGroup = new ArrayList<>();
|
||||
group.forEach(pluginClazz ->
|
||||
curGroup.add(exec.submit(() ->
|
||||
{
|
||||
Plugin plugin;
|
||||
try
|
||||
{
|
||||
plugin = instantiate(scannedPlugins, (Class<Plugin>) pluginClazz);
|
||||
scannedPlugins.add(plugin);
|
||||
}
|
||||
catch (PluginInstantiationException e)
|
||||
{
|
||||
log.warn("Error instantiating plugin!", e);
|
||||
return;
|
||||
}
|
||||
|
||||
loaded++;
|
||||
SplashScreen.stage(.60, .70, null, "Loading Plugins", loaded, sortedPlugins.size(), false);
|
||||
}
|
||||
loaded.getAndIncrement();
|
||||
|
||||
RuneLiteSplashScreen.stage(.60, .70, "Loading plugins", loaded.get(), scannedPlugins.size());
|
||||
})));
|
||||
curGroup.forEach(future ->
|
||||
{
|
||||
try
|
||||
{
|
||||
future.get();
|
||||
}
|
||||
catch (InterruptedException | ExecutionException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
log.info("Plugin instantiation took {}ms", System.currentTimeMillis() - start);
|
||||
|
||||
return scannedPlugins;
|
||||
}
|
||||
@@ -341,9 +386,9 @@ public class PluginManager
|
||||
}
|
||||
}
|
||||
|
||||
eventBus.register(plugin);
|
||||
// eventBus.register(plugin);
|
||||
schedule(plugin);
|
||||
eventBus.post(new PluginChanged(plugin, true));
|
||||
eventBus.post(PluginChanged.class, new PluginChanged(plugin, true));
|
||||
}
|
||||
catch (InterruptedException | InvocationTargetException | IllegalArgumentException ex)
|
||||
{
|
||||
@@ -365,7 +410,6 @@ public class PluginManager
|
||||
try
|
||||
{
|
||||
unschedule(plugin);
|
||||
eventBus.unregister(plugin);
|
||||
|
||||
// plugins always stop in the event thread
|
||||
SwingUtilities.invokeAndWait(() ->
|
||||
@@ -381,7 +425,7 @@ public class PluginManager
|
||||
});
|
||||
|
||||
log.debug("Plugin {} is now stopped", plugin.getClass().getSimpleName());
|
||||
eventBus.post(new PluginChanged(plugin, false));
|
||||
eventBus.post(PluginChanged.class, new PluginChanged(plugin, false));
|
||||
|
||||
}
|
||||
catch (InterruptedException | InvocationTargetException ex)
|
||||
@@ -405,13 +449,14 @@ public class PluginManager
|
||||
|
||||
if (value != null)
|
||||
{
|
||||
return Boolean.valueOf(value);
|
||||
return Boolean.parseBoolean(value);
|
||||
}
|
||||
|
||||
final PluginDescriptor pluginDescriptor = plugin.getClass().getAnnotation(PluginDescriptor.class);
|
||||
return pluginDescriptor == null || pluginDescriptor.enabledByDefault();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Plugin instantiate(List<Plugin> scannedPlugins, Class<Plugin> clazz) throws PluginInstantiationException
|
||||
{
|
||||
PluginDependency[] pluginDependencies = clazz.getAnnotationsByType(PluginDependency.class);
|
||||
@@ -515,39 +560,54 @@ public class PluginManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Topologically sort a graph. Uses Kahn's algorithm.
|
||||
* Topologically sort a graph into separate groups.
|
||||
* Each group represents the dependency level of the plugins.
|
||||
* Plugins in group (index) 0 has no dependents.
|
||||
* Plugins in group 1 has dependents in group 0.
|
||||
* Plugins in group 2 has dependents in group 1, etc.
|
||||
* This allows for loading dependent groups serially, starting from the last group,
|
||||
* while loading plugins within each group in parallel.
|
||||
* @param graph
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
private <T> List<T> topologicalSort(Graph<T> graph)
|
||||
private <T> List<List<T>> topologicalGroupSort(Graph<T> graph)
|
||||
{
|
||||
MutableGraph<T> graphCopy = Graphs.copyOf(graph);
|
||||
List<T> l = new ArrayList<>();
|
||||
Set<T> s = graphCopy.nodes().stream()
|
||||
.filter(node -> graphCopy.inDegree(node) == 0)
|
||||
final Set<T> root = graph.nodes().stream()
|
||||
.filter(node -> graph.inDegree(node) == 0)
|
||||
.collect(Collectors.toSet());
|
||||
while (!s.isEmpty())
|
||||
{
|
||||
Iterator<T> it = s.iterator();
|
||||
T n = it.next();
|
||||
it.remove();
|
||||
final Map<T, Integer> dependencyCount = new HashMap<>();
|
||||
|
||||
l.add(n);
|
||||
root.forEach(n -> dependencyCount.put(n, 0));
|
||||
root.forEach(n -> graph.successors(n)
|
||||
.forEach(m -> incrementChildren(graph, dependencyCount, m, dependencyCount.get(n) + 1)));
|
||||
|
||||
for (T m : graphCopy.successors(n))
|
||||
// create list<list> dependency grouping
|
||||
final List<List<T>> dependencyGroups = new ArrayList<>();
|
||||
final int[] curGroup = {-1};
|
||||
|
||||
dependencyCount.entrySet().stream()
|
||||
.sorted(Map.Entry.comparingByValue())
|
||||
.forEach(entry ->
|
||||
{
|
||||
graphCopy.removeEdge(n, m);
|
||||
if (graphCopy.inDegree(m) == 0)
|
||||
if (entry.getValue() != curGroup[0])
|
||||
{
|
||||
s.add(m);
|
||||
curGroup[0] = entry.getValue();
|
||||
dependencyGroups.add(new ArrayList<>());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!graphCopy.edges().isEmpty())
|
||||
dependencyGroups.get(dependencyGroups.size() - 1).add(entry.getKey());
|
||||
});
|
||||
|
||||
return dependencyGroups;
|
||||
}
|
||||
|
||||
private <T> void incrementChildren(Graph<T> graph, Map<T, Integer> dependencyCount, T n, int val)
|
||||
{
|
||||
if (!dependencyCount.containsKey(n) || dependencyCount.get(n) < val)
|
||||
{
|
||||
throw new RuntimeException("Graph has at least one cycle");
|
||||
dependencyCount.put(n, val);
|
||||
graph.successors(n).forEach(m ->
|
||||
incrementChildren(graph, dependencyCount, m, val + 1));
|
||||
}
|
||||
return l;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package net.runelite.client.plugins;
|
||||
|
||||
public enum PluginType
|
||||
{
|
||||
PVM,
|
||||
PVP,
|
||||
SKILLING,
|
||||
UTILITY,
|
||||
GENERAL_USE,
|
||||
EXTERNAL,
|
||||
PLUGIN_ORGANIZER
|
||||
}
|
||||
@@ -0,0 +1,273 @@
|
||||
/*
|
||||
* 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.plugins;
|
||||
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Key;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Path;
|
||||
import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
|
||||
import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
|
||||
import java.nio.file.WatchEvent;
|
||||
import java.nio.file.WatchEvent.Kind;
|
||||
import java.nio.file.WatchKey;
|
||||
import java.nio.file.WatchService;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.client.RuneLite;
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.config.RuneLitePlusConfig;
|
||||
|
||||
@Singleton
|
||||
@Slf4j
|
||||
public class PluginWatcher extends Thread
|
||||
{
|
||||
private static final File BASE = RuneLite.PLUGIN_DIR;
|
||||
|
||||
private final RuneLitePlusConfig runelitePlusConfig;
|
||||
private final PluginManager pluginManager;
|
||||
private final WatchService watchService;
|
||||
private final WatchKey watchKey;
|
||||
|
||||
@Inject
|
||||
private ConfigManager configManager;
|
||||
|
||||
@Inject
|
||||
public PluginWatcher(RuneLitePlusConfig runelitePlusConfig, PluginManager pluginManager) throws IOException
|
||||
{
|
||||
this.runelitePlusConfig = runelitePlusConfig;
|
||||
this.pluginManager = pluginManager;
|
||||
|
||||
setName("Plugin Watcher");
|
||||
setDaemon(true);
|
||||
|
||||
watchService = FileSystems.getDefault().newWatchService();
|
||||
BASE.mkdirs();
|
||||
Path dir = BASE.toPath();
|
||||
watchKey = dir.register(watchService, ENTRY_MODIFY, ENTRY_DELETE);
|
||||
}
|
||||
|
||||
public void cancel()
|
||||
{
|
||||
watchKey.cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if (runelitePlusConfig.enablePlugins())
|
||||
{
|
||||
scan();
|
||||
}
|
||||
|
||||
for (; ; )
|
||||
{
|
||||
try
|
||||
{
|
||||
WatchKey key = watchService.take();
|
||||
Thread.sleep(50);
|
||||
|
||||
if (!runelitePlusConfig.enablePlugins())
|
||||
{
|
||||
key.reset();
|
||||
continue;
|
||||
}
|
||||
|
||||
for (WatchEvent<?> event : key.pollEvents())
|
||||
{
|
||||
Kind<?> kind = event.kind();
|
||||
Path path = (Path) event.context();
|
||||
File file = new File(BASE, path.toFile().getName());
|
||||
|
||||
log.debug("Event {} file {}", kind, file);
|
||||
|
||||
if (kind == ENTRY_MODIFY)
|
||||
{
|
||||
Plugin existing = findPluginForFile(file);
|
||||
if (existing != null)
|
||||
{
|
||||
log.info("Reloading plugin {}", file);
|
||||
unload(existing);
|
||||
}
|
||||
else
|
||||
{
|
||||
log.info("Loading plugin {}", file);
|
||||
}
|
||||
|
||||
load(file);
|
||||
}
|
||||
else if (kind == ENTRY_DELETE)
|
||||
{
|
||||
Plugin existing = findPluginForFile(file);
|
||||
if (existing != null)
|
||||
{
|
||||
log.info("Unloading plugin {}", file);
|
||||
|
||||
unload(existing);
|
||||
}
|
||||
}
|
||||
}
|
||||
key.reset();
|
||||
|
||||
}
|
||||
catch (InterruptedException ex)
|
||||
{
|
||||
log.warn("error polling for plugins", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void scan()
|
||||
{
|
||||
for (File file : BASE.listFiles())
|
||||
{
|
||||
if (!file.getName().endsWith(".jar"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
log.info("Loading plugin from {}", file);
|
||||
load(file);
|
||||
}
|
||||
}
|
||||
|
||||
private Plugin findPluginForFile(File file)
|
||||
{
|
||||
for (Plugin plugin : pluginManager.getPlugins())
|
||||
{
|
||||
if (plugin.file != null && plugin.file.equals(file))
|
||||
{
|
||||
return plugin;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void load(File pluginFile)
|
||||
{
|
||||
PluginClassLoader loader;
|
||||
try
|
||||
{
|
||||
loader = new PluginClassLoader(pluginFile, getClass().getClassLoader());
|
||||
}
|
||||
catch (MalformedURLException ex)
|
||||
{
|
||||
log.warn("Error loading plugin", ex);
|
||||
return;
|
||||
}
|
||||
|
||||
List<Plugin> loadedPlugins;
|
||||
try
|
||||
{
|
||||
loadedPlugins = pluginManager.scanAndInstantiate(loader, null);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
close(loader);
|
||||
log.warn("Error loading plugin", ex);
|
||||
return;
|
||||
}
|
||||
|
||||
if (loadedPlugins.isEmpty())
|
||||
{
|
||||
close(loader);
|
||||
log.warn("No plugin found in plugin {}", pluginFile);
|
||||
return;
|
||||
}
|
||||
|
||||
if (loadedPlugins.size() != 1)
|
||||
{
|
||||
close(loader);
|
||||
log.warn("You can not have more than one plugin per jar");
|
||||
return;
|
||||
}
|
||||
|
||||
Plugin plugin = loadedPlugins.get(0);
|
||||
plugin.file = pluginFile;
|
||||
plugin.loader = loader;
|
||||
|
||||
// Initialize default configuration
|
||||
Injector injector = plugin.getInjector();
|
||||
for (Key<?> key : injector.getAllBindings().keySet())
|
||||
{
|
||||
Class<?> type = key.getTypeLiteral().getRawType();
|
||||
if (Config.class.isAssignableFrom(type))
|
||||
{
|
||||
Config config = (Config) injector.getInstance(key);
|
||||
configManager.setDefaultConfiguration(config, false);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
pluginManager.startPlugin(plugin);
|
||||
}
|
||||
catch (PluginInstantiationException ex)
|
||||
{
|
||||
close(loader);
|
||||
log.warn("unable to start plugin", ex);
|
||||
return;
|
||||
}
|
||||
|
||||
// Plugin is now running
|
||||
pluginManager.add(plugin);
|
||||
}
|
||||
|
||||
private void unload(Plugin plugin)
|
||||
{
|
||||
try
|
||||
{
|
||||
pluginManager.stopPlugin(plugin);
|
||||
}
|
||||
catch (PluginInstantiationException ex)
|
||||
{
|
||||
log.warn("unable to stop plugin", ex);
|
||||
}
|
||||
|
||||
pluginManager.remove(plugin); // remove it regardless
|
||||
|
||||
close(plugin.loader);
|
||||
}
|
||||
|
||||
private void close(URLClassLoader classLoader)
|
||||
{
|
||||
try
|
||||
{
|
||||
classLoader.close();
|
||||
}
|
||||
catch (IOException ex1)
|
||||
{
|
||||
log.warn(null, ex1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,21 +24,17 @@
|
||||
*/
|
||||
package net.runelite.client.plugins.account;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import javax.inject.Inject;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.inject.Singleton;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.client.account.AccountSession;
|
||||
import net.runelite.client.account.SessionManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.events.SessionClose;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.SessionOpen;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.ui.ClientToolbar;
|
||||
import net.runelite.client.ui.NavigationButton;
|
||||
import net.runelite.client.util.ImageUtil;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Account",
|
||||
@@ -47,6 +43,7 @@ import net.runelite.client.util.ImageUtil;
|
||||
loadWhenOutdated = true
|
||||
)
|
||||
@Slf4j
|
||||
@Singleton
|
||||
public class AccountPlugin extends Plugin
|
||||
{
|
||||
@Inject
|
||||
@@ -58,76 +55,28 @@ public class AccountPlugin extends Plugin
|
||||
@Inject
|
||||
private ScheduledExecutorService executor;
|
||||
|
||||
private NavigationButton loginButton;
|
||||
private NavigationButton logoutButton;
|
||||
@Inject
|
||||
private EventBus eventBus;
|
||||
|
||||
private static final BufferedImage LOGIN_IMAGE, LOGOUT_IMAGE;
|
||||
|
||||
static
|
||||
{
|
||||
LOGIN_IMAGE = ImageUtil.getResourceStreamFromClass(AccountPlugin.class, "login_icon.png");
|
||||
LOGOUT_IMAGE = ImageUtil.getResourceStreamFromClass(AccountPlugin.class, "logout_icon.png");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
loginButton = NavigationButton.builder()
|
||||
.tab(false)
|
||||
.icon(LOGIN_IMAGE)
|
||||
.tooltip("Login to RuneLite")
|
||||
.onClick(this::loginClick)
|
||||
.build();
|
||||
|
||||
logoutButton = NavigationButton.builder()
|
||||
.tab(false)
|
||||
.icon(LOGOUT_IMAGE)
|
||||
.tooltip("Logout of RuneLite")
|
||||
.onClick(this::logoutClick)
|
||||
.build();
|
||||
|
||||
addAndRemoveButtons();
|
||||
}
|
||||
|
||||
private void addAndRemoveButtons()
|
||||
{
|
||||
clientToolbar.removeNavigation(loginButton);
|
||||
clientToolbar.removeNavigation(logoutButton);
|
||||
clientToolbar.addNavigation(sessionManager.getAccountSession() == null
|
||||
? loginButton
|
||||
: logoutButton);
|
||||
addSubscriptions();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
clientToolbar.removeNavigation(loginButton);
|
||||
clientToolbar.removeNavigation(logoutButton);
|
||||
eventBus.unregister(this);
|
||||
}
|
||||
|
||||
private void loginClick()
|
||||
private void addSubscriptions()
|
||||
{
|
||||
executor.execute(sessionManager::login);
|
||||
eventBus.subscribe(SessionOpen.class, this, this::onSessionOpen);
|
||||
}
|
||||
|
||||
private void logoutClick()
|
||||
{
|
||||
if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(null,
|
||||
"Are you sure you want to logout from RuneLite?", "Logout Confirmation",
|
||||
JOptionPane.YES_NO_OPTION))
|
||||
{
|
||||
executor.execute(sessionManager::logout);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onSessionClose(SessionClose e)
|
||||
{
|
||||
addAndRemoveButtons();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onSessionOpen(SessionOpen sessionOpen)
|
||||
private void onSessionOpen(SessionOpen sessionOpen)
|
||||
{
|
||||
AccountSession session = sessionManager.getAccountSession();
|
||||
|
||||
@@ -137,8 +86,6 @@ public class AccountPlugin extends Plugin
|
||||
}
|
||||
|
||||
log.debug("Session opened as {}", session.getUsername());
|
||||
|
||||
addAndRemoveButtons();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.FontTypeFace;
|
||||
@@ -43,7 +44,7 @@ import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetID;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.achievementdiary.diaries.ArdougneDiaryRequirement;
|
||||
@@ -66,6 +67,7 @@ import net.runelite.client.util.Text;
|
||||
description = "Display level requirements in Achievement Diary interface",
|
||||
tags = {"achievements", "tasks"}
|
||||
)
|
||||
@Singleton
|
||||
public class DiaryRequirementsPlugin extends Plugin
|
||||
{
|
||||
private static final String AND_JOINER = ", ";
|
||||
@@ -77,8 +79,22 @@ public class DiaryRequirementsPlugin extends Plugin
|
||||
@Inject
|
||||
private ClientThread clientThread;
|
||||
|
||||
@Subscribe
|
||||
public void onWidgetLoaded(final WidgetLoaded event)
|
||||
@Inject
|
||||
private EventBus eventBus;
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
eventBus.subscribe(WidgetLoaded.class, this, this::onWidgetLoaded);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
eventBus.unregister(this);
|
||||
}
|
||||
|
||||
private void onWidgetLoaded(final WidgetLoaded event)
|
||||
{
|
||||
if (event.getGroupId() == WidgetID.DIARY_QUEST_GROUP_ID)
|
||||
{
|
||||
@@ -122,10 +138,6 @@ public class DiaryRequirementsPlugin extends Plugin
|
||||
}
|
||||
|
||||
Map<String, String> skillRequirements = buildRequirements(requirements.getRequirements());
|
||||
if (skillRequirements == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int offset = 0;
|
||||
String taskBuffer = "";
|
||||
|
||||
@@ -87,7 +87,7 @@ public class ArdougneDiaryRequirement extends GenericDiaryRequirement
|
||||
new QuestRequirement(Quest.LEGENDS_QUEST));
|
||||
add("Enter the Magic Guild.",
|
||||
new SkillRequirement(Skill.MAGIC, 66));
|
||||
add("Attempt to steal from a chest in Ardougne Castle.",
|
||||
add("Attempt to steal from King Lathas' chest.",
|
||||
new SkillRequirement(Skill.THIEVING, 72));
|
||||
add("Have a zookeeper put you in Ardougne Zoo's monkey cage.",
|
||||
new QuestRequirement(Quest.MONKEY_MADNESS_I, true));
|
||||
|
||||
@@ -27,10 +27,10 @@ package net.runelite.client.plugins.achievementdiary.diaries;
|
||||
import net.runelite.api.Favour;
|
||||
import net.runelite.api.Quest;
|
||||
import net.runelite.api.Skill;
|
||||
import net.runelite.client.plugins.achievementdiary.GenericDiaryRequirement;
|
||||
import net.runelite.client.plugins.achievementdiary.SkillRequirement;
|
||||
import net.runelite.client.plugins.achievementdiary.QuestRequirement;
|
||||
import net.runelite.client.plugins.achievementdiary.FavourRequirement;
|
||||
import net.runelite.client.plugins.achievementdiary.GenericDiaryRequirement;
|
||||
import net.runelite.client.plugins.achievementdiary.QuestRequirement;
|
||||
import net.runelite.client.plugins.achievementdiary.SkillRequirement;
|
||||
|
||||
public class KourendDiaryRequirement extends GenericDiaryRequirement
|
||||
{
|
||||
|
||||
@@ -28,15 +28,42 @@ import java.awt.Color;
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
import net.runelite.client.config.Stub;
|
||||
|
||||
@ConfigGroup("agility")
|
||||
public interface AgilityConfig extends Config
|
||||
{
|
||||
@ConfigItem(
|
||||
position = 0,
|
||||
keyName = "mainConfig",
|
||||
name = "Main Config",
|
||||
description = ""
|
||||
)
|
||||
default Stub mainConfig()
|
||||
{
|
||||
return new Stub();
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "removeDistanceCap",
|
||||
name = "Remove Distance Cap",
|
||||
description = "This will remove the distance cap on rendering overlays for agility.",
|
||||
warning = "<html><center>Enabling this setting on a low end machine may severely affect your fps." +
|
||||
"<br>Click yes to enable this setting, knowing it might affect performance.</center></html>",
|
||||
position = 1,
|
||||
parent = "mainConfig"
|
||||
)
|
||||
default boolean removeDistanceCap()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showLapCount",
|
||||
name = "Show Lap Count",
|
||||
description = "Enable/disable the lap counter",
|
||||
position = 1
|
||||
position = 2,
|
||||
parent = "mainConfig"
|
||||
)
|
||||
default boolean showLapCount()
|
||||
{
|
||||
@@ -45,9 +72,12 @@ public interface AgilityConfig extends Config
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "lapTimeout",
|
||||
name = "Hide Lap Count (minutes)",
|
||||
description = "Time until the lap counter hides/resets",
|
||||
position = 2
|
||||
name = "Hide Lap Count",
|
||||
description = "Time in minutes until the lap counter hides/resets",
|
||||
position = 3,
|
||||
parent = "mainConfig",
|
||||
hidden = true,
|
||||
unhide = "showLapCount"
|
||||
)
|
||||
default int lapTimeout()
|
||||
{
|
||||
@@ -55,43 +85,86 @@ public interface AgilityConfig extends Config
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "overlayColor",
|
||||
name = "Overlay Color",
|
||||
description = "Color of Agility overlay",
|
||||
position = 3
|
||||
keyName = "lapsToLevel",
|
||||
name = "Show Laps Until Level",
|
||||
description = "Show number of laps remaining until next level is reached.",
|
||||
position = 4,
|
||||
parent = "mainConfig",
|
||||
hidden = true,
|
||||
unhide = "showLapCount"
|
||||
)
|
||||
default Color getOverlayColor()
|
||||
default boolean lapsToLevel()
|
||||
{
|
||||
return Color.GREEN;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "lapsToGoal",
|
||||
name = "Show Laps Until Goal",
|
||||
description = "Show number of laps remaining until experience tracker goal is reached",
|
||||
position = 5,
|
||||
parent = "mainConfig",
|
||||
hidden = true,
|
||||
unhide = "showLapCount"
|
||||
)
|
||||
default boolean lapsToGoal()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "agilityArenaTimer",
|
||||
name = "Agility Arena timer",
|
||||
description = "Configures whether Agility Arena timer is displayed",
|
||||
position = 6,
|
||||
parent = "mainConfig"
|
||||
)
|
||||
default boolean showAgilityArenaTimer()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "addLevelsToShortcutOptions",
|
||||
name = "Show Shortcut Agility Reqs",
|
||||
description = "Enable/disable showing shortcut agility level requirements in right-click options",
|
||||
position = 7,
|
||||
parent = "mainConfig"
|
||||
)
|
||||
default boolean showShortcutLevel()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 8,
|
||||
keyName = "miscConfig",
|
||||
name = "Misc Config",
|
||||
description = ""
|
||||
)
|
||||
default Stub miscConfig()
|
||||
{
|
||||
return new Stub();
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "highlightMarks",
|
||||
name = "Highlight Marks of Grace",
|
||||
description = "Enable/disable the highlighting of retrievable Marks of Grace",
|
||||
position = 4
|
||||
position = 9,
|
||||
parent = "miscConfig"
|
||||
)
|
||||
default boolean highlightMarks()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "markHighlight",
|
||||
name = "Mark Highlight Color",
|
||||
description = "Color of highlighted Marks of Grace",
|
||||
position = 5
|
||||
)
|
||||
default Color getMarkColor()
|
||||
{
|
||||
return Color.RED;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "highlightShortcuts",
|
||||
name = "Highlight Agility Shortcuts",
|
||||
description = "Enable/disable the highlighting of Agility shortcuts",
|
||||
position = 6
|
||||
position = 10,
|
||||
parent = "miscConfig"
|
||||
)
|
||||
default boolean highlightShortcuts()
|
||||
{
|
||||
@@ -99,21 +172,49 @@ public interface AgilityConfig extends Config
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "trapOverlay",
|
||||
name = "Show Trap Overlay",
|
||||
keyName = "showTrapOverlay",
|
||||
name = "Highlight Traps",
|
||||
description = "Enable/disable the highlighting of traps on Agility courses",
|
||||
position = 7
|
||||
position = 11,
|
||||
parent = "miscConfig"
|
||||
)
|
||||
default boolean showTrapOverlay()
|
||||
{
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "agilityArenaNotifier",
|
||||
name = "Agility Arena notifier",
|
||||
description = "Notify on ticket location change in Agility Arena",
|
||||
position = 12,
|
||||
parent = "miscConfig"
|
||||
)
|
||||
default boolean notifyAgilityArena()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "overlayColor",
|
||||
name = "Global Overlay Color",
|
||||
description = "Color of Agility overlay",
|
||||
position = 13,
|
||||
parent = "miscConfig"
|
||||
)
|
||||
default Color getOverlayColor()
|
||||
{
|
||||
return Color.GREEN;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "trapHighlight",
|
||||
name = "Trap Overlay Color",
|
||||
description = "Color of Agility trap overlay",
|
||||
position = 8
|
||||
position = 14,
|
||||
parent = "miscConfig",
|
||||
hidden = true,
|
||||
unhide = "showTrapOverlay"
|
||||
)
|
||||
default Color getTrapColor()
|
||||
{
|
||||
@@ -121,24 +222,16 @@ public interface AgilityConfig extends Config
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "agilityArenaNotifier",
|
||||
name = "Agility Arena notifier",
|
||||
description = "Notify on ticket location change in Agility Arena",
|
||||
position = 9
|
||||
keyName = "markHighlight",
|
||||
name = "Mark Highlight Color",
|
||||
description = "Color of highlighted Marks of Grace",
|
||||
position = 15,
|
||||
parent = "miscConfig",
|
||||
hidden = true,
|
||||
unhide = "highlightMarks"
|
||||
)
|
||||
default boolean notifyAgilityArena()
|
||||
default Color getMarkColor()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "agilityArenaTimer",
|
||||
name = "Agility Arena timer",
|
||||
description = "Configures whether Agility Arena timer is displayed",
|
||||
position = 10
|
||||
)
|
||||
default boolean showAgilityArenaTimer()
|
||||
{
|
||||
return true;
|
||||
return Color.RED;
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user