openrune: reset to upstream client bare

This commit is contained in:
therealunull
2020-12-13 12:42:33 -05:00
parent 9a257666be
commit 98d2a16798
265 changed files with 7149 additions and 23792 deletions

View File

@@ -24,88 +24,114 @@
*/ */
package net.runelite.client; package net.runelite.client;
import io.reactivex.rxjava3.schedulers.Schedulers; import java.io.IOException;
import java.time.temporal.ChronoUnit;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.runelite.client.eventbus.EventBus; import net.runelite.api.Client;
import net.runelite.api.GameState;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.events.ClientShutdown; import net.runelite.client.events.ClientShutdown;
import net.runelite.client.task.Schedule; import net.runelite.client.util.RunnableExceptionLogger;
import okhttp3.OkHttpClient; import okhttp3.OkHttpClient;
@Singleton @Singleton
@Slf4j @Slf4j
public class ClientSessionManager public class ClientSessionManager
{ {
private final ScheduledExecutorService executorService;
private final Client client;
private final SessionClient sessionClient; private final SessionClient sessionClient;
private ScheduledFuture<?> scheduledFuture;
private UUID sessionId; private UUID sessionId;
@Inject @Inject
ClientSessionManager(EventBus eventBus, ClientSessionManager(ScheduledExecutorService executorService,
@Nullable Client client,
OkHttpClient okHttpClient) OkHttpClient okHttpClient)
{ {
this.executorService = executorService;
this.client = client;
this.sessionClient = new SessionClient(okHttpClient); this.sessionClient = new SessionClient(okHttpClient);
}
eventBus.subscribe(ClientShutdown.class, this, (e) -> public void start()
{
try
{ {
Future<Void> f = shutdown(); sessionId = sessionClient.open();
if (f != null) log.debug("Opened session {}", sessionId);
}
catch (IOException ex)
{
log.warn("error opening session", ex);
}
scheduledFuture = executorService.scheduleWithFixedDelay(RunnableExceptionLogger.wrap(this::ping), 1, 10, TimeUnit.MINUTES);
}
@Subscribe
private void onClientShutdown(ClientShutdown e)
{
scheduledFuture.cancel(true);
e.waitFor(executorService.submit(() ->
{
try
{ {
e.waitFor(f); UUID localUuid = sessionId;
if (localUuid != null)
{
sessionClient.delete(localUuid);
}
}
catch (IOException ex)
{
log.warn(null, ex);
} }
sessionId = null; sessionId = null;
}); }));
} }
void start() private void ping()
{ {
sessionClient.openSession() try
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.single())
.doOnError(this::error)
.subscribe(this::setUuid);
}
@Schedule(period = 10, unit = ChronoUnit.MINUTES, asynchronous = true)
public void ping()
{
if (sessionId == null)
{ {
start(); if (sessionId == null)
{
sessionId = sessionClient.open();
log.debug("Opened session {}", sessionId);
return;
}
}
catch (IOException ex)
{
log.warn("unable to open session", ex);
return; return;
} }
sessionClient.pingSession(sessionId) boolean loggedIn = false;
.subscribeOn(Schedulers.io()) if (client != null)
.observeOn(Schedulers.single())
.doOnError(this::error)
.subscribe();
}
private Future<Void> shutdown()
{
if (sessionId != null)
{ {
return sessionClient.delete(sessionId) GameState gameState = client.getGameState();
.toFuture(); loggedIn = gameState.getState() >= GameState.LOADING.getState();
} }
return null;
}
private void setUuid(UUID uuid) try
{ {
this.sessionId = uuid; sessionClient.ping(sessionId, loggedIn);
log.debug("Opened session {}.", sessionId); }
} catch (IOException ex)
{
log.warn("Resetting session", ex);
sessionId = null;
}
private void error(Throwable error)
{
log.debug("Error in client session.");
log.trace(null, error);
} }
} }

View File

@@ -24,6 +24,7 @@
*/ */
package net.runelite.client; package net.runelite.client;
import com.google.common.base.Strings;
import com.google.common.escape.Escaper; import com.google.common.escape.Escaper;
import com.google.common.escape.Escapers; import com.google.common.escape.Escapers;
import com.google.inject.Inject; import com.google.inject.Inject;
@@ -113,7 +114,7 @@ public class Notifier
private final ChatMessageManager chatMessageManager; private final ChatMessageManager chatMessageManager;
private final EventBus eventBus; private final EventBus eventBus;
private final Path notifyIconPath; private final Path notifyIconPath;
private final boolean terminalNotifierAvailable; private boolean terminalNotifierAvailable;
private Instant flashStart; private Instant flashStart;
private long mouseLastPressedMillis; private long mouseLastPressedMillis;
private long lastClipMTime = CLIP_MTIME_UNLOADED; private long lastClipMTime = CLIP_MTIME_UNLOADED;
@@ -137,7 +138,10 @@ public class Notifier
this.notifyIconPath = RuneLite.RUNELITE_DIR.toPath().resolve("icon.png"); this.notifyIconPath = RuneLite.RUNELITE_DIR.toPath().resolve("icon.png");
// First check if we are running in launcher // First check if we are running in launcher
this.terminalNotifierAvailable = true; if (!Strings.isNullOrEmpty(RuneLiteProperties.getLauncherVersion()) && OSType.getOSType() == OSType.MacOS)
{
executorService.execute(() -> terminalNotifierAvailable = isTerminalNotifierAvailable());
}
storeIcon(); storeIcon();
} }
@@ -149,7 +153,7 @@ public class Notifier
public void notify(String message, TrayIcon.MessageType type) public void notify(String message, TrayIcon.MessageType type)
{ {
eventBus.post(NotificationFired.class, new NotificationFired(message, type)); eventBus.post(new NotificationFired(message, type));
if (!runeLiteConfig.sendNotificationsWhenFocused() && clientUI.isFocused()) if (!runeLiteConfig.sendNotificationsWhenFocused() && clientUI.isFocused())
{ {
@@ -364,7 +368,7 @@ public class Notifier
private static Process sendCommand(final List<String> commands) throws IOException private static Process sendCommand(final List<String> commands) throws IOException
{ {
return new ProcessBuilder(commands.toArray(new String[0])) return new ProcessBuilder(commands.toArray(new String[commands.size()]))
.redirectErrorStream(true) .redirectErrorStream(true)
.start(); .start();
} }
@@ -373,7 +377,7 @@ public class Notifier
{ {
if (OSType.getOSType() == OSType.Linux && !Files.exists(notifyIconPath)) if (OSType.getOSType() == OSType.Linux && !Files.exists(notifyIconPath))
{ {
try (InputStream stream = Notifier.class.getResourceAsStream("/openosrs.png")) try (InputStream stream = Notifier.class.getResourceAsStream("/runelite.png"))
{ {
Files.copy(stream, notifyIconPath); Files.copy(stream, notifyIconPath);
} }
@@ -386,21 +390,19 @@ public class Notifier
private boolean isTerminalNotifierAvailable() private boolean isTerminalNotifierAvailable()
{ {
if (OSType.getOSType() == OSType.MacOS) try
{ {
try final Process exec = Runtime.getRuntime().exec(new String[]{"terminal-notifier", "-help"});
{ if (!exec.waitFor(2, TimeUnit.SECONDS))
final Process exec = Runtime.getRuntime().exec(new String[]{"terminal-notifier", "-help"});
exec.waitFor();
return exec.exitValue() == 0;
}
catch (IOException | InterruptedException e)
{ {
return false; return false;
} }
return exec.exitValue() == 0;
}
catch (IOException | InterruptedException e)
{
return false;
} }
return false;
} }
private static String toUrgency(TrayIcon.MessageType type) private static String toUrgency(TrayIcon.MessageType type)

View File

@@ -26,41 +26,27 @@ package net.runelite.client;
import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger; import ch.qos.logback.classic.Logger;
import com.github.zafarkhaja.semver.Version;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.inject.Guice; import com.google.inject.Guice;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Injector; import com.google.inject.Injector;
import io.reactivex.rxjava3.core.Completable;
import io.reactivex.rxjava3.schedulers.Schedulers;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.management.ManagementFactory; import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean; import java.lang.management.RuntimeMXBean;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.security.KeyManagementException; import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.util.Locale; import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.UUID;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.inject.Provider; import javax.inject.Provider;
import javax.inject.Singleton; import javax.inject.Singleton;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager; import javax.net.ssl.X509TrustManager;
import javax.swing.SwingUtilities;
import joptsimple.ArgumentAcceptingOptionSpec; import joptsimple.ArgumentAcceptingOptionSpec;
import joptsimple.OptionException;
import joptsimple.OptionParser; import joptsimple.OptionParser;
import joptsimple.OptionSet; import joptsimple.OptionSet;
import joptsimple.ValueConversionException; import joptsimple.ValueConversionException;
@@ -69,49 +55,34 @@ import joptsimple.util.EnumConverter;
import lombok.Getter; import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.api.events.GameStateChanged;
import net.runelite.api.events.ScriptCallbackEvent;
import net.runelite.client.account.SessionManager; import net.runelite.client.account.SessionManager;
import net.runelite.client.callback.Hooks; import net.runelite.client.callback.Hooks;
import net.runelite.client.chat.ChatMessageManager; import net.runelite.client.chat.ChatMessageManager;
import net.runelite.client.chat.CommandManager; import net.runelite.client.chat.CommandManager;
import net.runelite.client.config.ConfigManager; import net.runelite.client.config.ConfigManager;
import net.runelite.client.config.LauncherConfig;
import net.runelite.client.config.OpenOSRSConfig;
import net.runelite.client.discord.DiscordService; import net.runelite.client.discord.DiscordService;
import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.EventBus;
import net.runelite.client.events.ExternalPluginsLoaded; import net.runelite.client.externalplugins.ExternalPluginManager;
import net.runelite.client.game.FriendChatManager; import net.runelite.client.game.FriendChatManager;
import net.runelite.client.game.ItemManager; import net.runelite.client.game.ItemManager;
import net.runelite.client.game.LootManager; import net.runelite.client.game.LootManager;
import net.runelite.client.game.PlayerManager;
import net.runelite.client.game.WorldService;
import net.runelite.client.game.XpDropManager;
import net.runelite.client.game.chatbox.ChatboxPanelManager; import net.runelite.client.game.chatbox.ChatboxPanelManager;
import net.runelite.client.graphics.ModelOutlineRenderer;
import net.runelite.client.menus.MenuManager; import net.runelite.client.menus.MenuManager;
import net.runelite.client.plugins.ExternalPluginManager;
import net.runelite.client.plugins.PluginManager; import net.runelite.client.plugins.PluginManager;
import net.runelite.client.rs.ClientLoader; import net.runelite.client.rs.ClientLoader;
import net.runelite.client.rs.ClientUpdateCheckMode; import net.runelite.client.rs.ClientUpdateCheckMode;
import net.runelite.client.task.Scheduler;
import net.runelite.client.ui.ClientUI; import net.runelite.client.ui.ClientUI;
import net.runelite.client.ui.RuneLiteSplashScreen; import net.runelite.client.ui.DrawManager;
import net.runelite.client.ui.FatalErrorDialog;
import net.runelite.client.ui.SplashScreen;
import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.ui.overlay.OverlayRenderer; import net.runelite.client.ui.overlay.OverlayRenderer;
import net.runelite.client.ui.overlay.WidgetOverlay; import net.runelite.client.ui.overlay.WidgetOverlay;
import net.runelite.client.ui.overlay.arrow.ArrowMinimapOverlay;
import net.runelite.client.ui.overlay.arrow.ArrowWorldOverlay;
import net.runelite.client.ui.overlay.infobox.InfoBoxManager; import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
import net.runelite.client.ui.overlay.tooltip.TooltipManager;
import net.runelite.client.ui.overlay.tooltip.TooltipOverlay; import net.runelite.client.ui.overlay.tooltip.TooltipOverlay;
import net.runelite.client.ui.overlay.worldmap.WorldMapOverlay; import net.runelite.client.ui.overlay.worldmap.WorldMapOverlay;
import net.runelite.client.util.Groups;
import net.runelite.client.util.WorldUtil;
import net.runelite.client.ws.PartyService; import net.runelite.client.ws.PartyService;
import net.runelite.http.api.RuneLiteAPI; import net.runelite.http.api.RuneLiteAPI;
import net.runelite.http.api.worlds.World;
import net.runelite.http.api.worlds.WorldResult;
import okhttp3.Cache; import okhttp3.Cache;
import okhttp3.OkHttpClient; import okhttp3.OkHttpClient;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -120,42 +91,41 @@ import org.slf4j.LoggerFactory;
@Slf4j @Slf4j
public class RuneLite public class RuneLite
{ {
public static final String SYSTEM_VERSION = "0.0.1";
public static final File RUNELITE_DIR = new File(System.getProperty("user.home"), ".runelite"); public static final File RUNELITE_DIR = new File(System.getProperty("user.home"), ".runelite");
public static final File CACHE_DIR = new File(RUNELITE_DIR, "cache"); public static final File CACHE_DIR = new File(RUNELITE_DIR, "cache");
public static final File PLUGINS_DIR = new File(RUNELITE_DIR, "plugins");
public static final File PROFILES_DIR = new File(RUNELITE_DIR, "profiles"); public static final File PROFILES_DIR = new File(RUNELITE_DIR, "profiles");
public static final File EXTERNALPLUGIN_DIR = new File(RUNELITE_DIR, "externalmanager");
public static final File SCREENSHOT_DIR = new File(RUNELITE_DIR, "screenshots"); public static final File SCREENSHOT_DIR = new File(RUNELITE_DIR, "screenshots");
public static final File LOGS_DIR = new File(RUNELITE_DIR, "logs"); public static final File LOGS_DIR = new File(RUNELITE_DIR, "logs");
public static final File DEFAULT_CONFIG_FILE = new File(RUNELITE_DIR, "runeliteplus.properties"); public static final File DEFAULT_SESSION_FILE = new File(RUNELITE_DIR, "session");
public static final Locale SYSTEM_LOCALE = Locale.getDefault(); public static final File DEFAULT_CONFIG_FILE = new File(RUNELITE_DIR, "settings.properties");
public static boolean allowPrivateServer = false;
public static String uuid = UUID.randomUUID().toString();
private static final int MAX_OKHTTP_CACHE_SIZE = 20 * 1024 * 1024; // 20mb private static final int MAX_OKHTTP_CACHE_SIZE = 20 * 1024 * 1024; // 20mb
@Getter @Getter
private static Injector injector; private static Injector injector;
@Inject
public DiscordService discordService;
@Inject
private WorldService worldService;
@Inject @Inject
private PluginManager pluginManager; private PluginManager pluginManager;
@Inject @Inject
private ExternalPluginManager externalPluginManager; private ExternalPluginManager externalPluginManager;
@Inject
private EventBus eventBus;
@Inject @Inject
private ConfigManager configManager; private ConfigManager configManager;
@Inject
private DrawManager drawManager;
@Inject @Inject
private SessionManager sessionManager; private SessionManager sessionManager;
@Inject
private DiscordService discordService;
@Inject @Inject
private ClientSessionManager clientSessionManager; private ClientSessionManager clientSessionManager;
@@ -163,10 +133,10 @@ public class RuneLite
private ClientUI clientUI; private ClientUI clientUI;
@Inject @Inject
private OverlayManager overlayManager; private Provider<InfoBoxManager> infoBoxManager;
@Inject @Inject
private TooltipManager tooltipManager; private OverlayManager overlayManager;
@Inject @Inject
private Provider<PartyService> partyService; private Provider<PartyService> partyService;
@@ -178,7 +148,7 @@ public class RuneLite
private Provider<OverlayRenderer> overlayRenderer; private Provider<OverlayRenderer> overlayRenderer;
@Inject @Inject
private Provider<FriendChatManager> friendChatManager; private Provider<FriendChatManager> friendsChatManager;
@Inject @Inject
private Provider<ChatMessageManager> chatMessageManager; private Provider<ChatMessageManager> chatMessageManager;
@@ -189,58 +159,25 @@ public class RuneLite
@Inject @Inject
private Provider<CommandManager> commandManager; private Provider<CommandManager> commandManager;
@Inject
private Provider<InfoBoxManager> infoBoxManager;
@Inject @Inject
private Provider<TooltipOverlay> tooltipOverlay; private Provider<TooltipOverlay> tooltipOverlay;
@Inject @Inject
private Provider<WorldMapOverlay> worldMapOverlay; private Provider<WorldMapOverlay> worldMapOverlay;
@Inject
private Provider<ArrowWorldOverlay> arrowWorldOverlay;
@Inject
private Provider<ArrowMinimapOverlay> arrowMinimapOverlay;
@Inject @Inject
private Provider<LootManager> lootManager; private Provider<LootManager> lootManager;
@Inject
private Provider<XpDropManager> xpDropManager;
@Inject
private Provider<PlayerManager> playerManager;
@Inject @Inject
private Provider<ChatboxPanelManager> chatboxPanelManager; private Provider<ChatboxPanelManager> chatboxPanelManager;
@Inject @Inject
private Groups groups; private Provider<Hooks> hooks;
@Inject
private Hooks hooks;
@Inject
private EventBus eventBus;
@Inject @Inject
@Nullable @Nullable
private Client client; private Client client;
@Inject
private OpenOSRSConfig openOSRSConfig;
@Inject
private LauncherConfig launcherConfig;
@Inject
private Provider<ModelOutlineRenderer> modelOutlineRenderer;
@Inject
private Scheduler scheduler;
public static void main(String[] args) throws Exception public static void main(String[] args) throws Exception
{ {
Locale.setDefault(Locale.ENGLISH); Locale.setDefault(Locale.ENGLISH);
@@ -249,15 +186,13 @@ public class RuneLite
parser.accepts("developer-mode", "Enable developer tools"); parser.accepts("developer-mode", "Enable developer tools");
parser.accepts("debug", "Show extra debugging output"); parser.accepts("debug", "Show extra debugging output");
parser.accepts("safe-mode", "Disables external plugins and the GPU plugin"); parser.accepts("safe-mode", "Disables external plugins and the GPU plugin");
parser.accepts("no-splash", "Do not show the splash screen");
parser.accepts("insecure-skip-tls-verification", "Disables TLS verification"); parser.accepts("insecure-skip-tls-verification", "Disables TLS verification");
final ArgumentAcceptingOptionSpec<String> proxyInfo = parser final ArgumentAcceptingOptionSpec<File> sessionfile = parser.accepts("sessionfile", "Use a specified session file")
.accepts("proxy") .withRequiredArg()
.withRequiredArg().ofType(String.class); .withValuesConvertedBy(new ConfigFileConverter())
final ArgumentAcceptingOptionSpec<Integer> worldInfo = parser .defaultsTo(DEFAULT_SESSION_FILE);
.accepts("world")
.withRequiredArg().ofType(Integer.class);
final ArgumentAcceptingOptionSpec<File> configfile = parser.accepts("config", "Use a specified config file") final ArgumentAcceptingOptionSpec<File> configfile = parser.accepts("config", "Use a specified config file")
.withRequiredArg() .withRequiredArg()
.withValuesConvertedBy(new ConfigFileConverter()) .withValuesConvertedBy(new ConfigFileConverter())
@@ -268,7 +203,7 @@ public class RuneLite
.withRequiredArg() .withRequiredArg()
.ofType(ClientUpdateCheckMode.class) .ofType(ClientUpdateCheckMode.class)
.defaultsTo(ClientUpdateCheckMode.AUTO) .defaultsTo(ClientUpdateCheckMode.AUTO)
.withValuesConvertedBy(new EnumConverter<>(ClientUpdateCheckMode.class) .withValuesConvertedBy(new EnumConverter<ClientUpdateCheckMode>(ClientUpdateCheckMode.class)
{ {
@Override @Override
public ClientUpdateCheckMode convert(String v) public ClientUpdateCheckMode convert(String v)
@@ -278,18 +213,7 @@ public class RuneLite
}); });
parser.accepts("help", "Show this text").forHelp(); parser.accepts("help", "Show this text").forHelp();
OptionSet options = parser.parse(args);
OptionSet options = parser.parse("");
try
{
options = parser.parse(args);
}
catch (OptionException e)
{
log.warn("Error parsing launch args: {}", e.getMessage());
log.warn("Proceeding with no arguments.");
}
if (options.has("help")) if (options.has("help"))
{ {
@@ -303,147 +227,92 @@ public class RuneLite
logger.setLevel(Level.DEBUG); logger.setLevel(Level.DEBUG);
} }
if (options.has("proxy")) Thread.setDefaultUncaughtExceptionHandler((thread, throwable) ->
{ {
String[] proxy = options.valueOf(proxyInfo).split(":"); log.error("Uncaught exception:", throwable);
if (throwable instanceof AbstractMethodError)
if (proxy.length >= 2)
{ {
System.setProperty("socksProxyHost", proxy[0]); log.error("Classes are out of date; Build with maven again.");
System.setProperty("socksProxyPort", proxy[1]);
} }
});
if (proxy.length >= 4) OkHttpClient.Builder okHttpClientBuilder = RuneLiteAPI.CLIENT.newBuilder()
{
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 final PasswordAuthentication auth = new PasswordAuthentication(user, pass);
protected PasswordAuthentication getPasswordAuthentication()
{
return auth;
}
});
}
}
if (options.has("world"))
{
int world = options.valueOf(worldInfo);
System.setProperty("cli.world", String.valueOf(world));
}
final File configFile = resolveLinks(options.valueOf(configfile));
Properties properties = new Properties();
try (FileInputStream in = new FileInputStream(configFile))
{
properties.load(new InputStreamReader(in, StandardCharsets.UTF_8));
try
{
@SuppressWarnings("unchecked") Map<String, String> copy = (Map) Map.copyOf(properties);
copy.forEach((groupAndKey, value) ->
{
final String[] split = groupAndKey.split("\\.", 2);
final String groupName = split[0];
final String key = split[1];
if (!groupName.equals("openosrs"))
{
return;
}
if (key.equals("disableHw") && value.equals("true"))
{
log.info("Disabling HW Accel");
System.setProperty("sun.java2d.noddraw", "true");
}
});
}
catch (Exception ex)
{
log.error("Unexpected error", ex);
}
}
catch (FileNotFoundException ex)
{
log.error("Unable to load settings - no such file");
}
catch (IllegalArgumentException | IOException ex)
{
log.error("Unable to load settings", ex);
}
final OkHttpClient.Builder okHttpClientBuilder = RuneLiteAPI.CLIENT.newBuilder()
.cache(new Cache(new File(CACHE_DIR, "okhttp"), MAX_OKHTTP_CACHE_SIZE)); .cache(new Cache(new File(CACHE_DIR, "okhttp"), MAX_OKHTTP_CACHE_SIZE));
final boolean insecureSkipTlsVerification = options.has("insecure-skip-tls-verification"); final boolean insecureSkipTlsVerification = options.has("insecure-skip-tls-verification");
if (insecureSkipTlsVerification) if (insecureSkipTlsVerification || RuneLiteProperties.isInsecureSkipTlsVerification())
{ {
setupInsecureTrustManager(okHttpClientBuilder); setupInsecureTrustManager(okHttpClientBuilder);
} }
final OkHttpClient okHttpClient = okHttpClientBuilder.build(); final OkHttpClient okHttpClient = okHttpClientBuilder.build();
final ClientLoader clientLoader = new ClientLoader(okHttpClient, options.valueOf(updateMode)); SplashScreen.init();
Completable.fromAction(clientLoader::get) SplashScreen.stage(0, "Retrieving client", "");
.subscribeOn(Schedulers.computation())
.subscribe();
Completable.fromAction(ClassPreloader::preload) try
.subscribeOn(Schedulers.computation())
.subscribe();
if (!options.has("no-splash"))
{ {
RuneLiteSplashScreen.init(); final ClientLoader clientLoader = new ClientLoader(okHttpClient, options.valueOf(updateMode));
}
Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> new Thread(() ->
{
log.error("Uncaught exception:", throwable);
if (throwable instanceof AbstractMethodError)
{ {
RuneLiteSplashScreen.setError("Out of date!", "Classes are out of date; Build with Gradle again."); clientLoader.get();
return; ClassPreloader.preload();
}, "Preloader").start();
final boolean developerMode = options.has("developer-mode") && RuneLiteProperties.getLauncherVersion() == null;
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;
}
} }
RuneLiteSplashScreen.setError("Error while loading!", "Please check your internet connection and your DNS settings."); PROFILES_DIR.mkdirs();
});
PROFILES_DIR.mkdirs(); log.info("RuneLite {} (launcher version {}) starting up, args: {}",
RuneLiteProperties.getVersion(), RuneLiteProperties.getLauncherVersion() == null ? "unknown" : RuneLiteProperties.getLauncherVersion(),
args.length == 0 ? "none" : String.join(" ", args));
log.info("OpenOSRS {} Runelite {} (launcher version {}) starting up, args: {}", final long start = System.currentTimeMillis();
RuneLiteProperties.getPlusVersion(), RuneLiteProperties.getVersion(), RuneLiteProperties.getLauncherVersion() == null ? "unknown" : RuneLiteProperties.getLauncherVersion(),
args.length == 0 ? "none" : String.join(" ", args));
final long start = System.currentTimeMillis(); injector = Guice.createInjector(new RuneLiteModule(
okHttpClient,
clientLoader,
developerMode,
options.has("safe-mode"),
options.valueOf(sessionfile),
options.valueOf(configfile)));
injector = Guice.createInjector(new RuneLiteModule( injector.getInstance(RuneLite.class).start();
okHttpClient,
clientLoader,
options.has("safe-mode"),
configFile));
injector.getInstance(RuneLite.class).start(); final long end = System.currentTimeMillis();
final long end = System.currentTimeMillis(); final RuntimeMXBean rb = ManagementFactory.getRuntimeMXBean();
final RuntimeMXBean rb = ManagementFactory.getRuntimeMXBean(); final long uptime = rb.getUptime();
final long uptime = rb.getUptime(); log.info("Client initialization took {}ms. Uptime: {}ms", end - start, uptime);
log.info("Client initialization took {}ms. Uptime: {}ms", end - start, uptime); }
catch (Exception e)
{
log.error("Failure during startup", e);
SwingUtilities.invokeLater(() ->
new FatalErrorDialog("RuneLite has encountered an unexpected error during startup.")
.open());
}
finally
{
SplashScreen.stop();
}
} }
@VisibleForTesting public void start() throws Exception
public static void setInjector(Injector injector)
{
RuneLite.injector = injector;
}
private void start() throws Exception
{ {
// Load RuneLite or Vanilla client // Load RuneLite or Vanilla client
final boolean isOutdated = client == null; final boolean isOutdated = client == null;
@@ -454,181 +323,84 @@ public class RuneLite
injector.injectMembers(client); injector.injectMembers(client);
} }
if (RuneLiteProperties.getLauncherVersion() == null || !openOSRSConfig.shareLogs()) SplashScreen.stage(.57, null, "Loading configuration");
{
final Logger logger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
logger.detachAppender("Sentry");
}
// Load user configuration // Load user configuration
RuneLiteSplashScreen.stage(.57, "Loading user config");
configManager.load(); configManager.load();
parseLauncherConfig();
// Load the session, including saved configuration // Load the session, including saved configuration
RuneLiteSplashScreen.stage(.58, "Loading session data");
sessionManager.loadSession(); sessionManager.loadSession();
// Tell the plugin manager if client is outdated or not // Tell the plugin manager if client is outdated or not
pluginManager.setOutdated(isOutdated); pluginManager.setOutdated(isOutdated);
// Load external plugin manager
externalPluginManager.startExternalUpdateManager();
externalPluginManager.startExternalPluginManager();
// Update external plugins
externalPluginManager.update();
// Load the plugins, but does not start them yet. // Load the plugins, but does not start them yet.
// This will initialize configuration // This will initialize configuration
pluginManager.loadCorePlugins(); pluginManager.loadCorePlugins();
externalPluginManager.loadPlugins(); externalPluginManager.loadExternalPlugins();
RuneLiteSplashScreen.stage(.76, "Finalizing configuration"); SplashScreen.stage(.70, null, "Finalizing configuration");
// Plugins have provided their config, so set default config // Plugins have provided their config, so set default config
// to main settings // to main settings
pluginManager.loadDefaultPluginConfiguration(); pluginManager.loadDefaultPluginConfiguration(null);
// Start client session // Start client session
RuneLiteSplashScreen.stage(.77, "Starting core interface");
clientSessionManager.start(); clientSessionManager.start();
eventBus.register(clientSessionManager);
//Set the world if specified via CLI args - will not work until clientUI.init is called SplashScreen.stage(.75, null, "Starting core interface");
Optional<Integer> worldArg = Optional.ofNullable(System.getProperty("cli.world")).map(Integer::parseInt);
worldArg.ifPresent(this::setWorld);
// Initialize UI // Initialize UI
RuneLiteSplashScreen.stage(.80, "Initialize UI");
clientUI.init(); clientUI.init();
// Initialize Discord service // Initialize Discord service
discordService.init(); discordService.init();
// Register event listeners
eventBus.register(clientUI);
eventBus.register(pluginManager);
eventBus.register(externalPluginManager);
eventBus.register(overlayManager);
eventBus.register(drawManager);
eventBus.register(configManager);
eventBus.register(discordService);
if (!isOutdated) if (!isOutdated)
{ {
// Initialize chat colors // Initialize chat colors
chatMessageManager.get().loadColors(); chatMessageManager.get().loadColors();
infoBoxManager.get(); eventBus.register(infoBoxManager.get());
overlayRenderer.get(); eventBus.register(partyService.get());
friendChatManager.get(); eventBus.register(overlayRenderer.get());
itemManager.get(); eventBus.register(friendsChatManager.get());
menuManager.get(); eventBus.register(itemManager.get());
chatMessageManager.get(); eventBus.register(menuManager.get());
commandManager.get(); eventBus.register(chatMessageManager.get());
lootManager.get(); eventBus.register(commandManager.get());
xpDropManager.get(); eventBus.register(lootManager.get());
playerManager.get(); eventBus.register(chatboxPanelManager.get());
chatboxPanelManager.get(); eventBus.register(hooks.get());
partyService.get();
eventBus.subscribe(GameStateChanged.class, this, hooks::onGameStateChanged);
eventBus.subscribe(ScriptCallbackEvent.class, this, hooks::onScriptCallbackEvent);
// Add core overlays // Add core overlays
WidgetOverlay.createOverlays(client).forEach(overlayManager::add); WidgetOverlay.createOverlays(client).forEach(overlayManager::add);
overlayManager.add(worldMapOverlay.get()); overlayManager.add(worldMapOverlay.get());
overlayManager.add(tooltipOverlay.get()); overlayManager.add(tooltipOverlay.get());
overlayManager.add(arrowWorldOverlay.get());
overlayManager.add(arrowMinimapOverlay.get());
} }
// Start plugins // Start plugins
pluginManager.startPlugins(); pluginManager.startPlugins();
eventBus.post(ExternalPluginsLoaded.class, new ExternalPluginsLoaded());
// Register additional schedulers SplashScreen.stop();
if (this.client != null)
{
scheduler.registerObject(modelOutlineRenderer.get());
scheduler.registerObject(clientSessionManager);
}
// Close the splash screen
RuneLiteSplashScreen.close();
clientUI.show(); clientUI.show();
} }
private void setWorld(int cliWorld) @VisibleForTesting
public static void setInjector(Injector injector)
{ {
int correctedWorld = cliWorld < 300 ? cliWorld + 300 : cliWorld; RuneLite.injector = injector;
if (correctedWorld <= 300 || client.getWorld() == correctedWorld)
{
return;
}
final WorldResult worldResult = worldService.getWorlds();
if (worldResult == null)
{
log.warn("Failed to lookup worlds.");
return;
}
final World world = worldResult.findWorld(correctedWorld);
if (world != null)
{
final net.runelite.api.World rsWorld = client.createWorld();
rsWorld.setActivity(world.getActivity());
rsWorld.setAddress(world.getAddress());
rsWorld.setId(world.getId());
rsWorld.setPlayerCount(world.getPlayers());
rsWorld.setLocation(world.getLocation());
rsWorld.setTypes(WorldUtil.toWorldTypes(world.getTypes()));
client.changeWorld(rsWorld);
log.debug("Applied new world {}", correctedWorld);
}
else
{
log.warn("World {} not found.", correctedWorld);
}
}
private void parseLauncherConfig()
{
String launcherVersion = RuneLiteProperties.getLauncherVersion();
if (launcherVersion == null || !Version.valueOf(launcherVersion).greaterThanOrEqualTo(Version.valueOf("2.2.0")))
{
return;
}
if (launcherConfig.useProxy())
{
log.info("Setting proxy.");
String[] proxy = launcherConfig.proxyDetails().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 final PasswordAuthentication auth = new PasswordAuthentication(user, pass);
protected PasswordAuthentication getPasswordAuthentication()
{
return auth;
}
});
}
}
} }
private static class ConfigFileConverter implements ValueConverter<File> private static class ConfigFileConverter implements ValueConverter<File>
@@ -670,18 +442,6 @@ public class RuneLite
} }
} }
private static File resolveLinks(File f)
{
try
{
return f.toPath().toRealPath().toFile();
}
catch (IOException e)
{
return f;
}
}
private static void setupInsecureTrustManager(OkHttpClient.Builder okHttpClientBuilder) private static void setupInsecureTrustManager(OkHttpClient.Builder okHttpClientBuilder)
{ {
try try

View File

@@ -24,18 +24,13 @@
*/ */
package net.runelite.client; package net.runelite.client;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Provides; import com.google.inject.Provides;
import com.google.inject.name.Names; import com.google.inject.name.Names;
import java.applet.Applet; import java.applet.Applet;
import java.io.File; import java.io.File;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier; import java.util.function.Supplier;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.inject.Singleton; import javax.inject.Singleton;
@@ -47,8 +42,6 @@ import net.runelite.client.callback.Hooks;
import net.runelite.client.chat.ChatMessageManager; import net.runelite.client.chat.ChatMessageManager;
import net.runelite.client.config.ChatColorConfig; import net.runelite.client.config.ChatColorConfig;
import net.runelite.client.config.ConfigManager; import net.runelite.client.config.ConfigManager;
import net.runelite.client.config.LauncherConfig;
import net.runelite.client.config.OpenOSRSConfig;
import net.runelite.client.config.RuneLiteConfig; import net.runelite.client.config.RuneLiteConfig;
import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.EventBus;
import net.runelite.client.game.ItemManager; import net.runelite.client.game.ItemManager;
@@ -57,25 +50,27 @@ import net.runelite.client.plugins.PluginManager;
import net.runelite.client.task.Scheduler; import net.runelite.client.task.Scheduler;
import net.runelite.client.util.DeferredEventBus; import net.runelite.client.util.DeferredEventBus;
import net.runelite.client.util.ExecutorServiceExceptionLogger; import net.runelite.client.util.ExecutorServiceExceptionLogger;
import net.runelite.client.util.NonScheduledExecutorServiceExceptionLogger;
import net.runelite.http.api.chat.ChatClient; import net.runelite.http.api.chat.ChatClient;
import okhttp3.OkHttpClient; import okhttp3.OkHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@AllArgsConstructor @AllArgsConstructor
public class RuneLiteModule extends AbstractModule public class RuneLiteModule extends AbstractModule
{ {
private final OkHttpClient okHttpClient; private final OkHttpClient okHttpClient;
private final Supplier<Applet> clientLoader; private final Supplier<Applet> clientLoader;
private final boolean developerMode;
private final boolean safeMode; private final boolean safeMode;
private final File sessionfile;
private final File config; private final File config;
@Override @Override
protected void configure() protected void configure()
{ {
bindConstant().annotatedWith(Names.named("developerMode")).to(developerMode);
bindConstant().annotatedWith(Names.named("safeMode")).to(safeMode); bindConstant().annotatedWith(Names.named("safeMode")).to(safeMode);
bind(File.class).annotatedWith(Names.named("sessionfile")).toInstance(sessionfile);
bind(File.class).annotatedWith(Names.named("config")).toInstance(config); bind(File.class).annotatedWith(Names.named("config")).toInstance(config);
bind(ScheduledExecutorService.class).toInstance(new ExecutorServiceExceptionLogger(Executors.newSingleThreadScheduledExecutor()));
bind(OkHttpClient.class).toInstance(okHttpClient); bind(OkHttpClient.class).toInstance(okHttpClient);
bind(MenuManager.class); bind(MenuManager.class);
bind(ChatMessageManager.class); bind(ChatMessageManager.class);
@@ -92,10 +87,6 @@ public class RuneLiteModule extends AbstractModule
bind(EventBus.class) bind(EventBus.class)
.annotatedWith(Names.named("Deferred EventBus")) .annotatedWith(Names.named("Deferred EventBus"))
.to(DeferredEventBus.class); .to(DeferredEventBus.class);
bind(Logger.class)
.annotatedWith(Names.named("Core Logger"))
.toInstance(LoggerFactory.getLogger(RuneLite.class));
} }
@Provides @Provides
@@ -119,13 +110,6 @@ public class RuneLiteModule extends AbstractModule
return configManager.getConfig(RuneLiteConfig.class); return configManager.getConfig(RuneLiteConfig.class);
} }
@Provides
@Singleton
OpenOSRSConfig providePlusConfig(ConfigManager configManager)
{
return configManager.getConfig(OpenOSRSConfig.class);
}
@Provides @Provides
@Singleton @Singleton
ChatColorConfig provideChatColorConfig(ConfigManager configManager) ChatColorConfig provideChatColorConfig(ConfigManager configManager)
@@ -133,39 +117,6 @@ public class RuneLiteModule extends AbstractModule
return configManager.getConfig(ChatColorConfig.class); return configManager.getConfig(ChatColorConfig.class);
} }
@Provides
@Singleton
LauncherConfig provideLauncherConfig(ConfigManager configManager)
{
return configManager.getConfig(LauncherConfig.class);
}
@Provides
@Singleton
ScheduledExecutorService provideScheduledExecutorService()
{
return new ExecutorServiceExceptionLogger(Executors.newSingleThreadScheduledExecutor(new ThreadFactoryBuilder()
.setNameFormat("scheduled-%d")
.build()));
}
@Provides
@Singleton
ExecutorService provideExecutorService()
{
int poolSize = 2 * Runtime.getRuntime().availableProcessors();
// Will start up to poolSize threads (because of allowCoreThreadTimeOut) as necessary, and times out
// unused threads after 1 minute
ThreadPoolExecutor executor = new ThreadPoolExecutor(poolSize, poolSize,
60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(),
new ThreadFactoryBuilder().setNameFormat("worker-%d").build());
executor.allowCoreThreadTimeOut(true);
return new NonScheduledExecutorServiceExceptionLogger(executor);
}
@Provides @Provides
@Singleton @Singleton
ChatClient provideChatClient(OkHttpClient okHttpClient) ChatClient provideChatClient(OkHttpClient okHttpClient)

View File

@@ -24,37 +24,38 @@
*/ */
package net.runelite.client; package net.runelite.client;
import com.google.common.base.Strings;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Properties; import java.util.Properties;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import okhttp3.HttpUrl;
public class RuneLiteProperties public class RuneLiteProperties
{ {
private static final String RUNELITE_TITLE = "open.osrs.title"; private static final String RUNELITE_TITLE = "runelite.title";
private static final String RUNELITE_VERSION = "runelite.version"; private static final String RUNELITE_VERSION = "runelite.version";
private static final String RUNELITE_PLUS_VERSION = "open.osrs.version";
private static final String RUNELITE_PLUS_DATE = "open.osrs.builddate";
private static final String RUNESCAPE_VERSION = "runescape.version"; private static final String RUNESCAPE_VERSION = "runescape.version";
private static final String DISCORD_APP_ID = "open.osrs.discord.appid"; private static final String DISCORD_APP_ID = "runelite.discord.appid";
private static final String DISCORD_INVITE = "runelite.discord.invite"; private static final String DISCORD_INVITE = "runelite.discord.invite";
private static final String GITHUB_LINK = "runelite.github.link"; private static final String GITHUB_LINK = "runelite.github.link";
private static final String WIKI_LINK = "runelite.wiki.link"; private static final String WIKI_LINK = "runelite.wiki.link";
private static final String PATREON_LINK = "runelite.patreon.link"; private static final String PATREON_LINK = "runelite.patreon.link";
private static final String LAUNCHER_VERSION_PROPERTY = "launcher.version"; private static final String LAUNCHER_VERSION_PROPERTY = "runelite.launcher.version";
private static final String PLUGIN_PATH = "plugin.path"; private static final String INSECURE_SKIP_TLS_VERIFICATION_PROPERTY = "runelite.insecure-skip-tls-verification";
private static final String PLUGIN_DEVELOPMENT_PATH = "plugin.development.path";
private static final String TROUBLESHOOTING_LINK = "runelite.wiki.troubleshooting.link"; private static final String TROUBLESHOOTING_LINK = "runelite.wiki.troubleshooting.link";
private static final String BUILDING_LINK = "runelite.wiki.building.link"; private static final String BUILDING_LINK = "runelite.wiki.building.link";
private static final String DNS_CHANGE_LINK = "runelite.dnschange.link"; private static final String DNS_CHANGE_LINK = "runelite.dnschange.link";
private static final String JAV_CONFIG = "runelite.jav_config";
private static final String JAV_CONFIG_BACKUP = "runelite.jav_config_backup";
private static final String PLUGINHUB_BASE = "runelite.pluginhub.url";
private static final String PLUGINHUB_VERSION = "runelite.pluginhub.version";
private static final String IMGUR_CLIENT_ID = "runelite.imgur.client.id"; private static final String IMGUR_CLIENT_ID = "runelite.imgur.client.id";
private static final Properties properties = new Properties(); private static final Properties properties = new Properties();
static static
{ {
try (InputStream in = RuneLiteProperties.class.getResourceAsStream("open.osrs.properties")) try (InputStream in = RuneLiteProperties.class.getResourceAsStream("runelite.properties"))
{ {
properties.load(in); properties.load(in);
} }
@@ -66,13 +67,7 @@ public class RuneLiteProperties
public static String getTitle() public static String getTitle()
{ {
final StringBuilder sb = new StringBuilder(properties.getProperty(RUNELITE_TITLE)); return 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() public static String getVersion()
@@ -80,16 +75,6 @@ public class RuneLiteProperties
return properties.getProperty(RUNELITE_VERSION); 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() public static String getRunescapeVersion()
{ {
return properties.getProperty(RUNESCAPE_VERSION); return properties.getProperty(RUNESCAPE_VERSION);
@@ -120,6 +105,17 @@ public class RuneLiteProperties
return properties.getProperty(PATREON_LINK); return properties.getProperty(PATREON_LINK);
} }
@Nullable
public static String getLauncherVersion()
{
return System.getProperty(LAUNCHER_VERSION_PROPERTY);
}
public static boolean isInsecureSkipTlsVerification()
{
return Boolean.getBoolean(INSECURE_SKIP_TLS_VERIFICATION_PROPERTY);
}
public static String getTroubleshootingLink() public static String getTroubleshootingLink()
{ {
return properties.getProperty(TROUBLESHOOTING_LINK); return properties.getProperty(TROUBLESHOOTING_LINK);
@@ -135,31 +131,20 @@ public class RuneLiteProperties
return properties.getProperty(DNS_CHANGE_LINK); return properties.getProperty(DNS_CHANGE_LINK);
} }
@Nullable public static String getJavConfig()
public static String getLauncherVersion()
{ {
return System.getProperty(LAUNCHER_VERSION_PROPERTY); return properties.getProperty(JAV_CONFIG);
} }
@Nullable public static String getJavConfigBackup()
public static String getPluginPath()
{ {
String pluginPath = properties.getProperty(PLUGIN_PATH); return properties.getProperty(JAV_CONFIG_BACKUP);
return pluginPath.equals("") ? null : pluginPath;
} }
public static String[] getPluginDevelopmentPath() public static HttpUrl getPluginHubBase()
{ {
// First check if property supplied as environment variable PLUGIN_DEVELOPMENT_PATHS String version = System.getProperty(PLUGINHUB_VERSION, properties.getProperty(PLUGINHUB_VERSION));
String developmentPluginPaths = System.getenv(PLUGIN_DEVELOPMENT_PATH.replace('.', '_').toUpperCase()); return HttpUrl.parse(properties.get(PLUGINHUB_BASE) + "/" + version);
if (Strings.isNullOrEmpty(developmentPluginPaths))
{
// Otherwise check the property file
developmentPluginPaths = properties.getProperty(PLUGIN_DEVELOPMENT_PATH);
}
return Strings.isNullOrEmpty(developmentPluginPaths) ? new String[0] : developmentPluginPaths.split(";");
} }
public static String getImgurClientId() public static String getImgurClientId()

View File

@@ -24,8 +24,7 @@
*/ */
package net.runelite.client; package net.runelite.client;
import io.reactivex.rxjava3.core.Completable; import com.google.gson.JsonParseException;
import io.reactivex.rxjava3.core.Observable;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
@@ -36,6 +35,7 @@ import net.runelite.http.api.RuneLiteAPI;
import okhttp3.HttpUrl; import okhttp3.HttpUrl;
import okhttp3.OkHttpClient; import okhttp3.OkHttpClient;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response; import okhttp3.Response;
import okhttp3.ResponseBody; import okhttp3.ResponseBody;
@@ -44,73 +44,62 @@ class SessionClient
{ {
private final OkHttpClient okHttpClient; private final OkHttpClient okHttpClient;
Observable<UUID> openSession() UUID open() throws IOException
{ {
final HttpUrl url = RuneLiteAPI.getSessionBase().newBuilder() HttpUrl url = RuneLiteAPI.getSessionBase().newBuilder()
.addPathSegment("new")
.build(); .build();
return Observable.fromCallable(() -> Request request = new Request.Builder()
.post(RequestBody.create(null, new byte[0]))
.url(url)
.build();
try (Response response = okHttpClient.newCall(request).execute())
{ {
Request request = new Request.Builder() ResponseBody body = response.body();
.url(url)
.build();
try (Response response = okHttpClient.newCall(request).execute()) InputStream in = body.byteStream();
{ return RuneLiteAPI.GSON.fromJson(new InputStreamReader(in, StandardCharsets.UTF_8), UUID.class);
ResponseBody body = response.body(); }
catch (JsonParseException | IllegalArgumentException ex) // UUID.fromString can throw IllegalArgumentException
InputStream in = body.byteStream(); {
try throw new IOException(ex);
{ }
return RuneLiteAPI.GSON.fromJson(new InputStreamReader(in, StandardCharsets.UTF_8), UUID.class);
}
catch (IllegalArgumentException ex)
{
ex.printStackTrace();
return null;
}
}
});
} }
Completable pingSession(UUID uuid) void ping(UUID uuid, boolean loggedIn) throws IOException
{ {
final HttpUrl url = RuneLiteAPI.getSessionBase().newBuilder() HttpUrl url = RuneLiteAPI.getSessionBase().newBuilder()
.addPathSegment("ping") .addPathSegment("ping")
.addQueryParameter("uuid", uuid.toString()) .addQueryParameter("session", uuid.toString())
.addQueryParameter("logged-in", String.valueOf(loggedIn))
.build(); .build();
return Completable.fromAction(() -> Request request = new Request.Builder()
{ .post(RequestBody.create(null, new byte[0]))
Request request = new Request.Builder() .url(url)
.url(url) .build();
.build();
try (Response response = okHttpClient.newCall(request).execute()) try (Response response = okHttpClient.newCall(request).execute())
{
if (!response.isSuccessful())
{ {
if (!response.isSuccessful()) throw new IOException("Unsuccessful ping");
{
throw new IOException("Unsuccessful ping");
}
} }
}); }
} }
Completable delete(UUID uuid) void delete(UUID uuid) throws IOException
{ {
final HttpUrl url = RuneLiteAPI.getSessionBase().newBuilder() HttpUrl url = RuneLiteAPI.getSessionBase().newBuilder()
.addQueryParameter("session", uuid.toString()) .addQueryParameter("session", uuid.toString())
.build(); .build();
return Completable.fromAction(() -> Request request = new Request.Builder()
{ .delete()
Request request = new Request.Builder() .url(url)
.delete() .build();
.url(url)
.build();
okHttpClient.newCall(request).execute().close(); okHttpClient.newCall(request).execute().close();
});
} }
} }

View File

@@ -25,7 +25,6 @@
package net.runelite.client.account; package net.runelite.client.account;
import com.google.gson.Gson; import com.google.gson.Gson;
import io.reactivex.rxjava3.schedulers.Schedulers;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@@ -37,11 +36,13 @@ import java.nio.charset.StandardCharsets;
import java.time.Instant; import java.time.Instant;
import java.util.UUID; import java.util.UUID;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import lombok.Getter; import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.runelite.client.RuneLite; import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.EventBus;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.events.SessionClose; import net.runelite.client.events.SessionClose;
import net.runelite.client.events.SessionOpen; import net.runelite.client.events.SessionOpen;
import net.runelite.client.util.LinkBrowser; import net.runelite.client.util.LinkBrowser;
@@ -55,31 +56,35 @@ import okhttp3.OkHttpClient;
@Slf4j @Slf4j
public class SessionManager public class SessionManager
{ {
private static final File SESSION_FILE = new File(RuneLite.RUNELITE_DIR, "session");
@Getter @Getter
private AccountSession accountSession; private AccountSession accountSession;
private final EventBus eventBus; private final EventBus eventBus;
private final ConfigManager configManager;
private final WSClient wsClient; private final WSClient wsClient;
private final File sessionFile;
private final AccountClient accountClient; private final AccountClient accountClient;
@Inject @Inject
private SessionManager( private SessionManager(
@Named("sessionfile") File sessionfile,
ConfigManager configManager,
EventBus eventBus, EventBus eventBus,
WSClient wsClient, WSClient wsClient,
OkHttpClient okHttpClient) OkHttpClient okHttpClient)
{ {
this.configManager = configManager;
this.eventBus = eventBus; this.eventBus = eventBus;
this.wsClient = wsClient; this.wsClient = wsClient;
this.sessionFile = sessionfile;
this.accountClient = new AccountClient(okHttpClient); this.accountClient = new AccountClient(okHttpClient);
this.eventBus.subscribe(LoginResponse.class, this, this::onLoginResponse); eventBus.register(this);
} }
public void loadSession() public void loadSession()
{ {
if (!SESSION_FILE.exists()) if (!sessionFile.exists())
{ {
log.info("No session file exists"); log.info("No session file exists");
return; return;
@@ -87,7 +92,7 @@ public class SessionManager
AccountSession session; AccountSession session;
try (FileInputStream in = new FileInputStream(SESSION_FILE)) try (FileInputStream in = new FileInputStream(sessionFile))
{ {
session = new Gson().fromJson(new InputStreamReader(in, StandardCharsets.UTF_8), AccountSession.class); session = new Gson().fromJson(new InputStreamReader(in, StandardCharsets.UTF_8), AccountSession.class);
@@ -101,26 +106,13 @@ public class SessionManager
// Check if session is still valid // Check if session is still valid
accountClient.setUuid(session.getUuid()); accountClient.setUuid(session.getUuid());
accountClient.sessionCheck() if (!accountClient.sessionCheck())
.subscribeOn(Schedulers.io()) {
.subscribe(b -> log.debug("Loaded session {} is invalid", session.getUuid());
{ return;
if (!b) }
{
log.debug("Loaded session {} is invalid", session.getUuid()); openSession(session, false);
}
else
{
openSession(session, false);
}
}, ex ->
{
if (ex instanceof IOException)
{
log.debug("Unable to verify session", ex);
openSession(session, false);
}
});
} }
private void saveSession() private void saveSession()
@@ -130,11 +122,11 @@ public class SessionManager
return; return;
} }
try (Writer fw = new OutputStreamWriter(new FileOutputStream(SESSION_FILE), StandardCharsets.UTF_8)) try (Writer fw = new OutputStreamWriter(new FileOutputStream(sessionFile), StandardCharsets.UTF_8))
{ {
new Gson().toJson(accountSession, fw); new Gson().toJson(accountSession, fw);
log.debug("Saved session to {}", SESSION_FILE); log.debug("Saved session to {}", sessionFile);
} }
catch (IOException ex) catch (IOException ex)
{ {
@@ -144,7 +136,7 @@ public class SessionManager
private void deleteSession() private void deleteSession()
{ {
SESSION_FILE.delete(); sessionFile.delete();
} }
/** /**
@@ -163,7 +155,14 @@ public class SessionManager
accountSession = session; accountSession = session;
eventBus.post(SessionOpen.class, new SessionOpen()); if (session.getUsername() != null)
{
// Initialize config for new session
// If the session isn't logged in yet, don't switch to the new config
configManager.switchSession(session);
}
eventBus.post(new SessionOpen());
} }
private void closeSession() private void closeSession()
@@ -189,7 +188,10 @@ public class SessionManager
accountSession = null; // No more account accountSession = null; // No more account
eventBus.post(SessionClose.class, new SessionClose()); // Restore config
configManager.switchSession(null);
eventBus.post(new SessionClose());
} }
public void login() public void login()
@@ -217,7 +219,8 @@ public class SessionManager
LinkBrowser.browse(login.getOauthUrl()); LinkBrowser.browse(login.getOauthUrl());
} }
private void onLoginResponse(LoginResponse loginResponse) @Subscribe
public void onLoginResponse(LoginResponse loginResponse)
{ {
log.debug("Now logged in as {}", loginResponse.getUsername()); log.debug("Now logged in as {}", loginResponse.getUsername());

View File

@@ -25,34 +25,22 @@
package net.runelite.client.callback; package net.runelite.client.callback;
import com.google.inject.Inject; import com.google.inject.Inject;
import io.reactivex.rxjava3.plugins.RxJavaPlugins;
import io.reactivex.rxjava3.schedulers.Schedulers;
import java.util.Iterator; import java.util.Iterator;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executor;
import java.util.function.BooleanSupplier; import java.util.function.BooleanSupplier;
import javax.annotation.Nullable;
import javax.inject.Singleton; import javax.inject.Singleton;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client; import net.runelite.api.Client;
import org.jetbrains.annotations.NotNull;
@Singleton @Singleton
@Slf4j @Slf4j
public class ClientThread implements Executor public class ClientThread
{ {
private final ConcurrentLinkedQueue<BooleanSupplier> invokes = new ConcurrentLinkedQueue<>(); private final ConcurrentLinkedQueue<BooleanSupplier> invokes = new ConcurrentLinkedQueue<>();
@Inject @Inject
@Nullable
private Client client; private Client client;
@Inject
private ClientThread()
{
RxJavaPlugins.setSingleSchedulerHandler(old -> Schedulers.from(this));
}
public void invoke(Runnable r) public void invoke(Runnable r)
{ {
invoke(() -> invoke(() ->
@@ -124,14 +112,4 @@ public class ClientThread implements Executor
} }
} }
} }
@Override
public void execute(@NotNull Runnable r)
{
invoke(() ->
{
r.run();
return true;
});
}
} }

View File

@@ -24,7 +24,6 @@
*/ */
package net.runelite.client.callback; package net.runelite.client.callback;
import com.google.inject.Injector;
import java.awt.Color; import java.awt.Color;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Graphics; import java.awt.Graphics;
@@ -40,31 +39,25 @@ import java.awt.image.VolatileImage;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.runelite.api.BufferProvider;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.api.Entity;
import net.runelite.api.MainBufferProvider; import net.runelite.api.MainBufferProvider;
import net.runelite.api.NullItemID; import net.runelite.api.NullItemID;
import net.runelite.api.RenderOverview; import net.runelite.api.RenderOverview;
import net.runelite.api.Skill; import net.runelite.api.Skill;
import net.runelite.api.WorldMapManager; import net.runelite.api.WorldMapManager;
import net.runelite.api.events.BeforeMenuRender;
import net.runelite.api.events.BeforeRender; import net.runelite.api.events.BeforeRender;
import net.runelite.api.events.Event;
import net.runelite.api.events.FakeXpDrop; import net.runelite.api.events.FakeXpDrop;
import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GameStateChanged;
import net.runelite.api.events.GameTick; import net.runelite.api.events.GameTick;
import net.runelite.api.events.ScriptCallbackEvent; import net.runelite.api.events.ScriptCallbackEvent;
import net.runelite.api.hooks.Callbacks; import net.runelite.api.hooks.Callbacks;
import net.runelite.api.hooks.DrawCallbacks;
import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.Widget;
import static net.runelite.api.widgets.WidgetInfo.WORLD_MAP_VIEW; import static net.runelite.api.widgets.WidgetInfo.WORLD_MAP_VIEW;
import net.runelite.api.widgets.WidgetItem; import net.runelite.api.widgets.WidgetItem;
import net.runelite.client.Notifier; import net.runelite.client.Notifier;
import net.runelite.client.RuneLite;
import net.runelite.client.chat.ChatMessageManager; import net.runelite.client.chat.ChatMessageManager;
import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.EventBus;
import net.runelite.client.events.DrawFinished; import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.input.KeyManager; import net.runelite.client.input.KeyManager;
import net.runelite.client.input.MouseManager; import net.runelite.client.input.MouseManager;
import net.runelite.client.task.Scheduler; import net.runelite.client.task.Scheduler;
@@ -75,7 +68,6 @@ import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.ui.overlay.OverlayRenderer; import net.runelite.client.ui.overlay.OverlayRenderer;
import net.runelite.client.ui.overlay.infobox.InfoBoxManager; import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
import net.runelite.client.util.DeferredEventBus; import net.runelite.client.util.DeferredEventBus;
import net.runelite.client.util.ImageUtil;
import net.runelite.client.util.RSTimeUnit; import net.runelite.client.util.RSTimeUnit;
/** /**
@@ -89,19 +81,17 @@ public class Hooks implements Callbacks
{ {
private static final long CHECK = RSTimeUnit.GAME_TICKS.getDuration().toNanos(); // ns - how often to run checks private static final long CHECK = RSTimeUnit.GAME_TICKS.getDuration().toNanos(); // ns - how often to run checks
private static final Injector injector = RuneLite.getInjector(); private static final GameTick GAME_TICK = new GameTick();
private static final Client client = injector.getInstance(Client.class); private static final BeforeRender BEFORE_RENDER = new BeforeRender();
public static final OverlayRenderer renderer = injector.getInstance(OverlayRenderer.class);
private static final OverlayManager overlayManager = injector.getInstance(OverlayManager.class);
private static final GameTick GAME_TICK = GameTick.INSTANCE; @Inject
private static final BeforeRender BEFORE_RENDER = BeforeRender.INSTANCE; private Client client;
private static final DrawFinished drawFinishedEvent = new DrawFinished();
private int mouseX = 0; @Inject
private int mouseY = 0; private OverlayRenderer renderer;
private final Image cursor = ImageUtil.getResourceStreamFromClass(Hooks.class, "cursor.png");
@Inject
private OverlayManager overlayManager;
@Inject @Inject
private EventBus eventBus; private EventBus eventBus;
@@ -145,7 +135,7 @@ public class Hooks implements Callbacks
private boolean shouldProcessGameTick; private boolean shouldProcessGameTick;
private static MainBufferProvider lastMainBufferProvider; private static MainBufferProvider lastMainBufferProvider;
public static Graphics2D lastGraphics; private static Graphics2D lastGraphics;
/** /**
* Get the Graphics2D for the MainBufferProvider image * Get the Graphics2D for the MainBufferProvider image
@@ -170,15 +160,15 @@ public class Hooks implements Callbacks
} }
@Override @Override
public <T extends Event, E extends T> void post(Class<T> eventClass, E event) public void post(Object event)
{ {
eventBus.post(eventClass, event); eventBus.post(event);
} }
@Override @Override
public <T extends Event, E extends T> void postDeferred(Class<T> eventClass, E event) public void postDeferred(Object event)
{ {
deferredEventBus.post(eventClass, event); deferredEventBus.post(event);
} }
@Override @Override
@@ -190,13 +180,13 @@ public class Hooks implements Callbacks
deferredEventBus.replay(); deferredEventBus.replay();
eventBus.post(GameTick.class, GameTick.INSTANCE); eventBus.post(GAME_TICK);
int tick = client.getTickCount(); int tick = client.getTickCount();
client.setTickCount(tick + 1); client.setTickCount(tick + 1);
} }
eventBus.post(BeforeRender.class, BeforeRender.INSTANCE); eventBus.post(BEFORE_RENDER);
clientThread.invoke(); clientThread.invoke();
@@ -293,16 +283,12 @@ public class Hooks implements Callbacks
@Override @Override
public MouseEvent mouseDragged(MouseEvent mouseEvent) public MouseEvent mouseDragged(MouseEvent mouseEvent)
{ {
mouseX = mouseEvent.getX();
mouseY = mouseEvent.getY();
return mouseManager.processMouseDragged(mouseEvent); return mouseManager.processMouseDragged(mouseEvent);
} }
@Override @Override
public MouseEvent mouseMoved(MouseEvent mouseEvent) public MouseEvent mouseMoved(MouseEvent mouseEvent)
{ {
mouseX = mouseEvent.getX();
mouseY = mouseEvent.getY();
return mouseManager.processMouseMoved(mouseEvent); return mouseManager.processMouseMoved(mouseEvent);
} }
@@ -405,22 +391,6 @@ public class Hooks implements Callbacks
finalImage = image; finalImage = image;
} }
if (client.isMirrored())
{
drawFinishedEvent.image = copy(finalImage);
drawFinishedEvent.image.getGraphics().drawImage(cursor, mouseX, mouseY, null);
eventBus.post(DrawFinished.class, drawFinishedEvent);
}
try
{
renderer.render((Graphics2D)finalImage.getGraphics(), OverlayLayer.AFTER_MIRROR);
}
catch (Exception ex)
{
log.warn("Error during post-mirror rendering", ex);
}
// Draw the image onto the game canvas // Draw the image onto the game canvas
graphics.drawImage(finalImage, 0, 0, client.getCanvas()); graphics.drawImage(finalImage, 0, 0, client.getCanvas());
@@ -431,6 +401,8 @@ public class Hooks implements Callbacks
/** /**
* Copy an image * Copy an image
* @param src
* @return
*/ */
private static Image copy(Image src) private static Image copy(Image src)
{ {
@@ -475,7 +447,8 @@ public class Hooks implements Callbacks
} }
} }
public static void drawAfterWidgets() @Override
public void drawAfterWidgets()
{ {
MainBufferProvider bufferProvider = (MainBufferProvider) client.getBufferProvider(); MainBufferProvider bufferProvider = (MainBufferProvider) client.getBufferProvider();
Graphics2D graphics2d = getGraphics(bufferProvider); Graphics2D graphics2d = getGraphics(bufferProvider);
@@ -495,6 +468,7 @@ public class Hooks implements Callbacks
overlayManager.getItemWidgets().clear(); overlayManager.getItemWidgets().clear();
} }
@Subscribe
public void onGameStateChanged(GameStateChanged gameStateChanged) public void onGameStateChanged(GameStateChanged gameStateChanged)
{ {
switch (gameStateChanged.getGameState()) switch (gameStateChanged.getGameState())
@@ -530,38 +504,6 @@ public class Hooks implements Callbacks
deferredEventBus.replay(); deferredEventBus.replay();
} }
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(entity, orientation, pitchSin, pitchCos, yawSin, yawCos, x, y, z, hash);
}
else
{
entity.draw(orientation, pitchSin, pitchCos, yawSin, yawCos, x, y, z, hash);
}
}
public static void clearColorBuffer(int x, int y, int width, int height, int color)
{
BufferProvider bp = client.getBufferProvider();
int canvasWidth = bp.getWidth();
int[] pixels = bp.getPixels();
int pixelPos = y * canvasWidth + x;
int pixelJump = canvasWidth - width;
for (int cy = y; cy < y + height; cy++)
{
for (int cx = x; cx < x + width; cx++)
{
pixels[pixelPos++] = 0;
}
pixelPos += pixelJump;
}
}
@Override @Override
public void drawItem(int itemId, WidgetItem widgetItem) public void drawItem(int itemId, WidgetItem widgetItem)
{ {
@@ -572,13 +514,7 @@ public class Hooks implements Callbacks
} }
} }
public static boolean drawMenu() @Subscribe
{
BeforeMenuRender event = new BeforeMenuRender();
client.getCallbacks().post(BeforeMenuRender.class, event);
return event.isConsumed();
}
public void onScriptCallbackEvent(ScriptCallbackEvent scriptCallbackEvent) public void onScriptCallbackEvent(ScriptCallbackEvent scriptCallbackEvent)
{ {
if (!scriptCallbackEvent.getEventName().equals("fakeXpDrop")) if (!scriptCallbackEvent.getEventName().equals("fakeXpDrop"))
@@ -597,6 +533,6 @@ public class Hooks implements Callbacks
skill, skill,
xp xp
); );
eventBus.post(FakeXpDrop.class, fakeXpDrop); eventBus.post(fakeXpDrop);
} }
} }

View File

@@ -41,21 +41,20 @@ import net.runelite.client.events.ChatboxInput;
import net.runelite.client.events.PrivateMessageInput; import net.runelite.client.events.PrivateMessageInput;
@Singleton @Singleton
public class ChatCommandManager public class ChatCommandManager implements ChatboxInputListener
{ {
private final Map<String, ChatCommand> commands = new ConcurrentHashMap<>(); private final Map<String, ChatCommand> commands = new ConcurrentHashMap<>();
private final Client client; private final Client client;
private final ScheduledExecutorService scheduledExecutorService; private final ScheduledExecutorService scheduledExecutorService;
@Inject @Inject
private ChatCommandManager(EventBus eventBus, Client client, ScheduledExecutorService scheduledExecutorService) private ChatCommandManager(EventBus eventBus, CommandManager commandManager, Client client, ScheduledExecutorService scheduledExecutorService)
{ {
this.client = client; this.client = client;
this.scheduledExecutorService = scheduledExecutorService; this.scheduledExecutorService = scheduledExecutorService;
eventBus.register(this);
eventBus.subscribe(ChatboxInput.class, this, this::onChatboxInput); commandManager.register(this);
eventBus.subscribe(PrivateMessageInput.class, this, this::onPrivateMessageInput);
eventBus.subscribe(ChatMessage.class, this, this::onChatMessage);
} }
public void registerCommand(String command, BiConsumer<ChatMessage, String> execute) public void registerCommand(String command, BiConsumer<ChatMessage, String> execute)
@@ -83,7 +82,8 @@ public class ChatCommandManager
commands.remove(command.toLowerCase()); commands.remove(command.toLowerCase());
} }
private void onChatMessage(ChatMessage chatMessage) @Subscribe
public void onChatMessage(ChatMessage chatMessage)
{ {
if (client.getGameState() != GameState.LOGGED_IN) if (client.getGameState() != GameState.LOGGED_IN)
{ {
@@ -106,6 +106,11 @@ public class ChatCommandManager
String message = chatMessage.getMessage(); String message = chatMessage.getMessage();
String command = extractCommand(message); String command = extractCommand(message);
if (command == null)
{
return;
}
ChatCommand chatCommand = commands.get(command.toLowerCase()); ChatCommand chatCommand = commands.get(command.toLowerCase());
if (chatCommand == null) if (chatCommand == null)
{ {
@@ -122,8 +127,8 @@ public class ChatCommandManager
} }
} }
@Subscribe // just for show @Override
private void onChatboxInput(ChatboxInput chatboxInput) public boolean onChatboxInput(ChatboxInput chatboxInput)
{ {
String message = chatboxInput.getValue(); String message = chatboxInput.getValue();
if (message.startsWith("/")) if (message.startsWith("/"))
@@ -131,30 +136,51 @@ public class ChatCommandManager
message = message.substring(1); // friends chat input message = message.substring(1); // friends chat input
} }
onInput(chatboxInput, message);
}
@Subscribe // just for show
private void onPrivateMessageInput(PrivateMessageInput input)
{
onInput(input, input.getMessage());
}
private void onInput(ChatInput chatInput, String message)
{
String command = extractCommand(message); String command = extractCommand(message);
if (command == null)
{
return false;
}
ChatCommand chatCommand = commands.get(command.toLowerCase()); ChatCommand chatCommand = commands.get(command.toLowerCase());
if (chatCommand == null) if (chatCommand == null)
{ {
return; return false;
} }
BiPredicate<ChatInput, String> input = chatCommand.getInput(); BiPredicate<ChatInput, String> input = chatCommand.getInput();
if (input != null && input.test(chatInput, message)) if (input == null)
{ {
chatInput.setStop(); return false;
} }
return input.test(chatboxInput, message);
}
@Override
public boolean onPrivateMessageInput(PrivateMessageInput privateMessageInput)
{
final String message = privateMessageInput.getMessage();
String command = extractCommand(message);
if (command == null)
{
return false;
}
ChatCommand chatCommand = commands.get(command.toLowerCase());
if (chatCommand == null)
{
return false;
}
BiPredicate<ChatInput, String> input = chatCommand.getInput();
if (input == null)
{
return false;
}
return input.test(privateMessageInput, message);
} }
private static String extractCommand(String message) private static String extractCommand(String message)

View File

@@ -25,8 +25,8 @@
package net.runelite.client.chat; package net.runelite.client.chat;
import java.awt.Color; import java.awt.Color;
import net.runelite.api.util.Text;
import net.runelite.client.util.ColorUtil; import net.runelite.client.util.ColorUtil;
import net.runelite.client.util.Text;
public class ChatMessageBuilder public class ChatMessageBuilder
{ {

View File

@@ -24,8 +24,10 @@
*/ */
package net.runelite.client.chat; package net.runelite.client.chat;
import com.google.common.base.MoreObjects;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.common.collect.HashMultimap; import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import java.awt.Color; import java.awt.Color;
import java.util.Arrays; import java.util.Arrays;
@@ -44,20 +46,20 @@ import net.runelite.api.MessageNode;
import net.runelite.api.Player; import net.runelite.api.Player;
import net.runelite.api.Varbits; import net.runelite.api.Varbits;
import net.runelite.api.events.ChatMessage; import net.runelite.api.events.ChatMessage;
import net.runelite.client.events.ConfigChanged;
import net.runelite.api.events.ResizeableChanged; import net.runelite.api.events.ResizeableChanged;
import net.runelite.api.events.ScriptCallbackEvent; import net.runelite.api.events.ScriptCallbackEvent;
import net.runelite.api.events.VarbitChanged; import net.runelite.api.events.VarbitChanged;
import net.runelite.client.callback.ClientThread; import net.runelite.client.callback.ClientThread;
import net.runelite.client.config.ChatColorConfig; import net.runelite.client.config.ChatColorConfig;
import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.events.ConfigChanged;
import net.runelite.client.ui.JagexColors; import net.runelite.client.ui.JagexColors;
import net.runelite.client.util.ColorUtil; import net.runelite.client.util.ColorUtil;
@Singleton @Singleton
public class ChatMessageManager public class ChatMessageManager
{ {
private static final Set<Integer> TUTORIAL_ISLAND_REGIONS = Set.of(12336, 12335, 12592, 12080, 12079, 12436); private static final Set<Integer> TUTORIAL_ISLAND_REGIONS = ImmutableSet.of(12336, 12335, 12592, 12080, 12079, 12436);
private final Multimap<ChatMessageType, ChatColor> colorCache = HashMultimap.create(); private final Multimap<ChatMessageType, ChatColor> colorCache = HashMultimap.create();
private final Client client; private final Client client;
@@ -68,23 +70,17 @@ public class ChatMessageManager
@Inject @Inject
private ChatMessageManager( private ChatMessageManager(
final Client client, Client client,
final ChatColorConfig chatColorConfig, ChatColorConfig chatColorConfig,
final ClientThread clientThread, ClientThread clientThread)
final EventBus eventbus)
{ {
this.client = client; this.client = client;
this.chatColorConfig = chatColorConfig; this.chatColorConfig = chatColorConfig;
this.clientThread = clientThread; 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);
} }
private void onVarbitChanged(VarbitChanged event) @Subscribe
public void onVarbitChanged(VarbitChanged event)
{ {
int setting = client.getVar(Varbits.TRANSPARENT_CHATBOX); int setting = client.getVar(Varbits.TRANSPARENT_CHATBOX);
@@ -95,12 +91,14 @@ public class ChatMessageManager
} }
} }
private void onResizeableChanged(ResizeableChanged event) @Subscribe
public void onResizeableChanged(ResizeableChanged event)
{ {
refreshAll(); refreshAll();
} }
private void onConfigChanged(ConfigChanged event) @Subscribe
public void onConfigChanged(ConfigChanged event)
{ {
if (event.getGroup().equals("textrecolor")) if (event.getGroup().equals("textrecolor"))
{ {
@@ -109,7 +107,8 @@ public class ChatMessageManager
} }
} }
void onChatMessage(ChatMessage chatMessage) @Subscribe(priority = -1) // run after all plugins
public void onChatMessage(ChatMessage chatMessage)
{ {
MessageNode messageNode = chatMessage.getMessageNode(); MessageNode messageNode = chatMessage.getMessageNode();
ChatMessageType chatMessageType = chatMessage.getType(); ChatMessageType chatMessageType = chatMessage.getType();
@@ -174,7 +173,8 @@ public class ChatMessageManager
} }
} }
private void onScriptCallbackEvent(ScriptCallbackEvent scriptCallbackEvent) @Subscribe
public void onScriptCallbackEvent(ScriptCallbackEvent scriptCallbackEvent)
{ {
final String eventName = scriptCallbackEvent.getEventName(); final String eventName = scriptCallbackEvent.getEventName();
@@ -571,17 +571,11 @@ public class ChatMessageManager
return; return;
} }
//guard case for google MoreObjects#firstNonNull
if (message.getValue() == null && message.getRuneLiteFormattedMessage() == null)
{
return;
}
// this updates chat cycle // this updates chat cycle
client.addChatMessage( client.addChatMessage(
message.getType(), message.getType(),
Objects.requireNonNullElse(message.getName(), ""), MoreObjects.firstNonNull(message.getName(), ""),
Objects.requireNonNullElse(message.getValue(), message.getRuneLiteFormattedMessage()), MoreObjects.firstNonNull(message.getValue(), message.getRuneLiteFormattedMessage()),
message.getSender()); message.getSender());
// Get last message from line buffer (the one we just added) // Get last message from line buffer (the one we just added)

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com> * Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -22,25 +22,14 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package net.runelite.client.discord; package net.runelite.client.chat;
/** import net.runelite.client.events.ChatboxInput;
* Discord reply type for request import net.runelite.client.events.PrivateMessageInput;
*/
public enum DiscordReplyType public interface ChatboxInputListener
{ {
/** boolean onChatboxInput(ChatboxInput chatboxInput);
* Used to decline a request
*/
NO,
/** boolean onPrivateMessageInput(PrivateMessageInput privateMessageInput);
* Used to accept a request
*/
YES,
/**
* Currently unused response, treated like NO.
*/
IGNORE
} }

View File

@@ -26,6 +26,8 @@
package net.runelite.client.chat; package net.runelite.client.chat;
import java.util.Arrays; import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -36,6 +38,7 @@ import net.runelite.api.events.CommandExecuted;
import net.runelite.api.events.ScriptCallbackEvent; import net.runelite.api.events.ScriptCallbackEvent;
import net.runelite.client.callback.ClientThread; import net.runelite.client.callback.ClientThread;
import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.EventBus;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.events.ChatboxInput; import net.runelite.client.events.ChatboxInput;
import net.runelite.client.events.PrivateMessageInput; import net.runelite.client.events.PrivateMessageInput;
@@ -52,20 +55,27 @@ public class CommandManager
private final ClientThread clientThread; private final ClientThread clientThread;
private boolean sending; private boolean sending;
private final List<ChatboxInputListener> chatboxInputListenerList = new CopyOnWriteArrayList<>();
@Inject @Inject
private CommandManager( private CommandManager(Client client, EventBus eventBus, ClientThread clientThread)
final Client client,
final EventBus eventBus,
final ClientThread clientThread
)
{ {
this.client = client; this.client = client;
this.eventBus = eventBus; this.eventBus = eventBus;
this.clientThread = clientThread; this.clientThread = clientThread;
eventBus.subscribe(ScriptCallbackEvent.class, this, this::onScriptCallbackEvent);
} }
public void register(ChatboxInputListener chatboxInputListener)
{
chatboxInputListenerList.add(chatboxInputListener);
}
public void unregister(ChatboxInputListener chatboxInputListener)
{
chatboxInputListenerList.remove(chatboxInputListener);
}
@Subscribe
private void onScriptCallbackEvent(ScriptCallbackEvent event) private void onScriptCallbackEvent(ScriptCallbackEvent event)
{ {
if (sending) if (sending)
@@ -105,7 +115,7 @@ public class CommandManager
String[] args = Arrays.copyOfRange(split, 1, split.length); String[] args = Arrays.copyOfRange(split, 1, split.length);
CommandExecuted commandExecuted = new CommandExecuted(command, args); CommandExecuted commandExecuted = new CommandExecuted(command, args);
eventBus.post(CommandExecuted.class, commandExecuted); eventBus.post(commandExecuted);
} }
private void handleInput(ScriptCallbackEvent event) private void handleInput(ScriptCallbackEvent event)
@@ -134,10 +144,13 @@ public class CommandManager
clientThread.invoke(() -> sendChatboxInput(chatType, typedText)); clientThread.invoke(() -> sendChatboxInput(chatType, typedText));
} }
}; };
boolean stop = false;
for (ChatboxInputListener chatboxInputListener : chatboxInputListenerList)
{
stop |= chatboxInputListener.onChatboxInput(chatboxInput);
}
eventBus.post(ChatboxInput.class, chatboxInput); if (stop)
if (chatboxInput.isStop())
{ {
// input was blocked. // input was blocked.
stringStack[stringStackCount - 1] = ""; // prevent script from sending stringStack[stringStackCount - 1] = ""; // prevent script from sending
@@ -171,9 +184,13 @@ public class CommandManager
} }
}; };
eventBus.post(PrivateMessageInput.class, privateMessageInput); boolean stop = false;
for (ChatboxInputListener chatboxInputListener : chatboxInputListenerList)
{
stop |= chatboxInputListener.onPrivateMessageInput(privateMessageInput);
}
if (privateMessageInput.isStop()) if (stop)
{ {
intStack[intStackCount - 1] = 1; intStack[intStackCount - 1] = 1;
client.setStringStackSize(stringStackCount - 2); // remove both target and message client.setStringStackSize(stringStackCount - 2); // remove both target and message

View File

@@ -37,4 +37,6 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD) @Target(ElementType.METHOD)
@Documented @Documented
public @interface Alpha {} public @interface Alpha
{
}

View File

@@ -1,3 +0,0 @@
package net.runelite.client.config;
public class Button {}

View File

@@ -30,34 +30,28 @@ import net.runelite.client.ui.JagexColors;
@ConfigGroup("textrecolor") @ConfigGroup("textrecolor")
public interface ChatColorConfig extends Config public interface ChatColorConfig extends Config
{ {
@ConfigTitleSection( @ConfigSection(
keyName = "opaqueTitle",
name = "Opaque", name = "Opaque",
description = "", description = "The options that control the colours for the Opaque Chatbox",
position = 1 position = 0,
closedByDefault = true
) )
default Title opaqueTitle() String opaqueSection = "opaqueSection";
{
return new Title();
}
@ConfigTitleSection( @ConfigSection(
keyName = "transparentTitle",
name = "Transparent", name = "Transparent",
description = "", description = "The options that control the colours for the Transparent Chatbox",
position = 1 position = 50,
closedByDefault = true
) )
default Title transparentTitle() String transparentSection = "transparentSection";
{
return new Title();
}
@ConfigItem( @ConfigItem(
position = 1, position = 1,
keyName = "opaquePublicChat", keyName = "opaquePublicChat",
name = "Public chat", name = "Public chat",
description = "Color of Public chat", description = "Color of Public chat",
titleSection = "opaqueTitle" section = opaqueSection
) )
Color opaquePublicChat(); Color opaquePublicChat();
@@ -66,7 +60,7 @@ public interface ChatColorConfig extends Config
keyName = "opaquePublicChatHighlight", keyName = "opaquePublicChatHighlight",
name = "Public chat highlight", name = "Public chat highlight",
description = "Color of highlights in Public chat", description = "Color of highlights in Public chat",
titleSection = "opaqueTitle" section = opaqueSection
) )
default Color opaquePublicChatHighlight() default Color opaquePublicChatHighlight()
{ {
@@ -78,7 +72,7 @@ public interface ChatColorConfig extends Config
keyName = "opaquePrivateMessageSent", keyName = "opaquePrivateMessageSent",
name = "Sent private messages", name = "Sent private messages",
description = "Color of Private messages you've sent", description = "Color of Private messages you've sent",
titleSection = "opaqueTitle" section = opaqueSection
) )
Color opaquePrivateMessageSent(); Color opaquePrivateMessageSent();
@@ -87,7 +81,7 @@ public interface ChatColorConfig extends Config
keyName = "opaquePrivateMessageSentHighlight", keyName = "opaquePrivateMessageSentHighlight",
name = "Sent private messages highlight", name = "Sent private messages highlight",
description = "Color of highlights in Private messages you've sent", description = "Color of highlights in Private messages you've sent",
titleSection = "opaqueTitle" section = opaqueSection
) )
default Color opaquePrivateMessageSentHighlight() default Color opaquePrivateMessageSentHighlight()
{ {
@@ -99,7 +93,7 @@ public interface ChatColorConfig extends Config
keyName = "opaquePrivateMessageReceived", keyName = "opaquePrivateMessageReceived",
name = "Received private messages", name = "Received private messages",
description = "Color of Private messages you've received", description = "Color of Private messages you've received",
titleSection = "opaqueTitle" section = opaqueSection
) )
Color opaquePrivateMessageReceived(); Color opaquePrivateMessageReceived();
@@ -108,7 +102,7 @@ public interface ChatColorConfig extends Config
keyName = "opaquePrivateMessageReceivedHighlight", keyName = "opaquePrivateMessageReceivedHighlight",
name = "Received private messages highlight", name = "Received private messages highlight",
description = "Color of highlights in Private messages you've received", description = "Color of highlights in Private messages you've received",
titleSection = "opaqueTitle" section = opaqueSection
) )
default Color opaquePrivateMessageReceivedHighlight() default Color opaquePrivateMessageReceivedHighlight()
{ {
@@ -120,7 +114,7 @@ public interface ChatColorConfig extends Config
keyName = "opaqueClanChatInfo", keyName = "opaqueClanChatInfo",
name = "Friends chat info", name = "Friends chat info",
description = "Friends Chat Information (eg. when joining a channel)", description = "Friends Chat Information (eg. when joining a channel)",
titleSection = "opaqueTitle" section = opaqueSection
) )
default Color opaqueFriendsChatInfo() default Color opaqueFriendsChatInfo()
{ {
@@ -132,7 +126,7 @@ public interface ChatColorConfig extends Config
keyName = "opaqueClanChatInfoHighlight", keyName = "opaqueClanChatInfoHighlight",
name = "Friends chat info highlight", name = "Friends chat info highlight",
description = "Friends Chat Information highlight (used for the Raids plugin)", description = "Friends Chat Information highlight (used for the Raids plugin)",
titleSection = "opaqueTitle" section = opaqueSection
) )
default Color opaqueFriendsChatInfoHighlight() default Color opaqueFriendsChatInfoHighlight()
{ {
@@ -144,7 +138,7 @@ public interface ChatColorConfig extends Config
keyName = "opaqueClanChatMessage", keyName = "opaqueClanChatMessage",
name = "Friends chat message", name = "Friends chat message",
description = "Color of Friends chat messages", description = "Color of Friends chat messages",
titleSection = "opaqueTitle" section = opaqueSection
) )
Color opaqueFriendsChatMessage(); Color opaqueFriendsChatMessage();
@@ -153,7 +147,7 @@ public interface ChatColorConfig extends Config
keyName = "opaqueClanChatMessageHighlight", keyName = "opaqueClanChatMessageHighlight",
name = "Friends chat message highlight", name = "Friends chat message highlight",
description = "Color of highlights in Friends Chat messages", description = "Color of highlights in Friends Chat messages",
titleSection = "opaqueTitle" section = opaqueSection
) )
default Color opaqueFriendsChatMessageHighlight() default Color opaqueFriendsChatMessageHighlight()
{ {
@@ -165,7 +159,7 @@ public interface ChatColorConfig extends Config
keyName = "opaqueAutochatMessage", keyName = "opaqueAutochatMessage",
name = "Autochat", name = "Autochat",
description = "Color of Autochat messages", description = "Color of Autochat messages",
titleSection = "opaqueTitle" section = opaqueSection
) )
Color opaqueAutochatMessage(); Color opaqueAutochatMessage();
@@ -174,7 +168,7 @@ public interface ChatColorConfig extends Config
keyName = "opaqueAutochatMessageHighlight", keyName = "opaqueAutochatMessageHighlight",
name = "Autochat highlight", name = "Autochat highlight",
description = "Color of highlights in Autochat messages", description = "Color of highlights in Autochat messages",
titleSection = "opaqueTitle" section = opaqueSection
) )
Color opaqueAutochatMessageHighlight(); Color opaqueAutochatMessageHighlight();
@@ -183,7 +177,7 @@ public interface ChatColorConfig extends Config
keyName = "opaqueTradeChatMessage", keyName = "opaqueTradeChatMessage",
name = "Trade chat", name = "Trade chat",
description = "Color of Trade Chat Messages", description = "Color of Trade Chat Messages",
titleSection = "opaqueTitle" section = opaqueSection
) )
Color opaqueTradeChatMessage(); Color opaqueTradeChatMessage();
@@ -192,7 +186,7 @@ public interface ChatColorConfig extends Config
keyName = "opaqueTradeChatMessageHighlight", keyName = "opaqueTradeChatMessageHighlight",
name = "Trade chat highlight", name = "Trade chat highlight",
description = "Color of highlights in Trade Chat Messages", description = "Color of highlights in Trade Chat Messages",
titleSection = "opaqueTitle" section = opaqueSection
) )
Color opaqueTradeChatMessageHighlight(); Color opaqueTradeChatMessageHighlight();
@@ -201,7 +195,7 @@ public interface ChatColorConfig extends Config
keyName = "opaqueServerMessage", keyName = "opaqueServerMessage",
name = "Server message", name = "Server message",
description = "Color of Server Messages (eg. 'Welcome to RuneScape')", description = "Color of Server Messages (eg. 'Welcome to RuneScape')",
titleSection = "opaqueTitle" section = opaqueSection
) )
Color opaqueServerMessage(); Color opaqueServerMessage();
@@ -210,7 +204,7 @@ public interface ChatColorConfig extends Config
keyName = "opaqueServerMessageHighlight", keyName = "opaqueServerMessageHighlight",
name = "Server message highlight", name = "Server message highlight",
description = "Color of highlights in Server Messages", description = "Color of highlights in Server Messages",
titleSection = "opaqueTitle" section = opaqueSection
) )
Color opaqueServerMessageHighlight(); Color opaqueServerMessageHighlight();
@@ -219,7 +213,7 @@ public interface ChatColorConfig extends Config
keyName = "opaqueGameMessage", keyName = "opaqueGameMessage",
name = "Game message", name = "Game message",
description = "Color of Game Messages", description = "Color of Game Messages",
titleSection = "opaqueTitle" section = opaqueSection
) )
Color opaqueGameMessage(); Color opaqueGameMessage();
@@ -228,7 +222,7 @@ public interface ChatColorConfig extends Config
keyName = "opaqueGameMessageHighlight", keyName = "opaqueGameMessageHighlight",
name = "Game message highlight", name = "Game message highlight",
description = "Color of highlights in Game Messages", description = "Color of highlights in Game Messages",
titleSection = "opaqueTitle" section = opaqueSection
) )
default Color opaqueGameMessageHighlight() default Color opaqueGameMessageHighlight()
{ {
@@ -240,7 +234,7 @@ public interface ChatColorConfig extends Config
keyName = "opaqueExamine", keyName = "opaqueExamine",
name = "Examine", name = "Examine",
description = "Color of Examine Text", description = "Color of Examine Text",
titleSection = "opaqueTitle" section = opaqueSection
) )
Color opaqueExamine(); Color opaqueExamine();
@@ -249,7 +243,7 @@ public interface ChatColorConfig extends Config
keyName = "opaqueExamineHighlight", keyName = "opaqueExamineHighlight",
name = "Examine highlight", name = "Examine highlight",
description = "Color of highlights in Examine Text", description = "Color of highlights in Examine Text",
titleSection = "opaqueTitle" section = opaqueSection
) )
default Color opaqueExamineHighlight() default Color opaqueExamineHighlight()
{ {
@@ -261,7 +255,7 @@ public interface ChatColorConfig extends Config
keyName = "opaqueFiltered", keyName = "opaqueFiltered",
name = "Filtered", name = "Filtered",
description = "Color of Filtered Text (messages that aren't shown when Game messages are filtered)", description = "Color of Filtered Text (messages that aren't shown when Game messages are filtered)",
titleSection = "opaqueTitle" section = opaqueSection
) )
Color opaqueFiltered(); Color opaqueFiltered();
@@ -270,7 +264,7 @@ public interface ChatColorConfig extends Config
keyName = "opaqueFilteredHighlight", keyName = "opaqueFilteredHighlight",
name = "Filtered highlight", name = "Filtered highlight",
description = "Color of highlights in Filtered Text", description = "Color of highlights in Filtered Text",
titleSection = "opaqueTitle" section = opaqueSection
) )
Color opaqueFilteredHighlight(); Color opaqueFilteredHighlight();
@@ -279,7 +273,7 @@ public interface ChatColorConfig extends Config
keyName = "opaqueUsername", keyName = "opaqueUsername",
name = "Usernames", name = "Usernames",
description = "Color of Usernames", description = "Color of Usernames",
titleSection = "opaqueTitle" section = opaqueSection
) )
Color opaqueUsername(); Color opaqueUsername();
@@ -288,7 +282,7 @@ public interface ChatColorConfig extends Config
keyName = "opaquePrivateUsernames", keyName = "opaquePrivateUsernames",
name = "Private chat usernames", name = "Private chat usernames",
description = "Color of Usernames in Private Chat", description = "Color of Usernames in Private Chat",
titleSection = "opaqueTitle" section = opaqueSection
) )
Color opaquePrivateUsernames(); Color opaquePrivateUsernames();
@@ -297,7 +291,7 @@ public interface ChatColorConfig extends Config
keyName = "opaqueClanChannelName", keyName = "opaqueClanChannelName",
name = "Friends chat channel name", name = "Friends chat channel name",
description = "Color of Friends chat channel name", description = "Color of Friends chat channel name",
titleSection = "opaqueTitle" section = opaqueSection
) )
Color opaqueFriendsChatChannelName(); Color opaqueFriendsChatChannelName();
@@ -306,7 +300,7 @@ public interface ChatColorConfig extends Config
keyName = "opaqueClanUsernames", keyName = "opaqueClanUsernames",
name = "Friends chat usernames", name = "Friends chat usernames",
description = "Color of usernames in Friends chat", description = "Color of usernames in Friends chat",
titleSection = "opaqueTitle" section = opaqueSection
) )
Color opaqueFriendsChatUsernames(); Color opaqueFriendsChatUsernames();
@@ -315,7 +309,7 @@ public interface ChatColorConfig extends Config
keyName = "opaquePublicFriendUsernames", keyName = "opaquePublicFriendUsernames",
name = "Public friend usernames", name = "Public friend usernames",
description = "Color of Friend Usernames in Public Chat", description = "Color of Friend Usernames in Public Chat",
titleSection = "opaqueTitle" section = opaqueSection
) )
Color opaquePublicFriendUsernames(); Color opaquePublicFriendUsernames();
@@ -324,7 +318,7 @@ public interface ChatColorConfig extends Config
keyName = "transparentPublicChat", keyName = "transparentPublicChat",
name = "Public chat (transparent)", name = "Public chat (transparent)",
description = "Color of Public chat (transparent)", description = "Color of Public chat (transparent)",
titleSection = "transparentTitle" section = transparentSection
) )
Color transparentPublicChat(); Color transparentPublicChat();
@@ -333,7 +327,7 @@ public interface ChatColorConfig extends Config
keyName = "transparentPublicChatHighlight", keyName = "transparentPublicChatHighlight",
name = "Public chat highlight (transparent)", name = "Public chat highlight (transparent)",
description = "Color of highlights in Public chat (transparent)", description = "Color of highlights in Public chat (transparent)",
titleSection = "transparentTitle" section = transparentSection
) )
default Color transparentPublicChatHighlight() default Color transparentPublicChatHighlight()
{ {
@@ -345,7 +339,7 @@ public interface ChatColorConfig extends Config
keyName = "transparentPrivateMessageSent", keyName = "transparentPrivateMessageSent",
name = "Sent private messages (transparent)", name = "Sent private messages (transparent)",
description = "Color of Private messages you've sent (transparent)", description = "Color of Private messages you've sent (transparent)",
titleSection = "transparentTitle" section = transparentSection
) )
Color transparentPrivateMessageSent(); Color transparentPrivateMessageSent();
@@ -354,7 +348,7 @@ public interface ChatColorConfig extends Config
keyName = "transparentPrivateMessageSentHighlight", keyName = "transparentPrivateMessageSentHighlight",
name = "Sent private messages highlight (transparent)", name = "Sent private messages highlight (transparent)",
description = "Color of highlights in Private messages you've sent (transparent)", description = "Color of highlights in Private messages you've sent (transparent)",
titleSection = "transparentTitle" section = transparentSection
) )
default Color transparentPrivateMessageSentHighlight() default Color transparentPrivateMessageSentHighlight()
{ {
@@ -366,7 +360,7 @@ public interface ChatColorConfig extends Config
keyName = "transparentPrivateMessageReceived", keyName = "transparentPrivateMessageReceived",
name = "Received private messages (transparent)", name = "Received private messages (transparent)",
description = "Color of Private messages you've received (transparent)", description = "Color of Private messages you've received (transparent)",
titleSection = "transparentTitle" section = transparentSection
) )
Color transparentPrivateMessageReceived(); Color transparentPrivateMessageReceived();
@@ -375,7 +369,7 @@ public interface ChatColorConfig extends Config
keyName = "transparentPrivateMessageReceivedHighlight", keyName = "transparentPrivateMessageReceivedHighlight",
name = "Received private messages highlight (transparent)", name = "Received private messages highlight (transparent)",
description = "Color of highlights in Private messages you've received (transparent)", description = "Color of highlights in Private messages you've received (transparent)",
titleSection = "transparentTitle" section = transparentSection
) )
default Color transparentPrivateMessageReceivedHighlight() default Color transparentPrivateMessageReceivedHighlight()
{ {
@@ -387,7 +381,7 @@ public interface ChatColorConfig extends Config
keyName = "transparentClanChatInfo", keyName = "transparentClanChatInfo",
name = "Friends chat info (transparent)", name = "Friends chat info (transparent)",
description = "Friends chat information (eg. when joining a channel) (transparent)", description = "Friends chat information (eg. when joining a channel) (transparent)",
titleSection = "transparentTitle" section = transparentSection
) )
default Color transparentFriendsChatInfo() default Color transparentFriendsChatInfo()
{ {
@@ -399,7 +393,7 @@ public interface ChatColorConfig extends Config
keyName = "transparentClanChatInfoHighlight", keyName = "transparentClanChatInfoHighlight",
name = "Friends chat info highlight (transparent)", name = "Friends chat info highlight (transparent)",
description = "Friends chat information highlight (used for the Raids plugin) (transparent)", description = "Friends chat information highlight (used for the Raids plugin) (transparent)",
titleSection = "transparentTitle" section = transparentSection
) )
default Color transparentFriendsChatInfoHighlight() default Color transparentFriendsChatInfoHighlight()
{ {
@@ -411,7 +405,7 @@ public interface ChatColorConfig extends Config
keyName = "transparentClanChatMessage", keyName = "transparentClanChatMessage",
name = "Friends chat message (transparent)", name = "Friends chat message (transparent)",
description = "Color of Friends chat messages (transparent)", description = "Color of Friends chat messages (transparent)",
titleSection = "transparentTitle" section = transparentSection
) )
Color transparentFriendsChatMessage(); Color transparentFriendsChatMessage();
@@ -420,7 +414,7 @@ public interface ChatColorConfig extends Config
keyName = "transparentClanChatMessageHighlight", keyName = "transparentClanChatMessageHighlight",
name = "Friends chat message highlight (transparent)", name = "Friends chat message highlight (transparent)",
description = "Color of highlights in Friends chat messages (transparent)", description = "Color of highlights in Friends chat messages (transparent)",
titleSection = "transparentTitle" section = transparentSection
) )
default Color transparentFriendsChatMessageHighlight() default Color transparentFriendsChatMessageHighlight()
{ {
@@ -432,7 +426,7 @@ public interface ChatColorConfig extends Config
keyName = "transparentAutochatMessage", keyName = "transparentAutochatMessage",
name = "Autochat (transparent)", name = "Autochat (transparent)",
description = "Color of Autochat messages (transparent)", description = "Color of Autochat messages (transparent)",
titleSection = "transparentTitle" section = transparentSection
) )
Color transparentAutochatMessage(); Color transparentAutochatMessage();
@@ -441,7 +435,7 @@ public interface ChatColorConfig extends Config
keyName = "transparentAutochatMessageHighlight", keyName = "transparentAutochatMessageHighlight",
name = "Autochat highlight (transparent)", name = "Autochat highlight (transparent)",
description = "Color of highlights in Autochat messages (transparent)", description = "Color of highlights in Autochat messages (transparent)",
titleSection = "transparentTitle" section = transparentSection
) )
Color transparentAutochatMessageHighlight(); Color transparentAutochatMessageHighlight();
@@ -450,7 +444,7 @@ public interface ChatColorConfig extends Config
keyName = "transparentTradeChatMessage", keyName = "transparentTradeChatMessage",
name = "Trade chat (transparent)", name = "Trade chat (transparent)",
description = "Color of Trade Chat Messages (transparent)", description = "Color of Trade Chat Messages (transparent)",
titleSection = "transparentTitle" section = transparentSection
) )
Color transparentTradeChatMessage(); Color transparentTradeChatMessage();
@@ -459,7 +453,7 @@ public interface ChatColorConfig extends Config
keyName = "transparentTradeChatMessageHighlight", keyName = "transparentTradeChatMessageHighlight",
name = "Trade chat highlight (transparent)", name = "Trade chat highlight (transparent)",
description = "Color of highlights in Trade Chat Messages (transparent)", description = "Color of highlights in Trade Chat Messages (transparent)",
titleSection = "transparentTitle" section = transparentSection
) )
Color transparentTradeChatMessageHighlight(); Color transparentTradeChatMessageHighlight();
@@ -468,7 +462,7 @@ public interface ChatColorConfig extends Config
keyName = "transparentServerMessage", keyName = "transparentServerMessage",
name = "Server message (transparent)", name = "Server message (transparent)",
description = "Color of Server Messages (eg. 'Welcome to RuneScape') (transparent)", description = "Color of Server Messages (eg. 'Welcome to RuneScape') (transparent)",
titleSection = "transparentTitle" section = transparentSection
) )
Color transparentServerMessage(); Color transparentServerMessage();
@@ -477,7 +471,7 @@ public interface ChatColorConfig extends Config
keyName = "transparentServerMessageHighlight", keyName = "transparentServerMessageHighlight",
name = "Server message highlight (transparent)", name = "Server message highlight (transparent)",
description = "Color of highlights in Server Messages (transparent)", description = "Color of highlights in Server Messages (transparent)",
titleSection = "transparentTitle" section = transparentSection
) )
Color transparentServerMessageHighlight(); Color transparentServerMessageHighlight();
@@ -486,7 +480,7 @@ public interface ChatColorConfig extends Config
keyName = "transparentGameMessage", keyName = "transparentGameMessage",
name = "Game message (transparent)", name = "Game message (transparent)",
description = "Color of Game Messages (transparent)", description = "Color of Game Messages (transparent)",
titleSection = "transparentTitle" section = transparentSection
) )
Color transparentGameMessage(); Color transparentGameMessage();
@@ -495,7 +489,7 @@ public interface ChatColorConfig extends Config
keyName = "transparentGameMessageHighlight", keyName = "transparentGameMessageHighlight",
name = "Game message highlight (transparent)", name = "Game message highlight (transparent)",
description = "Color of highlights in Game Messages (transparent)", description = "Color of highlights in Game Messages (transparent)",
titleSection = "transparentTitle" section = transparentSection
) )
default Color transparentGameMessageHighlight() default Color transparentGameMessageHighlight()
{ {
@@ -507,7 +501,7 @@ public interface ChatColorConfig extends Config
keyName = "transparentExamine", keyName = "transparentExamine",
name = "Examine (transparent)", name = "Examine (transparent)",
description = "Color of Examine Text (transparent)", description = "Color of Examine Text (transparent)",
titleSection = "transparentTitle" section = transparentSection
) )
Color transparentExamine(); Color transparentExamine();
@@ -516,7 +510,7 @@ public interface ChatColorConfig extends Config
keyName = "transparentExamineHighlight", keyName = "transparentExamineHighlight",
name = "Examine highlight (transparent)", name = "Examine highlight (transparent)",
description = "Color of highlights in Examine Text (transparent)", description = "Color of highlights in Examine Text (transparent)",
titleSection = "transparentTitle" section = transparentSection
) )
default Color transparentExamineHighlight() default Color transparentExamineHighlight()
{ {
@@ -528,7 +522,7 @@ public interface ChatColorConfig extends Config
keyName = "transparentFiltered", keyName = "transparentFiltered",
name = "Filtered (transparent)", name = "Filtered (transparent)",
description = "Color of Filtered Text (messages that aren't shown when Game messages are filtered) (transparent)", description = "Color of Filtered Text (messages that aren't shown when Game messages are filtered) (transparent)",
titleSection = "transparentTitle" section = transparentSection
) )
Color transparentFiltered(); Color transparentFiltered();
@@ -537,7 +531,7 @@ public interface ChatColorConfig extends Config
keyName = "transparentFilteredHighlight", keyName = "transparentFilteredHighlight",
name = "Filtered highlight (transparent)", name = "Filtered highlight (transparent)",
description = "Color of highlights in Filtered Text (transparent)", description = "Color of highlights in Filtered Text (transparent)",
titleSection = "transparentTitle" section = transparentSection
) )
Color transparentFilteredHighlight(); Color transparentFilteredHighlight();
@@ -546,7 +540,7 @@ public interface ChatColorConfig extends Config
keyName = "transparentUsername", keyName = "transparentUsername",
name = "Usernames (transparent)", name = "Usernames (transparent)",
description = "Color of Usernames (transparent)", description = "Color of Usernames (transparent)",
titleSection = "transparentTitle" section = transparentSection
) )
Color transparentUsername(); Color transparentUsername();
@@ -555,7 +549,7 @@ public interface ChatColorConfig extends Config
keyName = "transparentPrivateUsernames", keyName = "transparentPrivateUsernames",
name = "Private chat usernames (transparent)", name = "Private chat usernames (transparent)",
description = "Color of Usernames in Private Chat (transparent)", description = "Color of Usernames in Private Chat (transparent)",
titleSection = "transparentTitle" section = transparentSection
) )
Color transparentPrivateUsernames(); Color transparentPrivateUsernames();
@@ -564,7 +558,7 @@ public interface ChatColorConfig extends Config
keyName = "transparentClanChannelName", keyName = "transparentClanChannelName",
name = "Friends chat channel name (transparent)", name = "Friends chat channel name (transparent)",
description = "Color of Friends chat channel name (transparent)", description = "Color of Friends chat channel name (transparent)",
titleSection = "transparentTitle" section = transparentSection
) )
Color transparentFriendsChatChannelName(); Color transparentFriendsChatChannelName();
@@ -573,7 +567,7 @@ public interface ChatColorConfig extends Config
keyName = "transparentClanUsernames", keyName = "transparentClanUsernames",
name = "Friends chat usernames (transparent)", name = "Friends chat usernames (transparent)",
description = "Color of usernames in Friends chat (transparent)", description = "Color of usernames in Friends chat (transparent)",
titleSection = "transparentTitle" section = transparentSection
) )
Color transparentFriendsChatUsernames(); Color transparentFriendsChatUsernames();
@@ -582,7 +576,7 @@ public interface ChatColorConfig extends Config
keyName = "transparentPublicFriendUsernames", keyName = "transparentPublicFriendUsernames",
name = "Public friend usernames (transparent)", name = "Public friend usernames (transparent)",
description = "Color of Friend Usernames in Public Chat (transparent)", description = "Color of Friend Usernames in Public Chat (transparent)",
titleSection = "transparentTitle" section = transparentSection
) )
Color transparentPublicFriendUsernames(); Color transparentPublicFriendUsernames();
} }

View File

@@ -24,4 +24,6 @@
*/ */
package net.runelite.client.config; package net.runelite.client.config;
public interface Config {} public interface Config
{
}

View File

@@ -24,22 +24,20 @@
*/ */
package net.runelite.client.config; package net.runelite.client.config;
import java.util.Collection;
import lombok.Getter; import lombok.Getter;
import java.util.Collection;
@Getter @Getter
public class ConfigDescriptor public class ConfigDescriptor
{ {
private final ConfigGroup group; private final ConfigGroup group;
private final Collection<ConfigSection> sections; private final Collection<ConfigSectionDescriptor> sections;
private final Collection<ConfigTitleSection> titleSections;
private final Collection<ConfigItemDescriptor> items; private final Collection<ConfigItemDescriptor> items;
public ConfigDescriptor(ConfigGroup group, Collection<ConfigSection> sections, Collection<ConfigTitleSection> titleSections, Collection<ConfigItemDescriptor> items) public ConfigDescriptor(ConfigGroup group, Collection<ConfigSectionDescriptor> sections, Collection<ConfigItemDescriptor> items)
{ {
this.group = group; this.group = group;
this.sections = sections; this.sections = sections;
this.titleSections = titleSections;
this.items = items; this.items = items;
} }
} }

View File

@@ -26,11 +26,11 @@ package net.runelite.client.config;
import com.google.common.cache.Cache; import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Objects; import java.util.Objects;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.runelite.client.util.ReflectUtil;
@Slf4j @Slf4j
class ConfigInvocationHandler implements InvocationHandler class ConfigInvocationHandler implements InvocationHandler
@@ -112,11 +112,7 @@ class ConfigInvocationHandler implements InvocationHandler
log.warn("Unable to unmarshal {}.{} ", group.value(), item.keyName(), e); log.warn("Unable to unmarshal {}.{} ", group.value(), item.keyName(), e);
if (method.isDefault()) if (method.isDefault())
{ {
Object defaultValue = callDefaultMethod(proxy, method, null); return callDefaultMethod(proxy, method, null);
manager.setConfiguration(group.value(), item.keyName(), defaultValue);
return defaultValue;
} }
return null; return null;
} }
@@ -127,7 +123,7 @@ class ConfigInvocationHandler implements InvocationHandler
if (args.length != 1) if (args.length != 1)
{ {
throw new RuntimeException("Invalid number of arguents to configuration method"); throw new RuntimeException("Invalid number of arguments to configuration method");
} }
Object newValue = args[0]; Object newValue = args[0];
@@ -169,7 +165,7 @@ class ConfigInvocationHandler implements InvocationHandler
static Object callDefaultMethod(Object proxy, Method method, Object[] args) throws Throwable static Object callDefaultMethod(Object proxy, Method method, Object[] args) throws Throwable
{ {
Class<?> declaringClass = method.getDeclaringClass(); Class<?> declaringClass = method.getDeclaringClass();
return MethodHandles.privateLookupIn(declaringClass, MethodHandles.lookup()) return ReflectUtil.privateLookupIn(declaringClass)
.unreflectSpecial(method, declaringClass) .unreflectSpecial(method, declaringClass)
.bindTo(proxy) .bindTo(proxy)
.invokeWithArguments(args); .invokeWithArguments(args);

View File

@@ -33,143 +33,19 @@ import java.lang.annotation.Target;
@Target(ElementType.METHOD) @Target(ElementType.METHOD)
public @interface ConfigItem public @interface ConfigItem
{ {
/**
* If there is a section set, it will display in order
* starting from lowest value and ending at highest value
* in that specific section. Else, it will display in order
* for the config panel in a whole.
*
* @return The index of the config item.
*/
int position() default -1; int position() default -1;
/**
* This is not visible to users
*
* @return name used for finding the config item
* from the properties map. Hence, KEY name.
*/
String keyName(); String keyName();
/**
* This is the name that is shown to users when looking
* at the config panel.
* <p>
* Choose a name carefully, as there is a maximum width
* that depends on the users DPI scaling. Short is best.
*
* @return display name for the config item.
*/
String name(); String name();
/**
* This will be shown to the user if they are hovering
* the config item in the config panel.
*
* @return the description of the config item.
*/
String description(); String description();
/**
* If this is set to true, the config field will be
* hidden. You are able to change this value at runtime
* by having another config field unhide it {@link #unhide()}
*/
boolean hidden() default false; boolean hidden() default false;
/**
* This is only used for {@link Boolean} config fields.
* <p>
* If this is set, then a warning(y/n) will be displayed
* when the user enables said config field. If they accept
* then the value will be set updated.
*
* @return a warning for enabling the config field.
*/
String warning() default ""; String warning() default "";
/**
* This is only used for {@link String} config fields.
* <p>
* If this is set to true, any input from the user
* will be hidden, and not displayed. This should
* be used for any sensitive information that may
* be accidentally leaked.
* <p>
* For example; api keys.
*/
boolean secret() default false; boolean secret() default false;
/**
* If this is set, it will look for a section
* by that {@link ConfigSection#name()}, if it exists,
* it will insert the config item under that
* section in order.
*
* @return title of the section.
*/
String section() default ""; String section() default "";
/**
* If this is set, it will look for a title section
* by that {@link ConfigTitleSection#name()}, if it exists,
* it will insert the config item under that
* section in order.
*
* @return title of the section.
*/
String titleSection() default "";
/**
* If this is set, it will look for a config item
* by that name. If it is hidden, it will unhide the item.
*
* @return {@link #name()} to unhide.
*/
String unhide() default "";
String unhideValue() default "";
/**
* If this is set, it will look for a config item
* by that name. If it is not hidden, it will hide the item.
*
* @return {@link #name()} to hide.
*/
String hide() default "";
String hideValue() default "";
/**
* If this is set, it will look for a config item
* by the name provided, if that config item is enabled
* then this item will also be enabled.
*/
String enabledBy() default "";
String enabledByValue() default "";
/**
* If this is set, it will look for a config item
* by the name provided, if that config item is disabled
* then this item will also be disabled.
*/
String disabledBy() default "";
String disabledByValue() default "";
boolean parse() default false;
Class<?> clazz() default void.class;
String method() default "";
/**
* Use this to indicate the enum class that is going to be used in the multiple select config.
* This implementation made debugging problems with multiple selects a lot easier
*
* @return The Enum that will be used for the multiple select
*/
Class<? extends Enum> enumClass() default Enum.class;
} }

View File

@@ -27,11 +27,29 @@ package net.runelite.client.config;
import lombok.Value; import lombok.Value;
@Value @Value
public class ConfigItemDescriptor public class ConfigItemDescriptor implements ConfigObject
{ {
private final ConfigItem item; private final ConfigItem item;
private final Class<?> type; private final Class<?> type;
private final Range range; private final Range range;
private final Alpha alpha; private final Alpha alpha;
private final Units units; private final Units units;
@Override
public String key()
{
return item.keyName();
}
@Override
public String name()
{
return item.name();
}
@Override
public int position()
{
return item.position();
}
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, TheStonedTurtle <https://github.com/TheStonedTurtle> * Copyright (c) 2020, Hydrox6 <ikada@protonmail.ch>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -22,11 +22,11 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package net.runelite.client.ui.overlay.components.table; package net.runelite.client.config;
public enum TableAlignment public interface ConfigObject
{ {
LEFT, String key();
CENTER, String name();
RIGHT int position();
} }

View File

@@ -30,79 +30,14 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD) @Target(ElementType.FIELD)
public @interface ConfigSection public @interface ConfigSection
{ {
/**
* Displayed position of the section.
*
* @return The index of the section.
*/
int position();
/**
* This is not visible to users
*
* @return name used for finding the config section
* from the properties map. Hence, KEY name.
*/
String keyName();
/**
* This is the name that is shown to users when looking
* at the config panel.
* <p>
* Choose a name carefully, as there is a maximum width
* that depends on the users DPI scaling. Short is best.
*
* @return display name for the config section.
*/
String name(); String name();
/**
* This will be shown to the user if they are hovering
* the config item in the config panel.
*
* @return the description of the config item.
*/
String description(); String description();
/** int position();
* Setting this will tell the panel
* that this section should be placed beneath
* said section.
*
* @return parent section.
*/
String section() default "";
/** boolean closedByDefault() default false;
* NOT USED.
*/
String titleSection() default "";
/**
* NOT USED.
*/
boolean hidden() default false;
/**
* NOT USED.
*/
String unhide() default "";
/**
* NOT USED.
*/
String unhideValue() default "";
/**
* NOT USED.
*/
String hide() default "";
/**
* NOT USED.
*/
String hideValue() default "";
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, Woox <https://github.com/wooxsolo> * Copyright (c) 2020, Hydrox6 <ikada@protonmail.ch>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -22,15 +22,31 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package net.runelite.client.graphics; package net.runelite.client.config;
import lombok.RequiredArgsConstructor;
import lombok.Value; import lombok.Value;
@Value @Value
@RequiredArgsConstructor public class ConfigSectionDescriptor implements ConfigObject
class PixelDistanceAlpha
{ {
private final int outerAlpha; private final String key;
private final int distArrayPos; private final ConfigSection section;
@Override
public String key()
{
return key;
}
@Override
public String name()
{
return section.name();
}
@Override
public int position()
{
return section.position();
}
} }

View File

@@ -1,112 +0,0 @@
/*
* Copyright (c) 2019, Hydrox6 <ikada@protonmail.ch>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.client.config;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ConfigTitleSection
{
/**
* Displayed position of the title section.
*
* @return The index of the title section.
*/
int position();
/**
* This is not visible to users
*
* @return name used for finding the config section
* from the properties map. Hence, KEY name.
*/
String keyName();
/**
* This is the name that is shown to users when looking
* at the config panel.
* <p>
* Choose a name carefully, as there is a maximum width
* that depends on the users DPI scaling. Short is best.
*
* @return display name for the config title section.
*/
String name();
/**
* This will be shown to the user if they are hovering
* the config item in the config panel.
*
* @return the description of the config item.
*/
String description();
/**
* Setting this will tell the panel
* that this title should be placed beneath
* said section.
*
* @return parent section.
*/
String section() default "";
/**
* Setting this will tell the panel
* that this title should be placed beneath
* said title.
*
* @return parent title section.
*/
String titleSection() default "";
/**
* NOT USED.
*/
boolean hidden() default false;
/**
* NOT USED.
*/
String unhide() default "";
/**
* NOT USED.
*/
String unhideValue() default "";
/**
* NOT USED.
*/
String hide() default "";
/**
* NOT USED.
*/
String hideValue() default "";
}

View File

@@ -24,11 +24,12 @@
*/ */
package net.runelite.client.config; package net.runelite.client.config;
import java.awt.Font;
import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.Getter;
import net.runelite.client.ui.FontManager; import net.runelite.client.ui.FontManager;
import java.awt.Font;
@Getter @Getter
@RequiredArgsConstructor @RequiredArgsConstructor
public enum FontType public enum FontType

View File

@@ -60,7 +60,7 @@ public class Keybind
private final int keyCode; private final int keyCode;
private final int modifiers; private final int modifiers;
Keybind(int keyCode, int modifiers, boolean ignoreModifiers) protected Keybind(int keyCode, int modifiers, boolean ignoreModifiers)
{ {
modifiers &= KEYBOARD_MODIFIER_MASK; modifiers &= KEYBOARD_MODIFIER_MASK;
@@ -108,7 +108,7 @@ public class Keybind
return matches(e, false); return matches(e, false);
} }
boolean matches(KeyEvent e, boolean ignoreModifiers) protected boolean matches(KeyEvent e, boolean ignoreModifiers)
{ {
if (NOT_SET.equals(this)) if (NOT_SET.equals(this))
{ {
@@ -177,7 +177,7 @@ public class Keybind
return mod; return mod;
} }
private static String getModifiersExText(int modifiers) public static String getModifiersExText(int modifiers)
{ {
StringBuilder buf = new StringBuilder(); StringBuilder buf = new StringBuilder();
if ((modifiers & InputEvent.META_DOWN_MASK) != 0) if ((modifiers & InputEvent.META_DOWN_MASK) != 0)

View File

@@ -1,174 +0,0 @@
/*
* Copyright (c) 2019 Owain van Brakel <https://github.com/Owain94>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.client.config;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
@ConfigGroup("openosrs")
public interface LauncherConfig extends Config
{
@Getter(AccessLevel.PRIVATE)
@AllArgsConstructor
enum BootstrapMode
{
STABLE("Stable"),
NIGHTLY("Nightly");
private String name;
@Override
public String toString()
{
return getName();
}
}
@ConfigTitleSection(
keyName = "launcherTitle",
name = "Launcher",
description = "",
position = -1
)
default Title launcherTitle()
{
return new Title();
}
@ConfigTitleSection(
keyName = "updateChannelTitle",
name = "Update channel",
description = "",
position = 1,
titleSection = "launcherTitle"
)
default Title updateChannelTitle()
{
return new Title();
}
@ConfigItem(
position = 2,
keyName = "askMode",
name = "Prompt for update channel",
description = "Ask for nightly or stable every startup",
titleSection = "updateChannelTitle"
)
default boolean askMode()
{
return true;
}
@ConfigItem(
keyName = "bootstrapMode",
name = "Update channel",
description = "Select the update channel",
titleSection = "updateChannelTitle",
position = 3,
hide = "askMode"
)
default BootstrapMode bootstrapMode()
{
return BootstrapMode.STABLE;
}
@ConfigTitleSection(
keyName = "miscLauncherTitle",
name = "Miscellaneous",
description = "",
position = 4,
titleSection = "launcherTitle"
)
default Title miscLauncherTitle()
{
return new Title();
}
@ConfigItem(
position = 5,
keyName = "disableHw",
name = "Disable hardware acceleration",
description = "Enable this if you have graphical issues",
titleSection = "miscLauncherTitle",
warning = "Toggling this setting requires a restart of the client"
)
default boolean disableHw()
{
return false;
}
@ConfigTitleSection(
keyName = "advancedTitle",
name = "Advanced",
description = "",
position = 6,
titleSection = "launcherTitle"
)
default Title advancedTitle()
{
return new Title();
}
@ConfigItem(
position = 7,
keyName = "noJvm",
name = "Use system java (caution!)",
description = "Enable this if you want to make use of the system java version instead of the launcher bundled version",
titleSection = "advancedTitle",
warning = "Toggling this setting requires a restart of the client"
)
default boolean noJvm()
{
return false;
}
@ConfigItem(
position = 8,
keyName = "useProxy",
name = "Use SOCKS5 proxy",
description = "Enable the client to use a proxy",
titleSection = "advancedTitle",
warning = "Toggling this setting requires a restart of the client"
)
default boolean useProxy()
{
return false;
}
@ConfigItem(
keyName = "proxyDetails",
name = "Proxy details",
description = "The format for this field is ip:port or ip:port:user:pass",
titleSection = "advancedTitle",
position = 9,
hidden = true,
unhide = "useProxy"
)
default String proxyDetails()
{
return "";
}
}

View File

@@ -1,373 +0,0 @@
/*
*
* 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;
import java.awt.Color;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import net.runelite.client.plugins.ExternalPluginManager;
@ConfigGroup("openosrs")
public interface OpenOSRSConfig extends Config
{
@Getter(AccessLevel.PUBLIC)
@AllArgsConstructor
enum SortStyle
{
CATEGORY("Category"),
ALPHABETICALLY("Alphabetically"),
REPOSITORY("Repository");
private String name;
@Override
public String toString()
{
return getName();
}
}
@ConfigTitleSection(
keyName = "logTitle",
name = "Error data",
description = "",
position = 1
)
default Title logTitle()
{
return new Title();
}
@ConfigItem(
position = 3,
keyName = "shareLogs",
name = "Share anonymous error data",
description = "Share anonymous error data with the OpenOSRS developers",
titleSection = "logTitle"
)
default boolean shareLogs()
{
return true;
}
@ConfigTitleSection(
keyName = "pluginsTitle",
name = "Plugins",
description = "",
position = 1
)
default Title pluginsTitle()
{
return new Title();
}
@ConfigTitleSection(
keyName = "pluginSortingTitle",
name = "Sorting",
description = "",
position = 2,
titleSection = "pluginsTitle"
)
default Title pluginSortingTitle()
{
return new Title();
}
@ConfigItem(
position = 3,
keyName = "pluginSortMode",
name = "Sorting mode",
description = "Sorts plugins ",
titleSection = "pluginSortingTitle"
)
default SortStyle pluginSortMode()
{
return SortStyle.CATEGORY;
}
@ConfigItem(
position = 4,
keyName = "enableCategories",
name = "Categorize plugins",
description = "Show sections in the plugin list for each plugin type",
titleSection = "pluginSortingTitle",
hidden = true,
unhide = "pluginSortMode",
unhideValue = "Category"
)
default boolean enableCategories()
{
return true;
}
@ConfigTitleSection(
keyName = "pluginsColorTitle",
name = "Colors",
description = "",
position = 5,
titleSection = "pluginsTitle"
)
default Title pluginsColorTitle()
{
return new Title();
}
@ConfigItem(
position = 6,
keyName = "enabledColors",
name = "Enable plugin colors",
description = "Configure whether or not the plugins list should be colorcoded",
titleSection = "pluginsColorTitle"
)
default boolean enabledColors()
{
return true;
}
@Alpha
@ConfigItem(
position = 7,
keyName = "pvmColor",
name = "PvM color",
description = "Configure the color of PvM related plugins",
titleSection = "pluginsColorTitle",
hidden = true,
unhide = "enabledColors"
)
default Color pvmColor()
{
return new Color(119, 221, 119, 255);
}
@Alpha
@ConfigItem(
position = 8,
keyName = "skillingColor",
name = "Skilling color",
description = "Configure the color of skilling related plugins",
titleSection = "pluginsColorTitle",
hidden = true,
unhide = "enabledColors"
)
default Color skillingColor()
{
return new Color(252, 252, 100, 255);
}
@Alpha
@ConfigItem(
position = 9,
keyName = "pvpColor",
name = "PvP color",
description = "Configure the color of PvP related plugins",
titleSection = "pluginsColorTitle",
hidden = true,
unhide = "enabledColors"
)
default Color pvpColor()
{
return new Color(255, 105, 97, 255);
}
@Alpha
@ConfigItem(
position = 10,
keyName = "utilityColor",
name = "Utility color",
description = "Configure the color of utility related plugins",
titleSection = "pluginsColorTitle",
hidden = true,
unhide = "enabledColors"
)
default Color utilityColor()
{
return new Color(144, 212, 237, 255);
}
@Alpha
@ConfigItem(
position = 11,
keyName = "minigameColor",
name = "Minigame color",
description = "Configure the color of minigame related plugins",
titleSection = "pluginsColorTitle",
hidden = true,
unhide = "enabledColors"
)
default Color minigameColor()
{
return new Color(235, 130, 66, 255);
}
@Alpha
@ConfigItem(
position = 12,
keyName = "miscellaneousColor",
name = "Miscellaneous color",
description = "Configure the color of miscellaneous related plugins",
titleSection = "pluginsColorTitle",
hidden = true,
unhide = "enabledColors"
)
default Color miscellaneousColor()
{
return new Color(243, 85, 136, 255);
}
@Alpha
@ConfigItem(
position = 13,
keyName = "gamemodeColor",
name = "Gamemode color",
description = "Configure the color of gamemode plugins",
titleSection = "pluginsColorTitle",
hidden = true,
unhide = "enabledColors"
)
default Color gamemodeColor()
{
return new Color(244, 239, 211, 255);
}
@ConfigTitleSection(
keyName = "opacityTitle",
name = "Opacity",
description = "",
position = 17
)
default Title opacityTitle()
{
return new Title();
}
@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 = 18,
titleSection = "opacityTitle"
)
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 = 19,
titleSection = "opacityTitle"
)
@Units(Units.PERCENT)
default int opacityPercentage()
{
return 100;
}
@ConfigTitleSection(
keyName = "miscTitle",
name = "Miscellaneous",
description = "",
position = 20
)
default Title miscTitle()
{
return new Title();
}
@ConfigItem(
keyName = "localSync",
name = "Sync local instances",
description = "Enables multiple local instances of OpenOSRS to communicate (this enables syncing plugin state and config options)",
position = 21,
titleSection = "miscTitle"
)
default boolean localSync()
{
return true;
}
@ConfigItem(
keyName = "keyboardPin",
name = "Keyboard bank pin",
description = "Enables you to type your bank pin",
position = 22,
titleSection = "miscTitle"
)
default boolean keyboardPin()
{
return false;
}
@ConfigItem(
keyName = "detachHotkey",
name = "Detach Cam",
description = "Detach Camera hotkey, press this and it will activate detatched camera.",
position = 23,
titleSection = "miscTitle"
)
default Keybind detachHotkey()
{
return Keybind.NOT_SET;
}
@ConfigItem(
keyName = "externalRepositories",
name = "",
description = "",
hidden = true
)
default String getExternalRepositories()
{
return ExternalPluginManager.DEFAULT_PLUGIN_REPOS;
}
@ConfigItem(
keyName = "externalRepositories",
name = "",
description = "",
hidden = true
)
void setExternalRepositories(String val);
@ConfigItem(
keyName = "warning",
name = "",
description = "",
hidden = true
)
default boolean warning()
{
return true;
}
}

View File

@@ -38,25 +38,34 @@ public interface RuneLiteConfig extends Config
{ {
String GROUP_NAME = "runelite"; String GROUP_NAME = "runelite";
@ConfigTitleSection( @ConfigSection(
keyName = "uiTitle", name = "Window Settings",
name = "User interface", description = "Settings relating to the client's window and frame",
description = "", position = 0
)
String windowSettings = "windowSettings";
@ConfigSection(
name = "Notification Settings",
description = "Settings relating to notifications",
position = 1 position = 1
) )
default Title uiTitle() String notificationSettings = "notificationSettings";
{
return new Title(); @ConfigSection(
} name = "Overlay Settings",
description = "Settings relating to fonts",
position = 2
)
String overlaySettings = "overlaySettings";
@ConfigItem( @ConfigItem(
keyName = "gameSize", keyName = "gameSize",
name = "Game size", name = "Game size",
description = "The game will resize to this resolution upon starting the client", description = "The game will resize to this resolution upon starting the client",
position = 2, position = 10,
titleSection = "uiTitle" section = windowSettings
) )
@Units(Units.PIXELS)
default Dimension gameSize() default Dimension gameSize()
{ {
return Constants.GAME_FIXED_SIZE; return Constants.GAME_FIXED_SIZE;
@@ -66,8 +75,8 @@ public interface RuneLiteConfig extends Config
keyName = "automaticResizeType", keyName = "automaticResizeType",
name = "Resize type", name = "Resize type",
description = "Choose how the window should resize when opening and closing panels", description = "Choose how the window should resize when opening and closing panels",
position = 3, position = 11,
titleSection = "uiTitle" section = windowSettings
) )
default ExpandResizeType automaticResizeType() default ExpandResizeType automaticResizeType()
{ {
@@ -78,8 +87,8 @@ public interface RuneLiteConfig extends Config
keyName = "lockWindowSize", keyName = "lockWindowSize",
name = "Lock window size", name = "Lock window size",
description = "Determines if the window resizing is allowed or not", description = "Determines if the window resizing is allowed or not",
position = 4, position = 12,
titleSection = "uiTitle" section = windowSettings
) )
default boolean lockWindowSize() default boolean lockWindowSize()
{ {
@@ -90,82 +99,61 @@ public interface RuneLiteConfig extends Config
keyName = "containInScreen2", keyName = "containInScreen2",
name = "Contain in screen", name = "Contain in screen",
description = "Makes the client stay contained in the screen when attempted to move out of it.<br>Note: 'Always' only works if custom chrome is enabled.", description = "Makes the client stay contained in the screen when attempted to move out of it.<br>Note: 'Always' only works if custom chrome is enabled.",
position = 5, position = 13,
titleSection = "uiTitle" section = windowSettings
) )
default ContainableFrame.Mode containInScreen() default ContainableFrame.Mode containInScreen()
{ {
return ContainableFrame.Mode.RESIZING; return ContainableFrame.Mode.RESIZING;
} }
@ConfigItem(
keyName = "uiEnableCustomChrome",
name = "Enable custom window chrome",
description = "Use Runelite's custom window title and borders.",
warning = "Please restart your client after changing this setting.",
position = 6,
titleSection = "uiTitle"
)
default boolean enableCustomChrome()
{
return true;
}
@ConfigItem(
keyName = "borderless",
name = "Windowed borderless",
description = "Use windowed borderless mode",
warning = "Please restart your client after changing this setting.",
position = 7,
titleSection = "uiTitle"
)
default boolean borderless()
{
return false;
}
@ConfigItem(
keyName = "usernameInTitle",
name = "Show display name in title",
description = "Toggles displaying of local player's display name in client title",
position = 8,
titleSection = "uiTitle"
)
default boolean usernameInTitle()
{
return true;
}
@ConfigTitleSection(
keyName = "miscTitle",
name = "Miscellaneous",
description = "",
position = 9
)
default Title miscTitle()
{
return new Title();
}
@ConfigItem( @ConfigItem(
keyName = "rememberScreenBounds", keyName = "rememberScreenBounds",
name = "Remember client position", name = "Remember client position",
description = "Save the position and size of the client after exiting", description = "Save the position and size of the client after exiting",
position = 10, position = 14,
titleSection = "miscTitle" section = windowSettings
) )
default boolean rememberScreenBounds() default boolean rememberScreenBounds()
{ {
return true; return true;
} }
@ConfigItem(
keyName = "uiEnableCustomChrome",
name = "Enable custom window chrome",
description = "Use Runelite's custom window title and borders.",
warning = "Please restart your client after changing this setting",
position = 15,
section = windowSettings
)
default boolean enableCustomChrome()
{
return true;
}
@Range(
min = 10,
max = 100
)
@ConfigItem(
keyName = "uiWindowOpacity",
name = "Window opacity",
description = "Set the windows opacity. Requires \"Enable custom window chrome\" to be enabled.",
position = 16,
section = windowSettings
)
default int windowOpacity()
{
return 100;
}
@ConfigItem( @ConfigItem(
keyName = "gameAlwaysOnTop", keyName = "gameAlwaysOnTop",
name = "Enable client always on top", name = "Enable client always on top",
description = "The game will always be on the top of the screen", description = "The game will always be on the top of the screen",
position = 11, position = 17,
titleSection = "miscTitle" section = windowSettings
) )
default boolean gameAlwaysOnTop() default boolean gameAlwaysOnTop()
{ {
@@ -176,57 +164,32 @@ public interface RuneLiteConfig extends Config
keyName = "warningOnExit", keyName = "warningOnExit",
name = "Display warning on exit", name = "Display warning on exit",
description = "Toggles a warning popup when trying to exit the client", description = "Toggles a warning popup when trying to exit the client",
position = 12, position = 18,
titleSection = "miscTitle" section = windowSettings
) )
default WarningOnExit warningOnExit() default WarningOnExit warningOnExit()
{ {
return WarningOnExit.LOGGED_IN; return WarningOnExit.LOGGED_IN;
} }
@Range(max = 100, min = 0)
@ConfigItem( @ConfigItem(
keyName = "volume", keyName = "usernameInTitle",
name = "Runelite Volume", name = "Show display name in title",
description = "Sets the volume of custom Runelite sounds (not the client sounds)", description = "Toggles displaying of local player's display name in client title",
position = 13, position = 19,
titleSection = "miscTitle" section = windowSettings
) )
@Units(Units.PERCENT) default boolean usernameInTitle()
default int volume()
{ {
return 100; return true;
}
@ConfigItem(
keyName = "tooltipPosition",
name = "Tooltip Position",
description = "Configures whether to show the tooltip above or under the cursor",
position = 14,
titleSection = "miscTitle"
)
default TooltipPositionType tooltipPosition()
{
return TooltipPositionType.UNDER_CURSOR;
}
@ConfigTitleSection(
keyName = "notificationsTitle",
name = "Notifications",
description = "",
position = 15
)
default Title notificationsTitle()
{
return new Title();
} }
@ConfigItem( @ConfigItem(
keyName = "notificationTray", keyName = "notificationTray",
name = "Enable tray notifications", name = "Enable tray notifications",
description = "Enables tray notifications", description = "Enables tray notifications",
position = 16, position = 20,
titleSection = "notificationsTitle" section = notificationSettings
) )
default boolean enableTrayNotifications() default boolean enableTrayNotifications()
{ {
@@ -237,8 +200,8 @@ public interface RuneLiteConfig extends Config
keyName = "notificationRequestFocus", keyName = "notificationRequestFocus",
name = "Request focus on notification", name = "Request focus on notification",
description = "Configures the window focus request type on notification", description = "Configures the window focus request type on notification",
position = 17, position = 21,
titleSection = "notificationsTitle" section = notificationSettings
) )
default RequestFocusType notificationRequestFocus() default RequestFocusType notificationRequestFocus()
{ {
@@ -249,8 +212,8 @@ public interface RuneLiteConfig extends Config
keyName = "notificationSound", keyName = "notificationSound",
name = "Notification sound", name = "Notification sound",
description = "Enables the playing of a beep sound when notifications are displayed", description = "Enables the playing of a beep sound when notifications are displayed",
position = 18, position = 22,
titleSection = "notificationsTitle" section = notificationSettings
) )
default Notifier.NativeCustomOff notificationSound() default Notifier.NativeCustomOff notificationSound()
{ {
@@ -261,8 +224,8 @@ public interface RuneLiteConfig extends Config
keyName = "notificationGameMessage", keyName = "notificationGameMessage",
name = "Enable game message notifications", name = "Enable game message notifications",
description = "Puts a notification message in the chatbox", description = "Puts a notification message in the chatbox",
position = 19, position = 23,
titleSection = "notificationsTitle" section = notificationSettings
) )
default boolean enableGameMessageNotification() default boolean enableGameMessageNotification()
{ {
@@ -270,11 +233,11 @@ public interface RuneLiteConfig extends Config
} }
@ConfigItem( @ConfigItem(
keyName = "notificationFlash", keyName = "flashNotification",
name = "Enable flash notification", name = "Flash notification",
description = "Flashes the game frame as a notification", description = "Flashes the game frame as a notification",
position = 20, position = 24,
titleSection = "notificationsTitle" section = notificationSettings
) )
default FlashNotification flashNotification() default FlashNotification flashNotification()
{ {
@@ -285,8 +248,8 @@ public interface RuneLiteConfig extends Config
keyName = "notificationFocused", keyName = "notificationFocused",
name = "Send notifications when focused", name = "Send notifications when focused",
description = "Toggles all notifications for when the client is focused", description = "Toggles all notifications for when the client is focused",
position = 21, position = 25,
titleSection = "notificationsTitle" section = notificationSettings
) )
default boolean sendNotificationsWhenFocused() default boolean sendNotificationsWhenFocused()
{ {
@@ -298,31 +261,20 @@ public interface RuneLiteConfig extends Config
keyName = "notificationFlashColor", keyName = "notificationFlashColor",
name = "Notification Flash Color", name = "Notification Flash Color",
description = "Sets the color of the notification flashes.", description = "Sets the color of the notification flashes.",
position = 22, position = 26,
titleSection = "notificationsTitle" section = notificationSettings
) )
default Color notificationFlashColor() default Color notificationFlashColor()
{ {
return new Color(255, 0, 0, 70); return new Color(255, 0, 0, 70);
} }
@ConfigTitleSection(
keyName = "fontTitle",
name = "Font",
description = "",
position = 23
)
default Title fontTitle()
{
return new Title();
}
@ConfigItem( @ConfigItem(
keyName = "fontType", keyName = "fontType",
name = "Dynamic Overlay Font", name = "Dynamic Overlay Font",
description = "Configures what font type is used for in-game overlays such as player name, ground items, etc.", description = "Configures what font type is used for in-game overlays such as player name, ground items, etc.",
position = 24, position = 30,
titleSection = "fontTitle" section = overlaySettings
) )
default FontType fontType() default FontType fontType()
{ {
@@ -333,8 +285,8 @@ public interface RuneLiteConfig extends Config
keyName = "tooltipFontType", keyName = "tooltipFontType",
name = "Tooltip Font", name = "Tooltip Font",
description = "Configures what font type is used for in-game tooltips such as food stats, NPC names, etc.", description = "Configures what font type is used for in-game tooltips such as food stats, NPC names, etc.",
position = 25, position = 31,
titleSection = "fontTitle" section = overlaySettings
) )
default FontType tooltipFontType() default FontType tooltipFontType()
{ {
@@ -345,31 +297,20 @@ public interface RuneLiteConfig extends Config
keyName = "interfaceFontType", keyName = "interfaceFontType",
name = "Interface Overlay Font", name = "Interface Overlay Font",
description = "Configures what font type is used for in-game interface overlays such as panels, opponent info, clue scrolls etc.", description = "Configures what font type is used for in-game interface overlays such as panels, opponent info, clue scrolls etc.",
position = 26, position = 32,
titleSection = "fontTitle" section = overlaySettings
) )
default FontType interfaceFontType() default FontType interfaceFontType()
{ {
return FontType.REGULAR; return FontType.REGULAR;
} }
@ConfigTitleSection(
keyName = "overlayTitle",
name = "Overlays",
description = "",
position = 27
)
default Title overlayTitle()
{
return new Title();
}
@ConfigItem( @ConfigItem(
keyName = "menuEntryShift", keyName = "menuEntryShift",
name = "Require Shift for overlay menu", name = "Require Shift for overlay menu",
description = "Overlay right-click menu will require shift to be added", description = "Overlay right-click menu will require shift to be added",
position = 28, position = 33,
titleSection = "overlayTitle" section = overlaySettings
) )
default boolean menuEntryShift() default boolean menuEntryShift()
{ {
@@ -377,47 +318,23 @@ public interface RuneLiteConfig extends Config
} }
@ConfigItem( @ConfigItem(
keyName = "overlayBackgroundColor", keyName = "tooltipPosition",
name = "Overlay Color", name = "Tooltip Position",
description = "Configures the background color of infoboxes and overlays", description = "Configures whether to show the tooltip above or under the cursor",
position = 29, position = 35,
titleSection = "overlayTitle" section = overlaySettings
) )
@Alpha default TooltipPositionType tooltipPosition()
default Color overlayBackgroundColor()
{ {
return ComponentConstants.STANDARD_BACKGROUND_COLOR; return TooltipPositionType.UNDER_CURSOR;
}
@ConfigTitleSection(
keyName = "infoboxTitle",
name = "Infoboxes",
description = "",
position = 30
)
default Title infoboxTitle()
{
return new Title();
}
@ConfigItem(
keyName = "infoBoxTextOutline",
name = "Outline infobox text",
description = "Draw a full outline instead of a simple shadow for infobox text",
position = 31,
titleSection = "infoboxTitle"
)
default boolean infoBoxTextOutline()
{
return false;
} }
@ConfigItem( @ConfigItem(
keyName = "infoBoxVertical", keyName = "infoBoxVertical",
name = "Display infoboxes vertically", name = "Display infoboxes vertically",
description = "Toggles the infoboxes to display vertically", description = "Toggles the infoboxes to display vertically",
position = 32, position = 40,
titleSection = "infoboxTitle", section = overlaySettings,
hidden = true hidden = true
) )
default boolean infoBoxVertical() default boolean infoBoxVertical()
@@ -429,8 +346,8 @@ public interface RuneLiteConfig extends Config
keyName = "infoBoxSize", keyName = "infoBoxSize",
name = "Infobox size", name = "Infobox size",
description = "Configures the size of each infobox in pixels", description = "Configures the size of each infobox in pixels",
position = 33, position = 42,
titleSection = "infoboxTitle" section = overlaySettings
) )
@Units(Units.PIXELS) @Units(Units.PIXELS)
default int infoBoxSize() default int infoBoxSize()
@@ -438,23 +355,48 @@ public interface RuneLiteConfig extends Config
return 35; return 35;
} }
@ConfigTitleSection( @ConfigItem(
keyName = "keybindsTitle", keyName = "infoBoxTextOutline",
name = "Key binds", name = "Outline infobox text",
description = "", description = "Draw a full outline instead of a simple shadow for infobox text",
position = 34 position = 43,
section = overlaySettings
) )
default Title keybindsTitle() default boolean infoBoxTextOutline()
{ {
return new Title(); return false;
}
@ConfigItem(
keyName = "overlayBackgroundColor",
name = "Overlay Color",
description = "Configures the background color of infoboxes and overlays",
position = 44,
section = overlaySettings
)
@Alpha
default Color overlayBackgroundColor()
{
return ComponentConstants.STANDARD_BACKGROUND_COLOR;
}
@ConfigItem(
keyName = "blockExtraMouseButtons",
name = "Block Extra Mouse Buttons",
description = "Blocks extra mouse buttons (4 and above)",
position = 44
)
default boolean blockExtraMouseButtons()
{
return true;
} }
@ConfigItem( @ConfigItem(
keyName = "sidebarToggleKey", keyName = "sidebarToggleKey",
name = "Sidebar Toggle Key", name = "Sidebar Toggle Key",
description = "The key that will toggle the sidebar (accepts modifiers)", description = "The key that will toggle the sidebar (accepts modifiers)",
position = 35, position = 45,
titleSection = "keybindsTitle" section = windowSettings
) )
default Keybind sidebarToggleKey() default Keybind sidebarToggleKey()
{ {
@@ -465,23 +407,11 @@ public interface RuneLiteConfig extends Config
keyName = "panelToggleKey", keyName = "panelToggleKey",
name = "Plugin Panel Toggle Key", name = "Plugin Panel Toggle Key",
description = "The key that will toggle the current or last opened plugin panel (accepts modifiers)", description = "The key that will toggle the current or last opened plugin panel (accepts modifiers)",
position = 36, position = 46,
titleSection = "keybindsTitle" section = windowSettings
) )
default Keybind panelToggleKey() default Keybind panelToggleKey()
{ {
return new Keybind(KeyEvent.VK_F12, InputEvent.CTRL_DOWN_MASK); return new Keybind(KeyEvent.VK_F12, InputEvent.CTRL_DOWN_MASK);
} }
@ConfigItem(
keyName = "blockExtraMouseButtons",
name = "Block Extra Mouse Buttons",
description = "Blocks extra mouse buttons (4 and above)",
position = 37,
titleSection = "keybindsTitle"
)
default boolean blockExtraMouseButtons()
{
return false;
}
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, TheStonedTurtle <https://github.com/TheStonedTurtle> * Copyright (c) 2020 Abex
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -22,20 +22,24 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package net.runelite.client.ui.overlay.components.table; package net.runelite.client.config;
import java.awt.Color;
import java.util.Collections;
import java.util.List;
import lombok.Builder;
import lombok.Data; import lombok.Data;
/**
* A profile/save of a OSRS account. Each account can 1 profile per {@link RuneScapeProfileType}
* (ie Standard/League/DMM}.
*/
@Data @Data
@Builder public class RuneScapeProfile
public class TableRow
{ {
Color rowColor; private final String displayName;
TableAlignment rowAlignment; private final RuneScapeProfileType type;
@Builder.Default private final byte[] loginHash;
List<TableElement> elements = Collections.emptyList();
/**
* Profile key used to save configs for this profile to the config store. This will
* always start with {@link ConfigManager#RSPROFILE_GROUP}
*/
private final String key;
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, Craftiii4 <craftiii4@gmail.com> * Copyright (c) 2020 Abex
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -24,27 +24,36 @@
*/ */
package net.runelite.client.config; package net.runelite.client.config;
import java.util.ArrayList; import java.util.function.Predicate;
import java.util.List;
import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor;
import net.runelite.api.Client;
import net.runelite.api.WorldType;
public class ConfigPanelItem @Getter
@RequiredArgsConstructor
public enum RuneScapeProfileType
{ {
STANDARD(client -> true),
BETA(client -> client.getWorldType().contains(WorldType.TOURNAMENT)),
DEADMAN(client -> client.getWorldType().contains(WorldType.DEADMAN)),
TRAILBLAZER_LEAGUE(client -> client.getWorldType().contains(WorldType.LEAGUE)),
;
@Getter(AccessLevel.PUBLIC) private final Predicate<Client> test;
private ConfigPanelItem parent;
@Getter(AccessLevel.PUBLIC) public static RuneScapeProfileType getCurrent(Client client)
private List<ConfigPanelItem> children;
@Getter(AccessLevel.PUBLIC)
private ConfigItemDescriptor item;
public ConfigPanelItem(ConfigPanelItem parent, ConfigItemDescriptor item)
{ {
this.parent = parent; RuneScapeProfileType[] types = values();
this.children = new ArrayList<>(); for (int i = types.length - 1; i >= 0; i--)
this.item = item; {
RuneScapeProfileType type = types[i];
if (types[i].test.test(client))
{
return type;
}
}
return STANDARD;
} }
} }

View File

@@ -1,3 +0,0 @@
package net.runelite.client.config;
public class Title {}

View File

@@ -42,12 +42,8 @@ public @interface Units
String MINUTES = " mins"; String MINUTES = " mins";
String PERCENT = "%"; String PERCENT = "%";
String PIXELS = "px"; String PIXELS = "px";
String POINTS = "pt";
String SECONDS = "s"; String SECONDS = "s";
String TICKS = " ticks"; String TICKS = " ticks";
String LEVELS = " lvls";
String FPS = " fps";
String GP = " GP";
String value(); String value();
} }

View File

@@ -1,91 +0,0 @@
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.conf.Settings;
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()
{
Settings settings = new Settings();
settings.setExecuteLogging(false);
return DSL.using(connection, SQLDialect.H2, settings);
}
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;
}
}

View File

@@ -1,42 +0,0 @@
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/")
)
);
GenerationTool tool = new GenerationTool();
tool.setConnection(c);
tool.run(configuration);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}

View File

@@ -1,62 +0,0 @@
/*
* 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.processing.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.12.3"
},
comments = "This class is generated by jOOQ"
)
@SuppressWarnings({"all", "unchecked", "rawtypes"})
public class DefaultCatalog extends CatalogImpl
{
private static final long serialVersionUID = -102989253;
/**
* 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);
}
}

View File

@@ -1,60 +0,0 @@
/*
* This file is generated by jOOQ.
*/
package net.runelite.client.database.data;
import javax.annotation.processing.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.TmorphSets;
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.12.3"
},
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_LOOTTRACKERDROP_INDEX_6 = Indexes0.FK_LOOTTRACKERDROP_INDEX_6;
public static final Index FK_LOOTTRACKEREVENT_INDEX_6 = Indexes0.FK_LOOTTRACKEREVENT_INDEX_6;
public static final Index FK_USER_INDEX_6 = Indexes0.FK_USER_INDEX_6;
public static final Index PRIMARY_KEY_6 = Indexes0.PRIMARY_KEY_6;
public static final Index TMORPH_SETS_SET_NAME_UINDEX = Indexes0.TMORPH_SETS_SET_NAME_UINDEX;
public static final Index PRIMARY_KEY_2 = Indexes0.PRIMARY_KEY_2;
public static final Index UN_USERNAME_INDEX_2 = Indexes0.UN_USERNAME_INDEX_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_LOOTTRACKERDROP_INDEX_6 = Internal.createIndex("FK_LOOTTRACKERDROP_INDEX_6", Loottrackerlink.LOOTTRACKERLINK, new OrderField[]{Loottrackerlink.LOOTTRACKERLINK.DROPUNIQUEID}, false);
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_USER_INDEX_6 = Internal.createIndex("FK_USER_INDEX_6", Loottrackerlink.LOOTTRACKERLINK, new OrderField[]{Loottrackerlink.LOOTTRACKERLINK.USERUNIQUEID}, false);
public static Index PRIMARY_KEY_6 = Internal.createIndex("PRIMARY_KEY_6", Loottrackerloot.LOOTTRACKERLOOT, new OrderField[]{Loottrackerloot.LOOTTRACKERLOOT.UNIQUEID}, true);
public static Index TMORPH_SETS_SET_NAME_UINDEX = Internal.createIndex("TMORPH_SETS_SET_NAME_UINDEX", TmorphSets.TMORPH_SETS, new OrderField[]{TmorphSets.TMORPH_SETS.SET_NAME}, true);
public static Index PRIMARY_KEY_2 = Internal.createIndex("PRIMARY_KEY_2", User.USER, new OrderField[]{User.USER.UNIQUEID}, true);
public static Index UN_USERNAME_INDEX_2 = Internal.createIndex("UN_USERNAME_INDEX_2", User.USER, new OrderField[]{User.USER.USERNAME}, true);
}
}

View File

@@ -1,76 +0,0 @@
/*
* This file is generated by jOOQ.
*/
package net.runelite.client.database.data;
import javax.annotation.processing.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.12.3"
},
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_LOOTTRACKEREVENTS = UniqueKeys0.PK_LOOTTRACKEREVENTS;
public static final UniqueKey<LoottrackerlootRecord> PK_LOOTTRACKERDROPS = UniqueKeys0.PK_LOOTTRACKERDROPS;
public static final UniqueKey<UserRecord> PK_USER = UniqueKeys0.PK_USER;
public static final UniqueKey<UserRecord> UN_USERNAME = UniqueKeys0.UN_USERNAME;
// -------------------------------------------------------------------------
// FOREIGN KEY definitions
// -------------------------------------------------------------------------
public static final ForeignKey<LoottrackerlinkRecord, LoottrackereventsRecord> FK_LOOTTRACKEREVENT = ForeignKeys0.FK_LOOTTRACKEREVENT;
public static final ForeignKey<LoottrackerlinkRecord, LoottrackerlootRecord> FK_LOOTTRACKERDROP = ForeignKeys0.FK_LOOTTRACKERDROP;
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_LOOTTRACKEREVENTS = Internal.createUniqueKey(Loottrackerevents.LOOTTRACKEREVENTS, "PK_LOOTTRACKEREVENTS", Loottrackerevents.LOOTTRACKEREVENTS.UNIQUEID);
public static final UniqueKey<LoottrackerlootRecord> PK_LOOTTRACKERDROPS = Internal.createUniqueKey(Loottrackerloot.LOOTTRACKERLOOT, "PK_LOOTTRACKERDROPS", Loottrackerloot.LOOTTRACKERLOOT.UNIQUEID);
public static final UniqueKey<UserRecord> PK_USER = Internal.createUniqueKey(User.USER, "PK_USER", User.USER.UNIQUEID);
public static final UniqueKey<UserRecord> UN_USERNAME = Internal.createUniqueKey(User.USER, "UN_USERNAME", User.USER.USERNAME);
}
private static class ForeignKeys0
{
public static final ForeignKey<LoottrackerlinkRecord, LoottrackereventsRecord> FK_LOOTTRACKEREVENT = Internal.createForeignKey(net.runelite.client.database.data.Keys.PK_LOOTTRACKEREVENTS, Loottrackerlink.LOOTTRACKERLINK, "FK_LOOTTRACKEREVENT", Loottrackerlink.LOOTTRACKERLINK.EVENTUNIQUEID);
public static final ForeignKey<LoottrackerlinkRecord, LoottrackerlootRecord> FK_LOOTTRACKERDROP = Internal.createForeignKey(net.runelite.client.database.data.Keys.PK_LOOTTRACKERDROPS, Loottrackerlink.LOOTTRACKERLINK, "FK_LOOTTRACKERDROP", 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.USERUNIQUEID);
}
}

View File

@@ -1,99 +0,0 @@
/*
* 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.processing.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.TmorphSets;
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.12.3"
},
comments = "This class is generated by jOOQ"
)
@SuppressWarnings({"all", "unchecked", "rawtypes"})
public class Public extends SchemaImpl
{
private static final long serialVersionUID = 1268129010;
/**
* 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.TMORPH_SETS</code>.
*/
public final TmorphSets TMORPH_SETS = net.runelite.client.database.data.tables.TmorphSets.TMORPH_SETS;
/**
* 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);
}
@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,
TmorphSets.TMORPH_SETS,
User.USER);
}
}

View File

@@ -1,53 +0,0 @@
/*
* This file is generated by jOOQ.
*/
package net.runelite.client.database.data;
import javax.annotation.processing.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.TmorphSets;
import net.runelite.client.database.data.tables.User;
/**
* Convenience access to all tables in PUBLIC
*/
@Generated(
value = {
"http://www.jooq.org",
"jOOQ version:3.12.3"
},
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 = Loottrackerevents.LOOTTRACKEREVENTS;
/**
* The table <code>PUBLIC.LOOTTRACKERLINK</code>.
*/
public static final Loottrackerlink LOOTTRACKERLINK = Loottrackerlink.LOOTTRACKERLINK;
/**
* The table <code>PUBLIC.LOOTTRACKERLOOT</code>.
*/
public static final Loottrackerloot LOOTTRACKERLOOT = Loottrackerloot.LOOTTRACKERLOOT;
/**
* The table <code>PUBLIC.TMORPH_SETS</code>.
*/
public static final TmorphSets TMORPH_SETS = TmorphSets.TMORPH_SETS;
/**
* The table <code>PUBLIC.USER</code>.
*/
public static final User USER = User.USER;
}

View File

@@ -1,182 +0,0 @@
/*
* 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.processing.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.Row4;
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.12.3"
},
comments = "This class is generated by jOOQ"
)
@SuppressWarnings({"all", "unchecked", "rawtypes"})
public class Loottrackerevents extends TableImpl<LoottrackereventsRecord>
{
private static final long serialVersionUID = 1578403652;
/**
* 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(DSL.name("UNIQUEID"), org.jooq.impl.SQLDataType.UUID.nullable(false), this, "");
/**
* The column <code>PUBLIC.LOOTTRACKEREVENTS.EVENTID</code>.
*/
public final TableField<LoottrackereventsRecord, String> EVENTID = createField(DSL.name("EVENTID"), org.jooq.impl.SQLDataType.VARCHAR(255).nullable(false), this, "");
/**
* The column <code>PUBLIC.LOOTTRACKEREVENTS.TYPE</code>.
*/
public final TableField<LoottrackereventsRecord, String> TYPE = createField(DSL.name("TYPE"), org.jooq.impl.SQLDataType.VARCHAR(255).nullable(false), this, "");
/**
* The column <code>PUBLIC.LOOTTRACKEREVENTS.TIME</code>.
*/
public final TableField<LoottrackereventsRecord, Timestamp> TIME = createField(DSL.name("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);
}
@Override
public Schema getSchema()
{
return Public.PUBLIC;
}
@Override
public List<Index> getIndexes()
{
return Arrays.<Index>asList(Indexes.PRIMARY_KEY_B);
}
@Override
public UniqueKey<LoottrackereventsRecord> getPrimaryKey()
{
return Keys.PK_LOOTTRACKEREVENTS;
}
@Override
public List<UniqueKey<LoottrackereventsRecord>> getKeys()
{
return Arrays.<UniqueKey<LoottrackereventsRecord>>asList(Keys.PK_LOOTTRACKEREVENTS);
}
@Override
public Loottrackerevents as(String alias)
{
return new Loottrackerevents(DSL.name(alias), this);
}
@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);
}
// -------------------------------------------------------------------------
// Row4 type methods
// -------------------------------------------------------------------------
@Override
public Row4<UUID, String, String, Timestamp> fieldsRow()
{
return (Row4) super.fieldsRow();
}
}

View File

@@ -1,189 +0,0 @@
/*
* 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.processing.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.Row4;
import org.jooq.Schema;
import org.jooq.Table;
import org.jooq.TableField;
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.12.3"
},
comments = "This class is generated by jOOQ"
)
@SuppressWarnings({"all", "unchecked", "rawtypes"})
public class Loottrackerlink extends TableImpl<LoottrackerlinkRecord>
{
private static final long serialVersionUID = -1694278583;
/**
* 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(DSL.name("LINKUNIQUEID"), org.jooq.impl.SQLDataType.UUID.nullable(false), this, "");
/**
* The column <code>PUBLIC.LOOTTRACKERLINK.EVENTUNIQUEID</code>.
*/
public final TableField<LoottrackerlinkRecord, UUID> EVENTUNIQUEID = createField(DSL.name("EVENTUNIQUEID"), org.jooq.impl.SQLDataType.UUID.nullable(false), this, "");
/**
* The column <code>PUBLIC.LOOTTRACKERLINK.DROPUNIQUEID</code>.
*/
public final TableField<LoottrackerlinkRecord, UUID> DROPUNIQUEID = createField(DSL.name("DROPUNIQUEID"), org.jooq.impl.SQLDataType.UUID.nullable(false), this, "");
/**
* The column <code>PUBLIC.LOOTTRACKERLINK.USERUNIQUEID</code>.
*/
public final TableField<LoottrackerlinkRecord, UUID> USERUNIQUEID = createField(DSL.name("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);
}
@Override
public Schema getSchema()
{
return Public.PUBLIC;
}
@Override
public List<Index> getIndexes()
{
return Arrays.<Index>asList(Indexes.FK_LOOTTRACKERDROP_INDEX_6, Indexes.FK_LOOTTRACKEREVENT_INDEX_6, Indexes.FK_USER_INDEX_6);
}
@Override
public List<ForeignKey<LoottrackerlinkRecord, ?>> getReferences()
{
return Arrays.<ForeignKey<LoottrackerlinkRecord, ?>>asList(Keys.FK_LOOTTRACKEREVENT, Keys.FK_LOOTTRACKERDROP, Keys.FK_USER);
}
public Loottrackerevents loottrackerevents()
{
return new Loottrackerevents(this, Keys.FK_LOOTTRACKEREVENT);
}
public Loottrackerloot loottrackerloot()
{
return new Loottrackerloot(this, Keys.FK_LOOTTRACKERDROP);
}
public User user()
{
return new User(this, Keys.FK_USER);
}
@Override
public Loottrackerlink as(String alias)
{
return new Loottrackerlink(DSL.name(alias), this);
}
@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);
}
// -------------------------------------------------------------------------
// Row4 type methods
// -------------------------------------------------------------------------
@Override
public Row4<UUID, UUID, UUID, UUID> fieldsRow()
{
return (Row4) super.fieldsRow();
}
}

View File

@@ -1,176 +0,0 @@
/*
* 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.processing.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.Row3;
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.12.3"
},
comments = "This class is generated by jOOQ"
)
@SuppressWarnings({"all", "unchecked", "rawtypes"})
public class Loottrackerloot extends TableImpl<LoottrackerlootRecord>
{
private static final long serialVersionUID = 1461948279;
/**
* 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(DSL.name("UNIQUEID"), org.jooq.impl.SQLDataType.UUID.nullable(false), this, "");
/**
* The column <code>PUBLIC.LOOTTRACKERLOOT.ITEMID</code>.
*/
public final TableField<LoottrackerlootRecord, Integer> ITEMID = createField(DSL.name("ITEMID"), org.jooq.impl.SQLDataType.INTEGER.nullable(false), this, "");
/**
* The column <code>PUBLIC.LOOTTRACKERLOOT.QUANTITY</code>.
*/
public final TableField<LoottrackerlootRecord, Integer> QUANTITY = createField(DSL.name("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);
}
@Override
public Schema getSchema()
{
return Public.PUBLIC;
}
@Override
public List<Index> getIndexes()
{
return Arrays.<Index>asList(Indexes.PRIMARY_KEY_6);
}
@Override
public UniqueKey<LoottrackerlootRecord> getPrimaryKey()
{
return Keys.PK_LOOTTRACKERDROPS;
}
@Override
public List<UniqueKey<LoottrackerlootRecord>> getKeys()
{
return Arrays.<UniqueKey<LoottrackerlootRecord>>asList(Keys.PK_LOOTTRACKERDROPS);
}
@Override
public Loottrackerloot as(String alias)
{
return new Loottrackerloot(DSL.name(alias), this);
}
@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);
}
// -------------------------------------------------------------------------
// Row3 type methods
// -------------------------------------------------------------------------
@Override
public Row3<UUID, Integer, Integer> fieldsRow()
{
return (Row3) super.fieldsRow();
}
}

View File

@@ -1,196 +0,0 @@
/*
* This file is generated by jOOQ.
*/
package net.runelite.client.database.data.tables;
import java.util.Arrays;
import java.util.List;
import javax.annotation.processing.Generated;
import net.runelite.client.database.data.Indexes;
import net.runelite.client.database.data.Public;
import net.runelite.client.database.data.tables.records.TmorphSetsRecord;
import org.jooq.Field;
import org.jooq.ForeignKey;
import org.jooq.Index;
import org.jooq.Name;
import org.jooq.Record;
import org.jooq.Row10;
import org.jooq.Schema;
import org.jooq.Table;
import org.jooq.TableField;
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.12.3"
},
comments = "This class is generated by jOOQ"
)
@SuppressWarnings({"all", "unchecked", "rawtypes"})
public class TmorphSets extends TableImpl<TmorphSetsRecord>
{
private static final long serialVersionUID = -2027086786;
/**
* The reference instance of <code>PUBLIC.TMORPH_SETS</code>
*/
public static final TmorphSets TMORPH_SETS = new TmorphSets();
/**
* The class holding records for this type
*/
@Override
public Class<TmorphSetsRecord> getRecordType()
{
return TmorphSetsRecord.class;
}
/**
* The column <code>PUBLIC.TMORPH_SETS.SET_NAME</code>.
*/
public final TableField<TmorphSetsRecord, String> SET_NAME = createField(DSL.name("SET_NAME"), org.jooq.impl.SQLDataType.VARCHAR(255).nullable(false), this, "");
/**
* The column <code>PUBLIC.TMORPH_SETS.HELMET</code>.
*/
public final TableField<TmorphSetsRecord, Integer> HELMET = createField(DSL.name("HELMET"), org.jooq.impl.SQLDataType.INTEGER.nullable(false), this, "");
/**
* The column <code>PUBLIC.TMORPH_SETS.CAPE</code>.
*/
public final TableField<TmorphSetsRecord, Integer> CAPE = createField(DSL.name("CAPE"), org.jooq.impl.SQLDataType.INTEGER.nullable(false), this, "");
/**
* The column <code>PUBLIC.TMORPH_SETS.AMULET</code>.
*/
public final TableField<TmorphSetsRecord, Integer> AMULET = createField(DSL.name("AMULET"), org.jooq.impl.SQLDataType.INTEGER.nullable(false), this, "");
/**
* The column <code>PUBLIC.TMORPH_SETS.WEAPON</code>.
*/
public final TableField<TmorphSetsRecord, Integer> WEAPON = createField(DSL.name("WEAPON"), org.jooq.impl.SQLDataType.INTEGER.nullable(false), this, "");
/**
* The column <code>PUBLIC.TMORPH_SETS.TORSO</code>.
*/
public final TableField<TmorphSetsRecord, Integer> TORSO = createField(DSL.name("TORSO"), org.jooq.impl.SQLDataType.INTEGER.nullable(false), this, "");
/**
* The column <code>PUBLIC.TMORPH_SETS.SHIELD</code>.
*/
public final TableField<TmorphSetsRecord, Integer> SHIELD = createField(DSL.name("SHIELD"), org.jooq.impl.SQLDataType.INTEGER.nullable(false), this, "");
/**
* The column <code>PUBLIC.TMORPH_SETS.LEGS</code>.
*/
public final TableField<TmorphSetsRecord, Integer> LEGS = createField(DSL.name("LEGS"), org.jooq.impl.SQLDataType.INTEGER.nullable(false), this, "");
/**
* The column <code>PUBLIC.TMORPH_SETS.HANDS</code>.
*/
public final TableField<TmorphSetsRecord, Integer> HANDS = createField(DSL.name("HANDS"), org.jooq.impl.SQLDataType.INTEGER.nullable(false), this, "");
/**
* The column <code>PUBLIC.TMORPH_SETS.BOOTS</code>.
*/
public final TableField<TmorphSetsRecord, Integer> BOOTS = createField(DSL.name("BOOTS"), org.jooq.impl.SQLDataType.INTEGER.nullable(false), this, "");
/**
* Create a <code>PUBLIC.TMORPH_SETS</code> table reference
*/
public TmorphSets()
{
this(DSL.name("TMORPH_SETS"), null);
}
/**
* Create an aliased <code>PUBLIC.TMORPH_SETS</code> table reference
*/
public TmorphSets(String alias)
{
this(DSL.name(alias), TMORPH_SETS);
}
/**
* Create an aliased <code>PUBLIC.TMORPH_SETS</code> table reference
*/
public TmorphSets(Name alias)
{
this(alias, TMORPH_SETS);
}
private TmorphSets(Name alias, Table<TmorphSetsRecord> aliased)
{
this(alias, aliased, null);
}
private TmorphSets(Name alias, Table<TmorphSetsRecord> aliased, Field<?>[] parameters)
{
super(alias, null, aliased, parameters, DSL.comment(""));
}
public <O extends Record> TmorphSets(Table<O> child, ForeignKey<O, TmorphSetsRecord> key)
{
super(child, key, TMORPH_SETS);
}
@Override
public Schema getSchema()
{
return Public.PUBLIC;
}
@Override
public List<Index> getIndexes()
{
return Arrays.<Index>asList(Indexes.TMORPH_SETS_SET_NAME_UINDEX);
}
@Override
public TmorphSets as(String alias)
{
return new TmorphSets(DSL.name(alias), this);
}
@Override
public TmorphSets as(Name alias)
{
return new TmorphSets(alias, this);
}
/**
* Rename this table
*/
@Override
public TmorphSets rename(String name)
{
return new TmorphSets(DSL.name(name), null);
}
/**
* Rename this table
*/
@Override
public TmorphSets rename(Name name)
{
return new TmorphSets(name, null);
}
// -------------------------------------------------------------------------
// Row10 type methods
// -------------------------------------------------------------------------
@Override
public Row10<String, Integer, Integer, Integer, Integer, Integer, Integer, Integer, Integer, Integer> fieldsRow()
{
return (Row10) super.fieldsRow();
}
}

View File

@@ -1,171 +0,0 @@
/*
* 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.processing.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.Row2;
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.12.3"
},
comments = "This class is generated by jOOQ"
)
@SuppressWarnings({"all", "unchecked", "rawtypes"})
public class User extends TableImpl<UserRecord>
{
private static final long serialVersionUID = -668009102;
/**
* 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(DSL.name("UNIQUEID"), org.jooq.impl.SQLDataType.UUID.nullable(false), this, "");
/**
* The column <code>PUBLIC.USER.USERNAME</code>.
*/
public final TableField<UserRecord, String> USERNAME = createField(DSL.name("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);
}
@Override
public Schema getSchema()
{
return Public.PUBLIC;
}
@Override
public List<Index> getIndexes()
{
return Arrays.<Index>asList(Indexes.PRIMARY_KEY_2, Indexes.UN_USERNAME_INDEX_2);
}
@Override
public UniqueKey<UserRecord> getPrimaryKey()
{
return Keys.PK_USER;
}
@Override
public List<UniqueKey<UserRecord>> getKeys()
{
return Arrays.<UniqueKey<UserRecord>>asList(Keys.PK_USER, Keys.UN_USERNAME);
}
@Override
public User as(String alias)
{
return new User(DSL.name(alias), this);
}
@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);
}
// -------------------------------------------------------------------------
// Row2 type methods
// -------------------------------------------------------------------------
@Override
public Row2<UUID, String> fieldsRow()
{
return (Row2) super.fieldsRow();
}
}

View File

@@ -1,258 +0,0 @@
/*
* 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.processing.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.12.3"
},
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 = -1418522415;
/**
* 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
// -------------------------------------------------------------------------
@Override
public Record1<UUID> key()
{
return (Record1) super.key();
}
// -------------------------------------------------------------------------
// Record4 type implementation
// -------------------------------------------------------------------------
@Override
public Row4<UUID, String, String, Timestamp> fieldsRow()
{
return (Row4) super.fieldsRow();
}
@Override
public Row4<UUID, String, String, Timestamp> valuesRow()
{
return (Row4) super.valuesRow();
}
@Override
public Field<UUID> field1()
{
return Loottrackerevents.LOOTTRACKEREVENTS.UNIQUEID;
}
@Override
public Field<String> field2()
{
return Loottrackerevents.LOOTTRACKEREVENTS.EVENTID;
}
@Override
public Field<String> field3()
{
return Loottrackerevents.LOOTTRACKEREVENTS.TYPE;
}
@Override
public Field<Timestamp> field4()
{
return Loottrackerevents.LOOTTRACKEREVENTS.TIME;
}
@Override
public UUID component1()
{
return getUniqueid();
}
@Override
public String component2()
{
return getEventid();
}
@Override
public String component3()
{
return getType();
}
@Override
public Timestamp component4()
{
return getTime();
}
@Override
public UUID value1()
{
return getUniqueid();
}
@Override
public String value2()
{
return getEventid();
}
@Override
public String value3()
{
return getType();
}
@Override
public Timestamp value4()
{
return getTime();
}
@Override
public LoottrackereventsRecord value1(UUID value)
{
setUniqueid(value);
return this;
}
@Override
public LoottrackereventsRecord value2(String value)
{
setEventid(value);
return this;
}
@Override
public LoottrackereventsRecord value3(String value)
{
setType(value);
return this;
}
@Override
public LoottrackereventsRecord value4(Timestamp value)
{
setTime(value);
return this;
}
@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);
}
}

View File

@@ -1,246 +0,0 @@
/*
* This file is generated by jOOQ.
*/
package net.runelite.client.database.data.tables.records;
import java.util.UUID;
import javax.annotation.processing.Generated;
import net.runelite.client.database.data.tables.Loottrackerlink;
import org.jooq.Field;
import org.jooq.Record4;
import org.jooq.Row4;
import org.jooq.impl.TableRecordImpl;
/**
* This class is generated by jOOQ.
*/
@Generated(
value = {
"http://www.jooq.org",
"jOOQ version:3.12.3"
},
comments = "This class is generated by jOOQ"
)
@SuppressWarnings({"all", "unchecked", "rawtypes"})
public class LoottrackerlinkRecord extends TableRecordImpl<LoottrackerlinkRecord> implements Record4<UUID, UUID, UUID, UUID>
{
private static final long serialVersionUID = -1701074584;
/**
* 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);
}
// -------------------------------------------------------------------------
// Record4 type implementation
// -------------------------------------------------------------------------
@Override
public Row4<UUID, UUID, UUID, UUID> fieldsRow()
{
return (Row4) super.fieldsRow();
}
@Override
public Row4<UUID, UUID, UUID, UUID> valuesRow()
{
return (Row4) super.valuesRow();
}
@Override
public Field<UUID> field1()
{
return Loottrackerlink.LOOTTRACKERLINK.LINKUNIQUEID;
}
@Override
public Field<UUID> field2()
{
return Loottrackerlink.LOOTTRACKERLINK.EVENTUNIQUEID;
}
@Override
public Field<UUID> field3()
{
return Loottrackerlink.LOOTTRACKERLINK.DROPUNIQUEID;
}
@Override
public Field<UUID> field4()
{
return Loottrackerlink.LOOTTRACKERLINK.USERUNIQUEID;
}
@Override
public UUID component1()
{
return getLinkuniqueid();
}
@Override
public UUID component2()
{
return getEventuniqueid();
}
@Override
public UUID component3()
{
return getDropuniqueid();
}
@Override
public UUID component4()
{
return getUseruniqueid();
}
@Override
public UUID value1()
{
return getLinkuniqueid();
}
@Override
public UUID value2()
{
return getEventuniqueid();
}
@Override
public UUID value3()
{
return getDropuniqueid();
}
@Override
public UUID value4()
{
return getUseruniqueid();
}
@Override
public LoottrackerlinkRecord value1(UUID value)
{
setLinkuniqueid(value);
return this;
}
@Override
public LoottrackerlinkRecord value2(UUID value)
{
setEventuniqueid(value);
return this;
}
@Override
public LoottrackerlinkRecord value3(UUID value)
{
setDropuniqueid(value);
return this;
}
@Override
public LoottrackerlinkRecord value4(UUID value)
{
setUseruniqueid(value);
return this;
}
@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);
}
}

View File

@@ -1,214 +0,0 @@
/*
* This file is generated by jOOQ.
*/
package net.runelite.client.database.data.tables.records;
import java.util.UUID;
import javax.annotation.processing.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.12.3"
},
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 = 693470968;
/**
* 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
// -------------------------------------------------------------------------
@Override
public Record1<UUID> key()
{
return (Record1) super.key();
}
// -------------------------------------------------------------------------
// Record3 type implementation
// -------------------------------------------------------------------------
@Override
public Row3<UUID, Integer, Integer> fieldsRow()
{
return (Row3) super.fieldsRow();
}
@Override
public Row3<UUID, Integer, Integer> valuesRow()
{
return (Row3) super.valuesRow();
}
@Override
public Field<UUID> field1()
{
return Loottrackerloot.LOOTTRACKERLOOT.UNIQUEID;
}
@Override
public Field<Integer> field2()
{
return Loottrackerloot.LOOTTRACKERLOOT.ITEMID;
}
@Override
public Field<Integer> field3()
{
return Loottrackerloot.LOOTTRACKERLOOT.QUANTITY;
}
@Override
public UUID component1()
{
return getUniqueid();
}
@Override
public Integer component2()
{
return getItemid();
}
@Override
public Integer component3()
{
return getQuantity();
}
@Override
public UUID value1()
{
return getUniqueid();
}
@Override
public Integer value2()
{
return getItemid();
}
@Override
public Integer value3()
{
return getQuantity();
}
@Override
public LoottrackerlootRecord value1(UUID value)
{
setUniqueid(value);
return this;
}
@Override
public LoottrackerlootRecord value2(Integer value)
{
setItemid(value);
return this;
}
@Override
public LoottrackerlootRecord value3(Integer value)
{
setQuantity(value);
return this;
}
@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);
}
}

View File

@@ -1,503 +0,0 @@
/*
* This file is generated by jOOQ.
*/
package net.runelite.client.database.data.tables.records;
import javax.annotation.processing.Generated;
import net.runelite.client.database.data.tables.TmorphSets;
import org.jooq.Field;
import org.jooq.Record10;
import org.jooq.Row10;
import org.jooq.impl.TableRecordImpl;
/**
* This class is generated by jOOQ.
*/
@Generated(
value = {
"http://www.jooq.org",
"jOOQ version:3.12.3"
},
comments = "This class is generated by jOOQ"
)
@SuppressWarnings({"all", "unchecked", "rawtypes"})
public class TmorphSetsRecord extends TableRecordImpl<TmorphSetsRecord> implements Record10<String, Integer, Integer, Integer, Integer, Integer, Integer, Integer, Integer, Integer>
{
private static final long serialVersionUID = 546214401;
/**
* Setter for <code>PUBLIC.TMORPH_SETS.SET_NAME</code>.
*/
public void setSetName(String value)
{
set(0, value);
}
/**
* Getter for <code>PUBLIC.TMORPH_SETS.SET_NAME</code>.
*/
public String getSetName()
{
return (String) get(0);
}
/**
* Setter for <code>PUBLIC.TMORPH_SETS.HELMET</code>.
*/
public void setHelmet(Integer value)
{
set(1, value);
}
/**
* Getter for <code>PUBLIC.TMORPH_SETS.HELMET</code>.
*/
public Integer getHelmet()
{
return (Integer) get(1);
}
/**
* Setter for <code>PUBLIC.TMORPH_SETS.CAPE</code>.
*/
public void setCape(Integer value)
{
set(2, value);
}
/**
* Getter for <code>PUBLIC.TMORPH_SETS.CAPE</code>.
*/
public Integer getCape()
{
return (Integer) get(2);
}
/**
* Setter for <code>PUBLIC.TMORPH_SETS.AMULET</code>.
*/
public void setAmulet(Integer value)
{
set(3, value);
}
/**
* Getter for <code>PUBLIC.TMORPH_SETS.AMULET</code>.
*/
public Integer getAmulet()
{
return (Integer) get(3);
}
/**
* Setter for <code>PUBLIC.TMORPH_SETS.WEAPON</code>.
*/
public void setWeapon(Integer value)
{
set(4, value);
}
/**
* Getter for <code>PUBLIC.TMORPH_SETS.WEAPON</code>.
*/
public Integer getWeapon()
{
return (Integer) get(4);
}
/**
* Setter for <code>PUBLIC.TMORPH_SETS.TORSO</code>.
*/
public void setTorso(Integer value)
{
set(5, value);
}
/**
* Getter for <code>PUBLIC.TMORPH_SETS.TORSO</code>.
*/
public Integer getTorso()
{
return (Integer) get(5);
}
/**
* Setter for <code>PUBLIC.TMORPH_SETS.SHIELD</code>.
*/
public void setShield(Integer value)
{
set(6, value);
}
/**
* Getter for <code>PUBLIC.TMORPH_SETS.SHIELD</code>.
*/
public Integer getShield()
{
return (Integer) get(6);
}
/**
* Setter for <code>PUBLIC.TMORPH_SETS.LEGS</code>.
*/
public void setLegs(Integer value)
{
set(7, value);
}
/**
* Getter for <code>PUBLIC.TMORPH_SETS.LEGS</code>.
*/
public Integer getLegs()
{
return (Integer) get(7);
}
/**
* Setter for <code>PUBLIC.TMORPH_SETS.HANDS</code>.
*/
public void setHands(Integer value)
{
set(8, value);
}
/**
* Getter for <code>PUBLIC.TMORPH_SETS.HANDS</code>.
*/
public Integer getHands()
{
return (Integer) get(8);
}
/**
* Setter for <code>PUBLIC.TMORPH_SETS.BOOTS</code>.
*/
public void setBoots(Integer value)
{
set(9, value);
}
/**
* Getter for <code>PUBLIC.TMORPH_SETS.BOOTS</code>.
*/
public Integer getBoots()
{
return (Integer) get(9);
}
// -------------------------------------------------------------------------
// Record10 type implementation
// -------------------------------------------------------------------------
@Override
public Row10<String, Integer, Integer, Integer, Integer, Integer, Integer, Integer, Integer, Integer> fieldsRow()
{
return (Row10) super.fieldsRow();
}
@Override
public Row10<String, Integer, Integer, Integer, Integer, Integer, Integer, Integer, Integer, Integer> valuesRow()
{
return (Row10) super.valuesRow();
}
@Override
public Field<String> field1()
{
return TmorphSets.TMORPH_SETS.SET_NAME;
}
@Override
public Field<Integer> field2()
{
return TmorphSets.TMORPH_SETS.HELMET;
}
@Override
public Field<Integer> field3()
{
return TmorphSets.TMORPH_SETS.CAPE;
}
@Override
public Field<Integer> field4()
{
return TmorphSets.TMORPH_SETS.AMULET;
}
@Override
public Field<Integer> field5()
{
return TmorphSets.TMORPH_SETS.WEAPON;
}
@Override
public Field<Integer> field6()
{
return TmorphSets.TMORPH_SETS.TORSO;
}
@Override
public Field<Integer> field7()
{
return TmorphSets.TMORPH_SETS.SHIELD;
}
@Override
public Field<Integer> field8()
{
return TmorphSets.TMORPH_SETS.LEGS;
}
@Override
public Field<Integer> field9()
{
return TmorphSets.TMORPH_SETS.HANDS;
}
@Override
public Field<Integer> field10()
{
return TmorphSets.TMORPH_SETS.BOOTS;
}
@Override
public String component1()
{
return getSetName();
}
@Override
public Integer component2()
{
return getHelmet();
}
@Override
public Integer component3()
{
return getCape();
}
@Override
public Integer component4()
{
return getAmulet();
}
@Override
public Integer component5()
{
return getWeapon();
}
@Override
public Integer component6()
{
return getTorso();
}
@Override
public Integer component7()
{
return getShield();
}
@Override
public Integer component8()
{
return getLegs();
}
@Override
public Integer component9()
{
return getHands();
}
@Override
public Integer component10()
{
return getBoots();
}
@Override
public String value1()
{
return getSetName();
}
@Override
public Integer value2()
{
return getHelmet();
}
@Override
public Integer value3()
{
return getCape();
}
@Override
public Integer value4()
{
return getAmulet();
}
@Override
public Integer value5()
{
return getWeapon();
}
@Override
public Integer value6()
{
return getTorso();
}
@Override
public Integer value7()
{
return getShield();
}
@Override
public Integer value8()
{
return getLegs();
}
@Override
public Integer value9()
{
return getHands();
}
@Override
public Integer value10()
{
return getBoots();
}
@Override
public TmorphSetsRecord value1(String value)
{
setSetName(value);
return this;
}
@Override
public TmorphSetsRecord value2(Integer value)
{
setHelmet(value);
return this;
}
@Override
public TmorphSetsRecord value3(Integer value)
{
setCape(value);
return this;
}
@Override
public TmorphSetsRecord value4(Integer value)
{
setAmulet(value);
return this;
}
@Override
public TmorphSetsRecord value5(Integer value)
{
setWeapon(value);
return this;
}
@Override
public TmorphSetsRecord value6(Integer value)
{
setTorso(value);
return this;
}
@Override
public TmorphSetsRecord value7(Integer value)
{
setShield(value);
return this;
}
@Override
public TmorphSetsRecord value8(Integer value)
{
setLegs(value);
return this;
}
@Override
public TmorphSetsRecord value9(Integer value)
{
setHands(value);
return this;
}
@Override
public TmorphSetsRecord value10(Integer value)
{
setBoots(value);
return this;
}
@Override
public TmorphSetsRecord values(String value1, Integer value2, Integer value3, Integer value4, Integer value5, Integer value6, Integer value7, Integer value8, Integer value9, Integer value10)
{
value1(value1);
value2(value2);
value3(value3);
value4(value4);
value5(value5);
value6(value6);
value7(value7);
value8(value8);
value9(value9);
value10(value10);
return this;
}
// -------------------------------------------------------------------------
// Constructors
// -------------------------------------------------------------------------
/**
* Create a detached TmorphSetsRecord
*/
public TmorphSetsRecord()
{
super(TmorphSets.TMORPH_SETS);
}
/**
* Create a detached, initialised TmorphSetsRecord
*/
public TmorphSetsRecord(String setName, Integer helmet, Integer cape, Integer amulet, Integer weapon, Integer torso, Integer shield, Integer legs, Integer hands, Integer boots)
{
super(TmorphSets.TMORPH_SETS);
set(0, setName);
set(1, helmet);
set(2, cape);
set(3, amulet);
set(4, weapon);
set(5, torso);
set(6, shield);
set(7, legs);
set(8, hands);
set(9, boots);
}
}

View File

@@ -1,171 +0,0 @@
/*
* This file is generated by jOOQ.
*/
package net.runelite.client.database.data.tables.records;
import java.util.UUID;
import javax.annotation.processing.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.12.3"
},
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 = 2077804101;
/**
* 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
// -------------------------------------------------------------------------
@Override
public Record1<UUID> key()
{
return (Record1) super.key();
}
// -------------------------------------------------------------------------
// Record2 type implementation
// -------------------------------------------------------------------------
@Override
public Row2<UUID, String> fieldsRow()
{
return (Row2) super.fieldsRow();
}
@Override
public Row2<UUID, String> valuesRow()
{
return (Row2) super.valuesRow();
}
@Override
public Field<UUID> field1()
{
return User.USER.UNIQUEID;
}
@Override
public Field<String> field2()
{
return User.USER.USERNAME;
}
@Override
public UUID component1()
{
return getUniqueid();
}
@Override
public String component2()
{
return getUsername();
}
@Override
public UUID value1()
{
return getUniqueid();
}
@Override
public String value2()
{
return getUsername();
}
@Override
public UserRecord value1(UUID value)
{
setUniqueid(value);
return this;
}
@Override
public UserRecord value2(String value)
{
setUsername(value);
return this;
}
@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);
}
}

View File

@@ -198,7 +198,7 @@ public class DiscordService implements AutoCloseable
{ {
log.info("Discord RPC service is ready with user {}.", user.username); log.info("Discord RPC service is ready with user {}.", user.username);
currentUser = user; currentUser = user;
eventBus.post(DiscordReady.class, new DiscordReady( eventBus.post(new DiscordReady(
user.userId, user.userId,
user.username, user.username,
user.discriminator, user.discriminator,
@@ -208,31 +208,31 @@ public class DiscordService implements AutoCloseable
private void disconnected(int errorCode, String message) private void disconnected(int errorCode, String message)
{ {
log.debug("Discord disconnected {}: {}", errorCode, message); log.debug("Discord disconnected {}: {}", errorCode, message);
eventBus.post(DiscordDisconnected.class, new DiscordDisconnected(errorCode, message)); eventBus.post(new DiscordDisconnected(errorCode, message));
} }
private void errored(int errorCode, String message) private void errored(int errorCode, String message)
{ {
log.warn("Discord error: {} - {}", errorCode, message); log.warn("Discord error: {} - {}", errorCode, message);
eventBus.post(DiscordErrored.class, new DiscordErrored(errorCode, message)); eventBus.post(new DiscordErrored(errorCode, message));
} }
private void joinGame(String joinSecret) private void joinGame(String joinSecret)
{ {
log.debug("Discord join game: {}", joinSecret); log.debug("Discord join game: {}", joinSecret);
eventBus.post(DiscordJoinGame.class, new DiscordJoinGame(joinSecret)); eventBus.post(new DiscordJoinGame(joinSecret));
} }
private void spectateGame(String spectateSecret) private void spectateGame(String spectateSecret)
{ {
log.debug("Discord spectate game: {}", spectateSecret); log.debug("Discord spectate game: {}", spectateSecret);
eventBus.post(DiscordSpectateGame.class, new DiscordSpectateGame(spectateSecret)); eventBus.post(new DiscordSpectateGame(spectateSecret));
} }
private void joinRequest(DiscordUser user) private void joinRequest(DiscordUser user)
{ {
log.debug("Discord join request: {}", user); log.debug("Discord join request: {}", user);
eventBus.post(DiscordJoinRequest.class, new DiscordJoinRequest( eventBus.post(new DiscordJoinRequest(
user.userId, user.userId,
user.username, user.username,
user.discriminator, user.discriminator,

View File

@@ -25,13 +25,12 @@
package net.runelite.client.discord.events; package net.runelite.client.discord.events;
import lombok.Value; import lombok.Value;
import net.runelite.api.events.Event;
/** /**
* Called when the RPC connection has been severed * Called when the RPC connection has been severed
*/ */
@Value @Value
public class DiscordDisconnected implements Event public class DiscordDisconnected
{ {
/** /**
* Discord error code * Discord error code

View File

@@ -25,13 +25,12 @@
package net.runelite.client.discord.events; package net.runelite.client.discord.events;
import lombok.Value; import lombok.Value;
import net.runelite.api.events.Event;
/** /**
* Called when an internal error is caught within the SDK * Called when an internal error is caught within the SDK
*/ */
@Value @Value
public class DiscordErrored implements Event public class DiscordErrored
{ {
/** /**
* Discord error code. * Discord error code.

View File

@@ -25,13 +25,12 @@
package net.runelite.client.discord.events; package net.runelite.client.discord.events;
import lombok.Value; import lombok.Value;
import net.runelite.api.events.Event;
/** /**
* Called when the logged in user joined a game * Called when the logged in user joined a game
*/ */
@Value @Value
public class DiscordJoinGame implements Event public class DiscordJoinGame
{ {
/** /**
* Obfuscated data of your choosing used as join secret * Obfuscated data of your choosing used as join secret

View File

@@ -25,13 +25,12 @@
package net.runelite.client.discord.events; package net.runelite.client.discord.events;
import lombok.Value; import lombok.Value;
import net.runelite.api.events.Event;
/** /**
* Called when another discord user wants to join the game of the logged in user * Called when another discord user wants to join the game of the logged in user
*/ */
@Value @Value
public class DiscordJoinRequest implements Event public class DiscordJoinRequest
{ {
/** /**
* The userId for the user that requests to join * The userId for the user that requests to join

View File

@@ -25,13 +25,12 @@
package net.runelite.client.discord.events; package net.runelite.client.discord.events;
import lombok.Value; import lombok.Value;
import net.runelite.api.events.Event;
/** /**
* Called when the RPC connection has been established * Called when the RPC connection has been established
*/ */
@Value @Value
public class DiscordReady implements Event public class DiscordReady
{ {
/** /**
* The userId for the active user * The userId for the active user

View File

@@ -25,13 +25,12 @@
package net.runelite.client.discord.events; package net.runelite.client.discord.events;
import lombok.Value; import lombok.Value;
import net.runelite.api.events.Event;
/** /**
* Called when the logged in user joined to spectate a game * Called when the logged in user joined to spectate a game
*/ */
@Value @Value
public class DiscordSpectateGame implements Event public class DiscordSpectateGame
{ {
/** /**
* Obfuscated data of your choosing used as spectate secret * Obfuscated data of your choosing used as spectate secret

View File

@@ -1,85 +0,0 @@
package net.runelite.client.eventbus;
import com.google.common.collect.ImmutableSet;
import io.reactivex.rxjava3.functions.Consumer;
import java.lang.invoke.CallSite;
import java.lang.invoke.LambdaMetafactory;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
import static java.lang.invoke.MethodType.methodType;
import java.lang.reflect.Method;
import java.util.Set;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.events.Event;
@Slf4j
public class AccessorGenerator
{
public static Set<Subscription> scanSubscribes(Lookup caller, Object ref)
{
ImmutableSet.Builder<Subscription> builder = ImmutableSet.builder();
final Class<?> refClass = ref.getClass();
caller = getPrivateAccess(refClass, caller).in(refClass);
for (Method method : refClass.getDeclaredMethods())
{
Subscribe sub = method.getAnnotation(Subscribe.class);
if (sub != null)
{
final Consumer accessor;
final Class paramType = method.getParameterTypes()[0];
try
{
accessor = getConsumerFor(caller, ref, method);
}
catch (Throwable t)
{
log.warn("Creating consumer lambda for {} failed!", method, t);
continue;
}
builder.add(new Subscription(paramType, accessor, sub.takeUntil(), sub.subscribe(), sub.observe()));
}
}
return builder.build();
}
@SuppressWarnings("unchecked")
private static <EVENT extends Event> Consumer<EVENT> getConsumerFor(Lookup caller, Object ref, Method method) throws Throwable
{
final MethodHandle methodHandle = caller.unreflect(method);
final MethodType actualConsumer = methodHandle.type().dropParameterTypes(0, 1);
final MethodType eventsConsumer = actualConsumer.erase();
final MethodType factoryType = methodType(Consumer.class, ref.getClass());
final CallSite callsite = LambdaMetafactory.metafactory(
caller, // To get past security checks
"accept", // The name of the method to implement inside the lambda type
factoryType, // Signature of the factory method
eventsConsumer, // Signature of function implementation
methodHandle, // Target method
actualConsumer // Target method signature
);
final MethodHandle factory = callsite.getTarget();
return (Consumer<EVENT>) factory.invoke(ref);
}
private static Lookup getPrivateAccess(Class<?> into, Lookup from)
{
try
{
return MethodHandles.privateLookupIn(into, from);
}
catch (IllegalAccessException a)
{
log.warn("Failed to get private access in {} from {}", into, from, a);
return from;
}
}
}

View File

@@ -1,117 +1,230 @@
/*
* 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; package net.runelite.client.eventbus;
import com.jakewharton.rxrelay3.PublishRelay; import com.google.common.base.Preconditions;
import com.jakewharton.rxrelay3.Relay; import com.google.common.collect.HashMultimap;
import io.reactivex.rxjava3.annotations.NonNull; import com.google.common.collect.ImmutableMultimap;
import io.reactivex.rxjava3.core.ObservableTransformer; import com.google.common.collect.Multimap;
import io.reactivex.rxjava3.core.Scheduler; import java.lang.invoke.CallSite;
import io.reactivex.rxjava3.disposables.CompositeDisposable; import java.lang.invoke.LambdaMetafactory;
import io.reactivex.rxjava3.disposables.Disposable; import java.lang.invoke.MethodHandle;
import io.reactivex.rxjava3.functions.Consumer; import java.lang.invoke.MethodHandles;
import java.util.HashMap; import java.lang.invoke.MethodType;
import java.util.Map; import java.lang.reflect.Method;
import java.util.Objects; import java.lang.reflect.Modifier;
import javax.annotation.Nullable; import java.util.Comparator;
import javax.inject.Inject; import java.util.function.Consumer;
import javax.inject.Singleton; import javax.annotation.Nonnull;
import javax.annotation.concurrent.ThreadSafe;
import lombok.EqualsAndHashCode;
import lombok.RequiredArgsConstructor;
import lombok.Value;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.runelite.api.events.Event; import net.runelite.client.util.ReflectUtil;
import net.runelite.client.config.OpenOSRSConfig;
@Slf4j @Slf4j
@Singleton @RequiredArgsConstructor
public class EventBus implements EventBusInterface @ThreadSafe
public class EventBus
{ {
private final Map<Object, Object> subscriptionList = new HashMap<>(); @FunctionalInterface
private final Map<Class<?>, Relay<Object>> subjectList = new HashMap<>(); public interface SubscriberMethod
private final Map<Object, CompositeDisposable> subscriptionsMap = new HashMap<>();
@Inject
private OpenOSRSConfig openOSRSConfig;
@NonNull
private <T extends Event> Relay<Object> getSubject(Class<T> eventClass)
{ {
return subjectList.computeIfAbsent(eventClass, k -> PublishRelay.create().toSerialized()); void invoke(Object event);
} }
@NonNull @Value
private CompositeDisposable getCompositeDisposable(@NonNull Object object) private static class Subscriber
{ {
CompositeDisposable compositeDisposable = subscriptionsMap.get(object); private final Object object;
if (compositeDisposable == null) private final Method method;
private final float priority;
@EqualsAndHashCode.Exclude
private final SubscriberMethod lamda;
void invoke(final Object arg) throws Exception
{ {
compositeDisposable = new CompositeDisposable(); if (lamda != null)
subscriptionsMap.put(object, compositeDisposable); {
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);
} }
return compositeDisposable; builder.orderValuesBy(Comparator.comparing(Subscriber::getPriority).reversed()
.thenComparing(s -> s.object.getClass().getName()));
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 = ReflectUtil.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, sub.priority(), lambda);
builder.put(parameterClazz, subscriber);
log.debug("Registering {} - {}", parameterClazz, subscriber);
}
}
subscribers = builder.build();
} }
private <T> ObservableTransformer<T, T> applyTake(int until) /**
* Unregisters all subscribed methods from provided subscriber object.
*
* @param object object to unsubscribe from
*/
public synchronized void unregister(@Nonnull final Object object)
{ {
return observable -> until > 0 ? observable.take(until) : observable; if (subscribers == null)
}
private <T> ObservableTransformer<T, T> applyScheduler(EventScheduler eventScheduler, boolean subscribe)
{
Scheduler scheduler = eventScheduler.get();
return observable -> scheduler == null ? observable : subscribe ? observable.subscribeOn(scheduler) : observable.observeOn(scheduler);
}
@Override
public <T extends Event> void subscribe(Class<T> eventClass, @NonNull Object lifecycle, @NonNull Consumer<T> action)
{
subscribe(eventClass, lifecycle, action, -1, EventScheduler.DEFAULT, EventScheduler.DEFAULT);
}
@Override
public <T extends Event> void subscribe(Class<T> eventClass, @NonNull Object lifecycle, @NonNull Consumer<T> action, int takeUtil)
{
subscribe(eventClass, lifecycle, action, takeUtil, EventScheduler.DEFAULT, EventScheduler.DEFAULT);
}
@Override
// Subscribe on lifecycle (for example from plugin startUp -> shutdown)
public <T extends Event> void subscribe(Class<T> eventClass, @NonNull Object lifecycle, @NonNull Consumer<T> action, int takeUntil, @Nullable EventScheduler subscribe, @Nullable EventScheduler observe)
{
assert Event.class.isAssignableFrom(eventClass) : "Parameters of methods annotated with @Subscribe should implement net.runelite.api.events.Event";
if (subscriptionList.containsKey(lifecycle) && eventClass.equals(subscriptionList.get(lifecycle)))
{ {
return; return;
} }
Disposable disposable = getSubject(eventClass) final Multimap<Class, Subscriber> map = HashMultimap.create();
.compose(applyTake(takeUntil)) map.putAll(subscribers);
.filter(Objects::nonNull) // Filter out null objects, better safe than sorry
.cast(eventClass) // Cast it for easier usage
.doFinally(() -> unregister(lifecycle))
.compose(applyScheduler(subscribe, true))
.compose(applyScheduler(observe, false))
.subscribe(action, error ->
log.error("Exception in eventbus", error));
getCompositeDisposable(lifecycle).add(disposable); for (Class<?> clazz = object.getClass(); clazz != null; clazz = clazz.getSuperclass())
subscriptionList.put(lifecycle, eventClass); {
for (final Method method : clazz.getDeclaredMethods())
{
final Subscribe sub = method.getAnnotation(Subscribe.class);
if (sub == null)
{
continue;
}
final Class<?> parameterClazz = method.getParameterTypes()[0];
map.remove(parameterClazz, new Subscriber(object, method, sub.priority(), null));
}
}
subscribers = ImmutableMultimap.copyOf(map);
} }
@Override /**
public void unregister(@NonNull Object lifecycle) * Posts provided event to all registered subscribers. Subscriber calls are invoked immediately,
* ordered by priority then their declaring class' name.
*
* @param event event to post
*/
public void post(@Nonnull final Object event)
{ {
//We have to remove the composition from the map, because once you dispose it can't be used anymore for (final Subscriber subscriber : subscribers.get(event.getClass()))
CompositeDisposable compositeDisposable = subscriptionsMap.remove(lifecycle);
subscriptionList.remove(lifecycle);
if (compositeDisposable != null)
{ {
compositeDisposable.dispose(); try
{
subscriber.invoke(event);
}
catch (Exception e)
{
exceptionHandler.accept(e);
}
} }
} }
@Override
public <T extends Event> void post(Class<? extends T> eventClass, @NonNull T event)
{
getSubject(eventClass).accept(event);
}
} }

View File

@@ -1,18 +0,0 @@
package net.runelite.client.eventbus;
import io.reactivex.rxjava3.annotations.NonNull;
import io.reactivex.rxjava3.functions.Consumer;
import net.runelite.api.events.Event;
public interface EventBusInterface
{
<T extends Event> void subscribe(Class<T> eventClass, @NonNull Object lifecycle, @NonNull Consumer<T> action);
<T extends Event> void subscribe(Class<T> eventClass, @NonNull Object lifecycle, @NonNull Consumer<T> action, int takeUntil);
<T extends Event> void subscribe(Class<T> eventClass, @NonNull Object lifecycle, @NonNull Consumer<T> action, int takeUntil, EventScheduler subscribe, EventScheduler observe);
void unregister(@NonNull Object lifecycle);
<T extends Event> void post(Class<? extends T> eventClass, @NonNull T event);
}

View File

@@ -1,35 +0,0 @@
package net.runelite.client.eventbus;
import io.reactivex.rxjava3.core.Scheduler;
import io.reactivex.rxjava3.functions.Supplier;
import io.reactivex.rxjava3.schedulers.Schedulers;
import javax.annotation.Nullable;
import lombok.AllArgsConstructor;
@AllArgsConstructor
public enum EventScheduler
{
DEFAULT(() -> null),
COMPUTATION(Schedulers::computation),
IO(Schedulers::io),
NEWTHREAD(Schedulers::newThread),
SINGLE(Schedulers::single),
TRAMPOLINE(Schedulers::trampoline),
CLIENT(Schedulers::single);
private Supplier<Scheduler> scheduler;
@Nullable
public Scheduler get()
{
try
{
return scheduler.get();
}
catch (Throwable ignored)
{
}
return null;
}
}

View File

@@ -38,7 +38,5 @@ import java.lang.annotation.Target;
@Documented @Documented
public @interface Subscribe public @interface Subscribe
{ {
int takeUntil() default -1; float priority() default 0;
EventScheduler subscribe() default EventScheduler.DEFAULT;
EventScheduler observe() default EventScheduler.DEFAULT;
} }

View File

@@ -1,20 +0,0 @@
package net.runelite.client.eventbus;
import io.reactivex.rxjava3.functions.Consumer;
import lombok.Value;
@Value
public class Subscription
{
private final Class type;
private final Consumer method;
private final int takeUntil;
private final EventScheduler subscribe;
private final EventScheduler observe;
@SuppressWarnings("unchecked")
public void subscribe(EventBus eventBus, Object lifecycle)
{
eventBus.subscribe(type, lifecycle, method, takeUntil, subscribe, observe);
}
}

View File

@@ -1,34 +0,0 @@
package net.runelite.client.events;
import lombok.Value;
import net.runelite.api.Player;
import net.runelite.api.events.Event;
import net.runelite.client.game.AttackStyle;
/**
* This will fire when {@link net.runelite.client.game.PlayerManager} detects
* a change in the player appearance that resulted in the shifting of an attack style.
* For example, ranged str went to 0, but melee str went to 108.
*/
@Value
public class AttackStyleChanged implements Event
{
/**
* The player that changed styles.
*/
Player player;
/**
* Can be Unknown(nullable)
*
* @see net.runelite.client.game.AttackStyle
*/
AttackStyle oldStyle;
/**
* Can be Unknown(nullable)
*
* @see net.runelite.client.game.AttackStyle
*/
AttackStyle newStyle;
}

View File

@@ -24,18 +24,7 @@
*/ */
package net.runelite.client.events; package net.runelite.client.events;
import lombok.Getter; public abstract class ChatInput
import net.runelite.api.events.Event;
public abstract class ChatInput implements Event
{ {
@Getter
private boolean stop = false;
public void setStop()
{
this.stop = true;
}
public abstract void resume(); public abstract void resume();
} }

View File

@@ -31,13 +31,12 @@ import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import lombok.Value; import lombok.Value;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.runelite.api.events.Event;
@Value @Value
@Slf4j @Slf4j
public class ClientShutdown implements Event public class ClientShutdown
{ {
Queue<Future<?>> tasks = new ConcurrentLinkedQueue<>(); private Queue<Future<?>> tasks = new ConcurrentLinkedQueue<>();
public void waitFor(Future<?> future) public void waitFor(Future<?> future)
{ {

View File

@@ -24,15 +24,15 @@
*/ */
package net.runelite.client.events; package net.runelite.client.events;
import java.io.Serializable; import javax.annotation.Nullable;
import lombok.Data; import lombok.Data;
import net.runelite.api.events.Event; import net.runelite.client.config.RuneScapeProfile;
/** /**
* An event where a configuration entry has been modified. * An event where a configuration entry has been modified.
*/ */
@Data @Data
public class ConfigChanged implements Event, Serializable public class ConfigChanged
{ {
/** /**
* The parent group for the key. * The parent group for the key.
@@ -41,6 +41,14 @@ public class ConfigChanged implements Event, Serializable
* between other key values that may have the same name. * between other key values that may have the same name.
*/ */
private String group; private String group;
/**
* The profile that has changed, if any
*
* @see RuneScapeProfile#getKey()
*/
@Nullable
private String profile;
/** /**
* The configuration key that has been modified. * The configuration key that has been modified.
*/ */
@@ -53,12 +61,4 @@ public class ConfigChanged implements Event, Serializable
* The new value of the entry, null if the entry has been unset. * The new value of the entry, null if the entry has been unset.
*/ */
private String newValue; private String newValue;
/**
* The client where the config value was changed from
*/
private String origin;
/**
* Path of the current config file
*/
private String path;
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019 Owain van Brakel <https://github.com/Owain94> * Copyright (c) 2019 Abex
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -24,14 +24,15 @@
*/ */
package net.runelite.client.events; package net.runelite.client.events;
import lombok.Data; import java.util.List;
import net.runelite.api.events.Event; import lombok.Value;
import net.runelite.client.plugins.Plugin; import net.runelite.client.externalplugins.ExternalPluginManifest;
@Data /**
public class ExternalPluginChanged implements Event * Posted when an external plugin has been added, removed, or updated
*/
@Value
public class ExternalPluginsChanged
{ {
private final String pluginId; private final List<ExternalPluginManifest> loadedManifest;
private final Plugin plugin;
private final boolean added;
} }

View File

@@ -1,32 +0,0 @@
/*
* Copyright (c) 2019 Owain van Brakel <https://github.com/Owain94>
* 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.events;
import lombok.Data;
import net.runelite.api.events.Event;
@Data
public class ExternalPluginsLoaded implements Event
{}

View File

@@ -25,13 +25,12 @@
package net.runelite.client.events; package net.runelite.client.events;
import lombok.Value; import lombok.Value;
import net.runelite.api.events.Event;
import net.runelite.client.ui.overlay.OverlayMenuEntry; import net.runelite.client.ui.overlay.OverlayMenuEntry;
import net.runelite.client.ui.overlay.infobox.InfoBox; import net.runelite.client.ui.overlay.infobox.InfoBox;
@Value @Value
public class InfoBoxMenuClicked implements Event public class InfoBoxMenuClicked
{ {
OverlayMenuEntry entry; private OverlayMenuEntry entry;
InfoBox infoBox; private InfoBox infoBox;
} }

View File

@@ -25,11 +25,10 @@
package net.runelite.client.events; package net.runelite.client.events;
import lombok.Value; import lombok.Value;
import net.runelite.api.events.Event;
import net.runelite.client.ui.NavigationButton; import net.runelite.client.ui.NavigationButton;
@Value @Value
public class NavigationButtonAdded implements Event public class NavigationButtonAdded
{ {
NavigationButton button; private NavigationButton button;
} }

View File

@@ -25,11 +25,10 @@
package net.runelite.client.events; package net.runelite.client.events;
import lombok.Value; import lombok.Value;
import net.runelite.api.events.Event;
import net.runelite.client.ui.NavigationButton; import net.runelite.client.ui.NavigationButton;
@Value @Value
public class NavigationButtonRemoved implements Event public class NavigationButtonRemoved
{ {
NavigationButton button; private NavigationButton button;
} }

View File

@@ -26,11 +26,10 @@ package net.runelite.client.events;
import java.awt.TrayIcon; import java.awt.TrayIcon;
import lombok.Value; import lombok.Value;
import net.runelite.api.events.Event;
@Value @Value
public class NotificationFired implements Event public class NotificationFired
{ {
String message; final String message;
TrayIcon.MessageType type; final TrayIcon.MessageType type;
} }

View File

@@ -27,12 +27,11 @@ package net.runelite.client.events;
import java.util.Collection; import java.util.Collection;
import lombok.Value; import lombok.Value;
import net.runelite.api.NPC; import net.runelite.api.NPC;
import net.runelite.api.events.Event;
import net.runelite.client.game.ItemStack; import net.runelite.client.game.ItemStack;
@Value @Value
public class NpcLootReceived implements Event public class NpcLootReceived
{ {
NPC npc; private final NPC npc;
Collection<ItemStack> items; private final Collection<ItemStack> items;
} }

View File

@@ -24,18 +24,15 @@
*/ */
package net.runelite.client.events; package net.runelite.client.events;
import lombok.AllArgsConstructor; import lombok.Value;
import lombok.Data;
import net.runelite.api.events.Event;
import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayMenuEntry; import net.runelite.client.ui.overlay.OverlayMenuEntry;
/** /**
* Event fired when an overlay menu entry is clicked. * Event fired when an overlay menu entry is clicked.
*/ */
@Data @Value
@AllArgsConstructor public class OverlayMenuClicked
public class OverlayMenuClicked implements Event
{ {
private OverlayMenuEntry entry; private OverlayMenuEntry entry;
private Overlay overlay; private Overlay overlay;

View File

@@ -26,10 +26,9 @@ package net.runelite.client.events;
import java.util.UUID; import java.util.UUID;
import lombok.Value; import lombok.Value;
import net.runelite.api.events.Event;
@Value @Value
public class PartyChanged implements Event public class PartyChanged
{ {
UUID partyId; private final UUID partyId;
} }

View File

@@ -27,12 +27,11 @@ package net.runelite.client.events;
import java.util.Collection; import java.util.Collection;
import lombok.Value; import lombok.Value;
import net.runelite.api.Player; import net.runelite.api.Player;
import net.runelite.api.events.Event;
import net.runelite.client.game.ItemStack; import net.runelite.client.game.ItemStack;
@Value @Value
public class PlayerLootReceived implements Event public class PlayerLootReceived
{ {
Player player; private final Player player;
Collection<ItemStack> items; private final Collection<ItemStack> items;
} }

View File

@@ -25,11 +25,10 @@
package net.runelite.client.events; package net.runelite.client.events;
import lombok.Data; import lombok.Data;
import net.runelite.api.events.Event;
import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.Plugin;
@Data @Data
public class PluginChanged implements Event public class PluginChanged
{ {
private final Plugin plugin; private final Plugin plugin;
private final boolean loaded; private final boolean loaded;

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019 Owain van Brakel <https://github.com/Owain94> * Copyright (c) 2020 Abex
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -24,12 +24,11 @@
*/ */
package net.runelite.client.events; package net.runelite.client.events;
import lombok.Data; /**
import net.runelite.api.events.Event; * Posted when the user switches to a different RuneScape save profile
* This might be because they logged into a different account, or hopped
@Data * to/from a Beta/Tournament/DMM/Leagues world
public class ExternalRepositoryChanged implements Event */
public class RuneScapeProfileChanged
{ {
private final String owner;
private final boolean added;
} }

View File

@@ -25,7 +25,6 @@
package net.runelite.client.events; package net.runelite.client.events;
import lombok.Data; import lombok.Data;
import net.runelite.api.events.Event;
/** /**
* An event where a new RuneLite account session has been closed, * An event where a new RuneLite account session has been closed,
@@ -35,4 +34,7 @@ import net.runelite.api.events.Event;
* it has nothing to do with whether an account is being logged out. * it has nothing to do with whether an account is being logged out.
*/ */
@Data @Data
public class SessionClose implements Event {} public class SessionClose
{
}

View File

@@ -25,7 +25,6 @@
package net.runelite.client.events; package net.runelite.client.events;
import lombok.Data; import lombok.Data;
import net.runelite.api.events.Event;
/** /**
* An event where a new RuneLite account session has been opened * An event where a new RuneLite account session has been opened
@@ -35,4 +34,7 @@ import net.runelite.api.events.Event;
* it has nothing to do with whether an account is being logged in. * it has nothing to do with whether an account is being logged in.
*/ */
@Data @Data
public class SessionOpen implements Event {} public class SessionOpen
{
}

View File

@@ -25,14 +25,13 @@
package net.runelite.client.events; package net.runelite.client.events;
import lombok.Value; import lombok.Value;
import net.runelite.api.events.Event;
import net.runelite.http.api.worlds.WorldResult; import net.runelite.http.api.worlds.WorldResult;
/** /**
* Fired when the @{link net.runelite.client.game.WorldService} refreshes the world list * Fired when the @{link net.runelite.client.game.WorldService} refreshes the world list
*/ */
@Value @Value
public class WorldsFetch implements Event public class WorldsFetch
{ {
WorldResult worldResult; private final WorldResult worldResult;
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017, Adam <Adam@sigterm.info> * Copyright (c) 2019 Abex
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -22,17 +22,20 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package net.runelite.client.ui.components; package net.runelite.client.externalplugins;
import java.awt.Dimension; import java.net.URL;
import javax.swing.JPanel; import java.net.URLClassLoader;
import net.runelite.client.ui.PluginPanel; import lombok.Getter;
class FixedWidthPanel extends JPanel class ExternalPluginClassLoader extends URLClassLoader
{ {
@Override @Getter
public Dimension getPreferredSize() private final ExternalPluginManifest manifest;
ExternalPluginClassLoader(ExternalPluginManifest manifest, URL[] urls)
{ {
return new Dimension(PluginPanel.PANEL_WIDTH, super.getPreferredSize().height); super(urls, ExternalPluginClassLoader.class.getClassLoader());
this.manifest = manifest;
} }
} }

View File

@@ -0,0 +1,175 @@
/*
* Copyright (c) 2019 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.externalplugins;
import com.google.common.reflect.TypeToken;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.util.List;
import javax.imageio.ImageIO;
import javax.inject.Inject;
import lombok.extern.slf4j.Slf4j;
import net.runelite.client.RuneLiteProperties;
import net.runelite.client.util.VerificationException;
import net.runelite.http.api.RuneLiteAPI;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okio.BufferedSource;
@Slf4j
public class ExternalPluginClient
{
private final OkHttpClient okHttpClient;
@Inject
private ExternalPluginClient(OkHttpClient okHttpClient)
{
this.okHttpClient = okHttpClient;
}
public List<ExternalPluginManifest> downloadManifest() throws IOException, VerificationException
{
HttpUrl manifest = RuneLiteProperties.getPluginHubBase()
.newBuilder()
.addPathSegments("manifest.js")
.build();
try (Response res = okHttpClient.newCall(new Request.Builder().url(manifest).build()).execute())
{
if (res.code() != 200)
{
throw new IOException("Non-OK response code: " + res.code());
}
BufferedSource src = res.body().source();
byte[] signature = new byte[src.readInt()];
src.readFully(signature);
byte[] data = src.readByteArray();
Signature s = Signature.getInstance("SHA256withRSA");
s.initVerify(loadCertificate());
s.update(data);
if (!s.verify(signature))
{
throw new VerificationException("Unable to verify external plugin manifest");
}
return RuneLiteAPI.GSON.fromJson(new String(data, StandardCharsets.UTF_8),
new TypeToken<List<ExternalPluginManifest>>()
{
}.getType());
}
catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e)
{
throw new RuntimeException(e);
}
}
public BufferedImage downloadIcon(ExternalPluginManifest plugin) throws IOException
{
if (!plugin.hasIcon())
{
return null;
}
HttpUrl url = RuneLiteProperties.getPluginHubBase()
.newBuilder()
.addPathSegment(plugin.getInternalName())
.addPathSegment(plugin.getCommit() + ".png")
.build();
try (Response res = okHttpClient.newCall(new Request.Builder().url(url).build()).execute())
{
byte[] bytes = res.body().bytes();
// We don't stream so the lock doesn't block the edt trying to load something at the same time
synchronized (ImageIO.class)
{
return ImageIO.read(new ByteArrayInputStream(bytes));
}
}
}
private static Certificate loadCertificate()
{
try
{
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
Certificate certificate = certFactory.generateCertificate(ExternalPluginClient.class.getResourceAsStream("externalplugins.crt"));
return certificate;
}
catch (CertificateException e)
{
throw new RuntimeException(e);
}
}
void submitPlugins(List<String> plugins)
{
if (plugins.isEmpty())
{
return;
}
HttpUrl url = RuneLiteAPI.getApiBase().newBuilder()
.addPathSegment("pluginhub")
.build();
Request request = new Request.Builder()
.url(url)
.post(RequestBody.create(RuneLiteAPI.JSON, RuneLiteAPI.GSON.toJson(plugins)))
.build();
okHttpClient.newCall(request).enqueue(new Callback()
{
@Override
public void onFailure(Call call, IOException e)
{
log.debug("Error submitting plugins", e);
}
@Override
public void onResponse(Call call, Response response)
{
log.debug("Submitted plugin list");
response.close();
}
});
}
}

View File

@@ -0,0 +1,429 @@
/*
* Copyright (c) 2019 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.externalplugins;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.hash.Hashing;
import com.google.common.hash.HashingInputStream;
import com.google.common.io.Files;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import javax.swing.SwingUtilities;
import lombok.extern.slf4j.Slf4j;
import net.runelite.client.RuneLite;
import net.runelite.client.RuneLiteProperties;
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.ExternalPluginsChanged;
import net.runelite.client.events.SessionClose;
import net.runelite.client.events.SessionOpen;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginInstantiationException;
import net.runelite.client.plugins.PluginManager;
import net.runelite.client.ui.SplashScreen;
import net.runelite.client.util.CountingInputStream;
import net.runelite.client.util.Text;
import net.runelite.client.util.VerificationException;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
@Singleton
@Slf4j
public class ExternalPluginManager
{
private static final String PLUGIN_LIST_KEY = "externalPlugins";
private static Class<? extends Plugin>[] builtinExternals = null;
@Inject
@Named("safeMode")
private boolean safeMode;
private final ConfigManager configManager;
private final ExternalPluginClient externalPluginClient;
private final ScheduledExecutorService executor;
private final PluginManager pluginManager;
private final EventBus eventBus;
private final OkHttpClient okHttpClient;
@Inject
private ExternalPluginManager(
ConfigManager configManager,
ExternalPluginClient externalPluginClient,
ScheduledExecutorService executor,
PluginManager pluginManager,
EventBus eventBus,
OkHttpClient okHttpClient
)
{
this.configManager = configManager;
this.externalPluginClient = externalPluginClient;
this.executor = executor;
this.pluginManager = pluginManager;
this.eventBus = eventBus;
this.okHttpClient = okHttpClient;
executor.scheduleWithFixedDelay(() -> externalPluginClient.submitPlugins(getInstalledExternalPlugins()),
new Random().nextInt(60), 180, TimeUnit.MINUTES);
}
public void loadExternalPlugins() throws PluginInstantiationException
{
refreshPlugins();
if (builtinExternals != null)
{
// builtin external's don't actually have a manifest or a separate classloader...
pluginManager.loadPlugins(Lists.newArrayList(builtinExternals), null);
}
}
@Subscribe
public void onSessionOpen(SessionOpen event)
{
executor.submit(this::refreshPlugins);
}
@Subscribe
public void onSessionClose(SessionClose event)
{
executor.submit(this::refreshPlugins);
}
private void refreshPlugins()
{
if (safeMode)
{
log.debug("External plugins are disabled in safe mode!");
return;
}
Multimap<ExternalPluginManifest, Plugin> loadedExternalPlugins = HashMultimap.create();
for (Plugin p : pluginManager.getPlugins())
{
ExternalPluginManifest m = getExternalPluginManifest(p.getClass());
if (m != null)
{
loadedExternalPlugins.put(m, p);
}
}
List<String> installedIDs = getInstalledExternalPlugins();
if (installedIDs.isEmpty() && loadedExternalPlugins.isEmpty())
{
return;
}
boolean startup = SplashScreen.isOpen();
try
{
double splashStart = startup ? .60 : 0;
double splashLength = startup ? .10 : 1;
if (!startup)
{
SplashScreen.init();
}
SplashScreen.stage(splashStart, null, "Downloading external plugins");
Set<ExternalPluginManifest> externalPlugins = new HashSet<>();
RuneLite.PLUGINS_DIR.mkdirs();
List<ExternalPluginManifest> manifestList;
try
{
manifestList = externalPluginClient.downloadManifest();
Map<String, ExternalPluginManifest> manifests = manifestList
.stream().collect(ImmutableMap.toImmutableMap(ExternalPluginManifest::getInternalName, Function.identity()));
Set<ExternalPluginManifest> needsDownload = new HashSet<>();
Set<File> keep = new HashSet<>();
for (String name : installedIDs)
{
ExternalPluginManifest manifest = manifests.get(name);
if (manifest != null)
{
externalPlugins.add(manifest);
if (!manifest.isValid())
{
needsDownload.add(manifest);
}
else
{
keep.add(manifest.getJarFile());
}
}
}
// delete old plugins
File[] files = RuneLite.PLUGINS_DIR.listFiles();
if (files != null)
{
for (File fi : files)
{
if (!keep.contains(fi))
{
fi.delete();
}
}
}
int toDownload = needsDownload.stream().mapToInt(ExternalPluginManifest::getSize).sum();
int downloaded = 0;
for (ExternalPluginManifest manifest : needsDownload)
{
HttpUrl url = RuneLiteProperties.getPluginHubBase().newBuilder()
.addPathSegment(manifest.getInternalName())
.addPathSegment(manifest.getCommit() + ".jar")
.build();
try (Response res = okHttpClient.newCall(new Request.Builder().url(url).build()).execute())
{
int fdownloaded = downloaded;
downloaded += manifest.getSize();
HashingInputStream his = new HashingInputStream(Hashing.sha256(),
new CountingInputStream(res.body().byteStream(), i ->
SplashScreen.stage(splashStart + (splashLength * .2), splashStart + (splashLength * .8),
null, "Downloading " + manifest.getDisplayName(),
i + fdownloaded, toDownload, true)));
Files.asByteSink(manifest.getJarFile()).writeFrom(his);
if (!his.hash().toString().equals(manifest.getHash()))
{
throw new VerificationException("Plugin " + manifest.getInternalName() + " didn't match its hash");
}
}
catch (IOException | VerificationException e)
{
externalPlugins.remove(manifest);
log.error("Unable to download external plugin \"{}\"", manifest.getInternalName(), e);
}
}
}
catch (IOException | VerificationException e)
{
log.error("Unable to download external plugins", e);
return;
}
SplashScreen.stage(splashStart + (splashLength * .8), null, "Starting external plugins");
// TODO(abex): make sure the plugins get fully removed from the scheduler/eventbus/other managers (iterate and check classloader)
Set<ExternalPluginManifest> add = new HashSet<>();
for (ExternalPluginManifest ex : externalPlugins)
{
if (loadedExternalPlugins.removeAll(ex).size() <= 0)
{
add.add(ex);
}
}
// list of loaded external plugins that aren't in the manifest
Collection<Plugin> remove = loadedExternalPlugins.values();
for (Plugin p : remove)
{
log.info("Stopping external plugin \"{}\"", p.getClass());
try
{
SwingUtilities.invokeAndWait(() ->
{
try
{
pluginManager.stopPlugin(p);
}
catch (Exception e)
{
throw new RuntimeException(e);
}
});
}
catch (InterruptedException | InvocationTargetException e)
{
log.warn("Unable to stop external plugin \"{}\"", p.getClass().getName(), e);
}
pluginManager.remove(p);
}
for (ExternalPluginManifest manifest : add)
{
// I think this can't happen, but just in case
if (!manifest.isValid())
{
log.warn("Invalid plugin for validated manifest: {}", manifest);
continue;
}
log.info("Loading external plugin \"{}\" version \"{}\" commit \"{}\"", manifest.getInternalName(), manifest.getVersion(), manifest.getCommit());
List<Plugin> newPlugins = null;
try
{
ClassLoader cl = new ExternalPluginClassLoader(manifest, new URL[]{manifest.getJarFile().toURI().toURL()});
List<Class<?>> clazzes = new ArrayList<>();
for (String className : manifest.getPlugins())
{
clazzes.add(cl.loadClass(className));
}
List<Plugin> newPlugins2 = newPlugins = pluginManager.loadPlugins(clazzes, null);
if (!startup)
{
pluginManager.loadDefaultPluginConfiguration(newPlugins);
SwingUtilities.invokeAndWait(() ->
{
try
{
for (Plugin p : newPlugins2)
{
pluginManager.startPlugin(p);
}
}
catch (PluginInstantiationException e)
{
throw new RuntimeException(e);
}
});
}
}
catch (ThreadDeath e)
{
throw e;
}
catch (Throwable e)
{
log.warn("Unable to start or load external plugin \"{}\"", manifest.getInternalName(), e);
if (newPlugins != null)
{
for (Plugin p : newPlugins)
{
try
{
SwingUtilities.invokeAndWait(() ->
{
try
{
pluginManager.stopPlugin(p);
}
catch (Exception e2)
{
throw new RuntimeException(e2);
}
});
}
catch (InterruptedException | InvocationTargetException e2)
{
log.info("Unable to fully stop plugin \"{}\"", manifest.getInternalName(), e2);
}
pluginManager.remove(p);
}
}
}
}
if (!startup)
{
eventBus.post(new ExternalPluginsChanged(manifestList));
}
}
finally
{
if (!startup)
{
SplashScreen.stop();
}
}
}
public List<String> getInstalledExternalPlugins()
{
String externalPluginsStr = configManager.getConfiguration(RuneLiteConfig.GROUP_NAME, PLUGIN_LIST_KEY);
return Text.fromCSV(externalPluginsStr == null ? "" : externalPluginsStr);
}
public void install(String key)
{
Set<String> plugins = new HashSet<>(getInstalledExternalPlugins());
if (plugins.add(key))
{
configManager.setConfiguration(RuneLiteConfig.GROUP_NAME, PLUGIN_LIST_KEY, Text.toCSV(plugins));
executor.submit(this::refreshPlugins);
}
}
public void remove(String key)
{
Set<String> plugins = new HashSet<>(getInstalledExternalPlugins());
if (plugins.remove(key))
{
configManager.setConfiguration(RuneLiteConfig.GROUP_NAME, PLUGIN_LIST_KEY, Text.toCSV(plugins));
executor.submit(this::refreshPlugins);
}
}
public void update()
{
executor.submit(this::refreshPlugins);
}
public static ExternalPluginManifest getExternalPluginManifest(Class<? extends Plugin> plugin)
{
ClassLoader cl = plugin.getClassLoader();
if (cl instanceof ExternalPluginClassLoader)
{
ExternalPluginClassLoader ecl = (ExternalPluginClassLoader) cl;
return ecl.getManifest();
}
return null;
}
public static void loadBuiltin(Class<? extends Plugin>... plugins)
{
builtinExternals = plugins;
}
}

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, TheStonedTurtle <http://www.github.com/TheStonedTurtle> * Copyright (c) 2019 Abex
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -22,23 +22,68 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package net.runelite.client.ui.components; package net.runelite.client.externalplugins;
import com.google.common.hash.Hashing;
import com.google.common.io.Files;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.swing.Icon; import lombok.Data;
import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode;
import lombok.Getter; import net.runelite.client.RuneLite;
/** @Data
* Used with ComboBoxListRenderer to render an icon next to the text of the list entry. public class ExternalPluginManifest
* Also supports adding a data object to be used for more complex selection logic
*/
@AllArgsConstructor
@Getter
public class ComboBoxIconEntry
{ {
private Icon icon; private String internalName;
private String text; private String commit;
private String hash;
private int size;
private String[] plugins;
private String displayName;
private String version;
private String author;
@Nullable @Nullable
private Object data; private String description;
@Nullable
private String warning;
@Nullable
private String[] tags;
@EqualsAndHashCode.Exclude
private URL support;
private boolean hasIcon;
public boolean hasIcon()
{
return hasIcon;
}
File getJarFile()
{
return new File(RuneLite.PLUGINS_DIR, internalName + commit + ".jar");
}
boolean isValid()
{
File file = getJarFile();
try
{
if (file.exists())
{
String hash = Files.asByteSource(file).hash(Hashing.sha256()).toString();
if (this.hash.equals(hash))
{
return true;
}
}
}
catch (IOException e)
{
}
return false;
}
} }

View File

@@ -28,56 +28,57 @@ package net.runelite.client.game;
import lombok.Getter; import lombok.Getter;
import static net.runelite.api.NullObjectID.*; import static net.runelite.api.NullObjectID.*;
import static net.runelite.api.ObjectID.*; import static net.runelite.api.ObjectID.*;
import net.runelite.api.TileObject;
import net.runelite.api.coords.WorldPoint; import net.runelite.api.coords.WorldPoint;
@Getter @Getter
public enum AgilityShortcut public enum AgilityShortcut
{ {
GENERIC_SHORTCUT(1, "Shortcut", null, GENERIC_SHORTCUT(1, "Shortcut", null,
// Trollheim // Trollheim
ROCKS_3790, ROCKS_3791, ROCKS_3790, ROCKS_3791,
// Fremennik Slayer Cave // Fremennik Slayer Cave
STEPS_29993, STEPS_29993,
// Fossil Island // Fossil Island
LADDER_30938, LADDER_30939, LADDER_30940, LADDER_30941, RUBBER_CAP_MUSHROOM, LADDER_30938, LADDER_30939, LADDER_30940, LADDER_30941, RUBBER_CAP_MUSHROOM,
// Brimhaven dungeon // Brimhaven dungeon
CREVICE_30198, CREVICE_30198,
// Lumbridge // Lumbridge
STILE_12982, STILE_12982,
// Gu'Tanoth Bridge // Gu'Tanoth Bridge
GAP, GAP_2831, GAP, GAP_2831,
// Lumbridge Swamp Caves // Lumbridge Swamp Caves
STEPPING_STONE_5948, STEPPING_STONE_5949, ROCKS_6673, STEPPING_STONE_5948, STEPPING_STONE_5949, ROCKS_6673,
// Morytania Pirate Ship // Morytania Pirate Ship
ROCK_16115, ROCK_16115,
// Lumber Yard // Lumber Yard
BROKEN_FENCE_2618, BROKEN_FENCE_2618,
// McGrubor's Wood // McGrubor's Wood
LOOSE_RAILING, LOOSE_RAILING,
// Underwater Area Fossil Island // Underwater Area Fossil Island
TUNNEL_30959, HOLE_30966, OBSTACLE, OBSTACLE_30767, OBSTACLE_30964, OBSTACLE_30962, PLANT_DOOR_30961, TUNNEL_30959, HOLE_30966, OBSTACLE, OBSTACLE_30767, OBSTACLE_30964, OBSTACLE_30962, PLANT_DOOR_30961,
// Tree Gnome Village // Tree Gnome Village
LOOSE_RAILING_2186, LOOSE_RAILING_2186,
// Burgh de Rott // Burgh de Rott
LOW_FENCE, LOW_FENCE,
// Taverley // Taverley
STILE, STILE,
// Asgarnian Ice Dungeon // Asgarnian Ice Dungeon
STEPS, STEPS,
// Fossil Island Wyvern Cave // Fossil Island Wyvern Cave
STAIRS_31485, STAIRS_31485,
// Trollweiss Mountain Cave // Trollweiss Mountain Cave
ROCKY_HANDHOLDS, ROCKY_HANDHOLDS_19847, ROCKY_HANDHOLDS, ROCKY_HANDHOLDS_19847,
// Witchaven Dungeon // Witchaven Dungeon
SHORTCUT), SHORTCUT),
BRIMHAVEN_DUNGEON_MEDIUM_PIPE_RETURN(1, "Pipe Squeeze", null, new WorldPoint(2698, 9491, 0), PIPE_21727), BRIMHAVEN_DUNGEON_MEDIUM_PIPE_RETURN(1, "Pipe Squeeze", null, new WorldPoint(2698, 9491, 0), PIPE_21727),
BRIMHAVEN_DUNGEON_PIPE_RETURN(1, "Pipe Squeeze", null, new WorldPoint(2655, 9573, 0), PIPE_21728), BRIMHAVEN_DUNGEON_PIPE_RETURN(1, "Pipe Squeeze", null, new WorldPoint(2655, 9573, 0), PIPE_21728),
BRIMHAVEN_DUNGEON_STEPPING_STONES_RETURN(1, "Pipe Squeeze", null, STEPPING_STONE_21739), BRIMHAVEN_DUNGEON_STEPPING_STONES_RETURN(1, "Pipe Squeeze", null, STEPPING_STONE_21739),
BRIMHAVEN_DUNGEON_LOG_BALANCE_RETURN(1, "Log Balance", null, LOG_BALANCE_20884), BRIMHAVEN_DUNGEON_LOG_BALANCE_RETURN(1, "Log Balance", null, LOG_BALANCE_20884),
AGILITY_PYRAMID_ROCKS_WEST(1, "Rocks", null, CLIMBING_ROCKS_11948), AGILITY_PYRAMID_ROCKS_WEST(1, "Rocks", null, CLIMBING_ROCKS_11948),
CAIRN_ISLE_CLIMBING_ROCKS(1, "Rocks", null, CLIMBING_ROCKS), CAIRN_ISLE_CLIMBING_ROCKS(1, "Rocks", null, CLIMBING_ROCKS),
KARAMJA_GLIDER_LOG(1, "Log Balance", new WorldPoint(2906, 3050, 0), A_WOODEN_LOG), 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), 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_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), 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), CORSAIR_COVE_ROCKS(10, "Rocks", new WorldPoint(2545, 2871, 0), ROCKS_31757),
@@ -88,7 +89,7 @@ public enum AgilityShortcut
GOBLIN_VILLAGE_WALL(14, "Wall", new WorldPoint(2925, 3523, 0), TIGHTGAP), 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), CORSAIR_COVE_DUNGEON_PILLAR(15, "Pillar Jump", new WorldPoint(1980, 8996, 0), PILLAR_31809),
EDGEVILLE_DUNGEON_MONKEYBARS(15, "Monkey Bars", null, MONKEYBARS_23566), 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_UNDERWALL_TUNNEL(16, "Underwall Tunnel", new WorldPoint(2574, 3109, 0), HOLE_16520, CASTLE_WALL),
KOUREND_CATACOMBS_SOUTH_WEST_CREVICE_NORTH(17, "Crevice", new WorldPoint(1647, 10008, 0), CRACK_28892), KOUREND_CATACOMBS_SOUTH_WEST_CREVICE_NORTH(17, "Crevice", new WorldPoint(1647, 10008, 0), CRACK_28892),
KOUREND_CATACOMBS_SOUTH_WEST_CREVICE_SOUTH(17, "Crevice", new WorldPoint(1645, 10001, 0), CRACK_28892), KOUREND_CATACOMBS_SOUTH_WEST_CREVICE_SOUTH(17, "Crevice", new WorldPoint(1645, 10001, 0), CRACK_28892),
@@ -151,7 +152,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), 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), RELEKKA_EAST_FENCE(57, "Fence", new WorldPoint(2688, 3697, 0), BROKEN_FENCE),
YANILLE_DUNGEON_MONKEY_BARS(57, "Monkey Bars", null, MONKEYBARS_23567), 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(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), 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), 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),
@@ -182,9 +183,17 @@ public enum AgilityShortcut
TAVERLEY_DUNGEON_PIPE_BLUE_DRAGON(70, "Pipe Squeeze", new WorldPoint(2886, 9798, 0), OBSTACLE_PIPE_16509), 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_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), TAVERLEY_DUNGEON_ROCKS_SOUTH(70, "Rocks", new WorldPoint(2887, 9631, 0), ROCKS, ROCKS_14106),
FOSSIL_ISLAND_HARDWOOD_NORTH(70, "Hole", new WorldPoint(3712, 3828, 0), HOLE_31481, HOLE_31482), FOSSIL_ISLAND_HARDWOOD_NORTH(70, "Hole" , new WorldPoint(3712, 3828, 0), HOLE_31481, HOLE_31482),
FOSSIL_ISLAND_HARDWOOD_SOUTH(70, "Hole", new WorldPoint(3714, 3816, 0), HOLE_31481, HOLE_31482), FOSSIL_ISLAND_HARDWOOD_SOUTH(70, "Hole" , new WorldPoint(3714, 3816, 0), HOLE_31481, HOLE_31482),
AL_KHARID_WINDOW(70, "Window", new WorldPoint(3293, 3158, 0), BROKEN_WALL_33344, BIG_WINDOW), AL_KHARID_WINDOW(70, "Window", new WorldPoint(3295, 3158, 0), BROKEN_WALL_33344, BIG_WINDOW)
{
@Override
public boolean matches(TileObject object)
{
// there are two BIG_WINDOW objects right next to each other here, but only this one is valid
return object.getId() != BIG_WINDOW || object.getWorldLocation().equals(getWorldLocation());
}
},
GWD_SARADOMIN_ROPE_NORTH(70, "Rope Descent", new WorldPoint(2912, 5300, 0), NULL_26371, NULL_26561), GWD_SARADOMIN_ROPE_NORTH(70, "Rope Descent", new WorldPoint(2912, 5300, 0), NULL_26371, NULL_26561),
GWD_SARADOMIN_ROPE_SOUTH(70, "Rope Descent", new WorldPoint(2951, 5267, 0), NULL_26375, NULL_26562), GWD_SARADOMIN_ROPE_SOUTH(70, "Rope Descent", new WorldPoint(2951, 5267, 0), NULL_26375, NULL_26562),
GU_TANOTH_CRUMBLING_WALL(71, "Rocks", new WorldPoint(2545, 3032, 0), CRUMBLING_WALL_40355, ROCKS_40356), GU_TANOTH_CRUMBLING_WALL(71, "Rocks", new WorldPoint(2545, 3032, 0), CRUMBLING_WALL_40355, ROCKS_40356),
@@ -192,14 +201,14 @@ public enum AgilityShortcut
SLAYER_TOWER_ADVANCED_CHAIN_SECOND(71, "Spiked Chain (Floor 3)", new WorldPoint(3446, 3576, 0), SPIKEY_CHAIN_16538), 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), 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), 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), LAVA_DRAGON_ISLE_JUMP(74, "Stepping Stone", new WorldPoint(3200, 3807, 0), STEPPING_STONE_14918),
FORTHOS_DUNGEON_SPIKED_BLADES(75, "Spiked Blades", new WorldPoint(1819, 9946, 0), STRANGE_FLOOR_34834), FORTHOS_DUNGEON_SPIKED_BLADES(75, "Spiked Blades", new WorldPoint(1819, 9946, 0), STRANGE_FLOOR_34834),
REVENANT_CAVES_DEMONS_JUMP(75, "Jump", new WorldPoint(3199, 10135, 0), PILLAR_31561), REVENANT_CAVES_DEMONS_JUMP(75, "Jump", new WorldPoint(3199, 10135, 0), PILLAR_31561),
REVENANT_CAVES_ANKOU_EAST(75, "Jump", new WorldPoint(3201, 10195, 0), PILLAR_31561), REVENANT_CAVES_ANKOU_EAST(75, "Jump", new WorldPoint(3201, 10195, 0), PILLAR_31561),
REVENANT_CAVES_ANKOU_NORTH(75, "Jump", new WorldPoint(3180, 10209, 0), PILLAR_31561), REVENANT_CAVES_ANKOU_NORTH(75, "Jump", new WorldPoint(3180, 10209, 0), PILLAR_31561),
ZUL_ANDRA_ISLAND_CROSSING(76, "Stepping Stone", new WorldPoint(2156, 3073, 0), STEPPING_STONE_10663), ZUL_ANDRA_ISLAND_CROSSING(76, "Stepping Stone", new WorldPoint(2156, 3073, 0), STEPPING_STONE_10663),
SHILO_VILLAGE_STEPPING_STONES(77, "Stepping Stones", new WorldPoint(2863, 2974, 0), STEPPING_STONE_16466), SHILO_VILLAGE_STEPPING_STONES( 77, "Stepping Stones", new WorldPoint(2863, 2974, 0), STEPPING_STONE_16466),
IORWERTHS_DUNGEON_NORTHERN_SHORTCUT_EAST(78, "Tight Gap", new WorldPoint(3221, 12441, 0), TIGHT_GAP), IORWERTHS_DUNGEON_NORTHERN_SHORTCUT_EAST(78, "Tight Gap", new WorldPoint(3221, 12441, 0), TIGHT_GAP),
IORWERTHS_DUNGEON_NORTHERN_SHORTCUT_WEST(78, "Tight Gap", new WorldPoint(3215, 12441, 0), TIGHT_GAP_36693), IORWERTHS_DUNGEON_NORTHERN_SHORTCUT_WEST(78, "Tight Gap", new WorldPoint(3215, 12441, 0), TIGHT_GAP_36693),
KHARAZI_JUNGLE_VINE_CLIMB(79, "Vine", new WorldPoint(2897, 2939, 0), NULL_26884, NULL_26886), KHARAZI_JUNGLE_VINE_CLIMB(79, "Vine", new WorldPoint(2897, 2939, 0), NULL_26884, NULL_26886),
@@ -265,4 +274,9 @@ public enum AgilityShortcut
{ {
return description + " - Level " + level; return description + " - Level " + level;
} }
public boolean matches(TileObject object)
{
return true;
}
} }

View File

@@ -1,43 +0,0 @@
/*
* Copyright (c) 2019, ganom <https://github.com/Ganom>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.client.game;
import java.awt.Color;
import lombok.AllArgsConstructor;
import lombok.Getter;
import net.runelite.api.Prayer;
@AllArgsConstructor
@Getter
public enum AttackStyle
{
MAGE("Mage", Color.CYAN, Prayer.PROTECT_FROM_MAGIC),
RANGE("Range", Color.GREEN, Prayer.PROTECT_FROM_MISSILES),
MELEE("Melee", Color.RED, Prayer.PROTECT_FROM_MELEE),
UNKNOWN("Unknown", Color.WHITE, null);
private String name;
private Color color;
private Prayer prayer;
}

View File

@@ -1,24 +0,0 @@
package net.runelite.client.game;
import lombok.Value;
@Value
public class CombatStats
{
private int magicAttack;
private int magicDefence;
private int magicStr;
private int meleeAtkCrush;
private int meleeAtkSlash;
private int meleeAtkStab;
private int meleeAttack;
private int meleeDefCrush;
private int meleeDefence;
private int meleeDefSlash;
private int meleeDefStab;
private int meleeStr;
private int rangeAttack;
private int rangeDefence;
private int rangeStr;
private int speed;
}

View File

@@ -36,18 +36,18 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import net.runelite.api.Client;
import net.runelite.api.FriendsChatManager;
import net.runelite.api.FriendsChatMember; import net.runelite.api.FriendsChatMember;
import net.runelite.api.FriendsChatManager;
import net.runelite.api.FriendsChatRank; import net.runelite.api.FriendsChatRank;
import net.runelite.api.Client;
import net.runelite.api.GameState; import net.runelite.api.GameState;
import net.runelite.api.IndexedSprite; import net.runelite.api.IndexedSprite;
import net.runelite.api.SpriteID; import net.runelite.api.SpriteID;
import net.runelite.api.events.FriendsChatChanged; import net.runelite.api.events.FriendsChatChanged;
import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GameStateChanged;
import net.runelite.api.util.Text; import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.eventbus.EventBus;
import net.runelite.client.util.ImageUtil; import net.runelite.client.util.ImageUtil;
import net.runelite.client.util.Text;
@Singleton @Singleton
public class FriendChatManager public class FriendChatManager
@@ -74,7 +74,7 @@ public class FriendChatManager
private final LoadingCache<String, FriendsChatRank> ranksCache = CacheBuilder.newBuilder() private final LoadingCache<String, FriendsChatRank> ranksCache = CacheBuilder.newBuilder()
.maximumSize(100) .maximumSize(100)
.expireAfterWrite(1, TimeUnit.MINUTES) .expireAfterWrite(1, TimeUnit.MINUTES)
.build(new CacheLoader<>() .build(new CacheLoader<String, FriendsChatRank>()
{ {
@Override @Override
public FriendsChatRank load(@Nonnull String key) public FriendsChatRank load(@Nonnull String key)
@@ -93,15 +93,10 @@ public class FriendChatManager
private int offset; private int offset;
@Inject @Inject
private FriendChatManager(final Client client, private FriendChatManager(Client client, SpriteManager spriteManager)
final SpriteManager spriteManager,
final EventBus eventbus)
{ {
this.client = client; this.client = client;
this.spriteManager = spriteManager; this.spriteManager = spriteManager;
eventbus.subscribe(GameStateChanged.class, this, this::onGameStateChanged);
eventbus.subscribe(FriendsChatChanged.class, this, this::onFriendsChatChanged);
} }
public boolean isMember(String name) public boolean isMember(String name)
@@ -131,14 +126,16 @@ public class FriendChatManager
return offset + friendsChatRank.ordinal() - 1; return offset + friendsChatRank.ordinal() - 1;
} }
private void onGameStateChanged(GameStateChanged gameStateChanged) @Subscribe
public void onGameStateChanged(GameStateChanged gameStateChanged)
{ {
if (gameStateChanged.getGameState() == GameState.LOGGED_IN && offset == 0) if (gameStateChanged.getGameState() == GameState.LOGIN_SCREEN && offset == 0)
{ {
loadRankIcons(); loadRankIcons();
} }
} }
@Subscribe
public void onFriendsChatChanged(FriendsChatChanged friendsChatChanged) public void onFriendsChatChanged(FriendsChatChanged friendsChatChanged)
{ {
ranksCache.invalidateAll(); ranksCache.invalidateAll();

View File

@@ -36,7 +36,6 @@ import static net.runelite.client.game.HiscoreManager.NONE;
import net.runelite.http.api.hiscore.HiscoreClient; import net.runelite.http.api.hiscore.HiscoreClient;
import net.runelite.http.api.hiscore.HiscoreEndpoint; import net.runelite.http.api.hiscore.HiscoreEndpoint;
import net.runelite.http.api.hiscore.HiscoreResult; import net.runelite.http.api.hiscore.HiscoreResult;
import org.jetbrains.annotations.NotNull;
@Slf4j @Slf4j
class HiscoreLoader extends CacheLoader<HiscoreManager.HiscoreKey, HiscoreResult> class HiscoreLoader extends CacheLoader<HiscoreManager.HiscoreKey, HiscoreResult>
@@ -51,7 +50,7 @@ class HiscoreLoader extends CacheLoader<HiscoreManager.HiscoreKey, HiscoreResult
} }
@Override @Override
public HiscoreResult load(@NotNull HiscoreManager.HiscoreKey hiscoreKey) public HiscoreResult load(HiscoreManager.HiscoreKey hiscoreKey) throws Exception
{ {
return EMPTY; return EMPTY;
} }

View File

@@ -28,9 +28,9 @@ import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader; import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache; import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import io.reactivex.rxjava3.schedulers.Schedulers;
import java.awt.Color; import java.awt.Color;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@@ -49,19 +49,17 @@ import net.runelite.api.Client;
import net.runelite.api.Constants; import net.runelite.api.Constants;
import static net.runelite.api.Constants.CLIENT_DEFAULT_ZOOM; import static net.runelite.api.Constants.CLIENT_DEFAULT_ZOOM;
import net.runelite.api.GameState; import net.runelite.api.GameState;
import net.runelite.api.ItemDefinition; import net.runelite.api.ItemComposition;
import net.runelite.api.ItemID;
import static net.runelite.api.ItemID.*; import static net.runelite.api.ItemID.*;
import net.runelite.api.Sprite; import net.runelite.api.SpritePixels;
import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GameStateChanged;
import net.runelite.api.events.PostItemDefinition; import net.runelite.api.events.PostItemComposition;
import net.runelite.client.callback.ClientThread; import net.runelite.client.callback.ClientThread;
import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.util.AsyncBufferedImage; import net.runelite.client.util.AsyncBufferedImage;
import net.runelite.http.api.item.ItemClient; import net.runelite.http.api.item.ItemClient;
import net.runelite.http.api.item.ItemPrice; import net.runelite.http.api.item.ItemPrice;
import net.runelite.http.api.item.ItemStats; import net.runelite.http.api.item.ItemStats;
import org.jetbrains.annotations.NotNull;
import okhttp3.OkHttpClient; import okhttp3.OkHttpClient;
@Singleton @Singleton
@@ -91,7 +89,7 @@ public class ItemManager
private Map<Integer, ItemPrice> itemPrices = Collections.emptyMap(); private Map<Integer, ItemPrice> itemPrices = Collections.emptyMap();
private Map<Integer, ItemStats> itemStats = Collections.emptyMap(); private Map<Integer, ItemStats> itemStats = Collections.emptyMap();
private final LoadingCache<ImageKey, AsyncBufferedImage> itemImages; private final LoadingCache<ImageKey, AsyncBufferedImage> itemImages;
private final LoadingCache<Integer, ItemDefinition> itemDefinitions; private final LoadingCache<Integer, ItemComposition> itemCompositions;
private final LoadingCache<OutlineKey, BufferedImage> itemOutlines; private final LoadingCache<OutlineKey, BufferedImage> itemOutlines;
// Worn items with weight reducing property have a different worn and inventory ItemID // Worn items with weight reducing property have a different worn and inventory ItemID
@@ -164,19 +162,15 @@ public class ItemManager
build(); build();
@Inject @Inject
public ItemManager( public ItemManager(Client client, ScheduledExecutorService scheduledExecutorService, ClientThread clientThread,
Client client,
ScheduledExecutorService executor,
ClientThread clientThread,
EventBus eventbus,
OkHttpClient okHttpClient) OkHttpClient okHttpClient)
{ {
this.client = client; this.client = client;
this.clientThread = clientThread; this.clientThread = clientThread;
this.itemClient = new ItemClient(okHttpClient); this.itemClient = new ItemClient(okHttpClient);
executor.scheduleWithFixedDelay(this::loadPrices, 0, 30, TimeUnit.MINUTES); scheduledExecutorService.scheduleWithFixedDelay(this::loadPrices, 0, 30, TimeUnit.MINUTES);
executor.submit(this::loadStats); scheduledExecutorService.submit(this::loadStats);
itemImages = CacheBuilder.newBuilder() itemImages = CacheBuilder.newBuilder()
.maximumSize(128L) .maximumSize(128L)
@@ -184,19 +178,19 @@ public class ItemManager
.build(new CacheLoader<ImageKey, AsyncBufferedImage>() .build(new CacheLoader<ImageKey, AsyncBufferedImage>()
{ {
@Override @Override
public AsyncBufferedImage load(@NotNull ImageKey key) public AsyncBufferedImage load(ImageKey key) throws Exception
{ {
return loadImage(key.itemId, key.itemQuantity, key.stackable); return loadImage(key.itemId, key.itemQuantity, key.stackable);
} }
}); });
itemDefinitions = CacheBuilder.newBuilder() itemCompositions = CacheBuilder.newBuilder()
.maximumSize(1024L) .maximumSize(1024L)
.expireAfterAccess(1, TimeUnit.HOURS) .expireAfterAccess(1, TimeUnit.HOURS)
.build(new CacheLoader<Integer, ItemDefinition>() .build(new CacheLoader<Integer, ItemComposition>()
{ {
@Override @Override
public ItemDefinition load(@NotNull Integer key) public ItemComposition load(Integer key) throws Exception
{ {
return client.getItemDefinition(key); return client.getItemDefinition(key);
} }
@@ -208,59 +202,77 @@ public class ItemManager
.build(new CacheLoader<OutlineKey, BufferedImage>() .build(new CacheLoader<OutlineKey, BufferedImage>()
{ {
@Override @Override
public BufferedImage load(@NotNull OutlineKey key) public BufferedImage load(OutlineKey key) throws Exception
{ {
return loadItemOutline(key.itemId, key.itemQuantity, key.outlineColor); return loadItemOutline(key.itemId, key.itemQuantity, key.outlineColor);
} }
}); });
eventbus.subscribe(GameStateChanged.class, this, this::onGameStateChanged);
eventbus.subscribe(PostItemDefinition.class, this, this::onPostItemDefinition);
} }
private void loadPrices() private void loadPrices()
{ {
itemClient.getPrices() try
.subscribeOn(Schedulers.io()) {
.subscribe( ItemPrice[] prices = itemClient.getPrices();
m -> itemPrices = m, if (prices != null)
e -> log.warn("Error loading prices", e), {
() -> log.debug("Loaded {} prices", itemPrices.size()) 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);
}
} }
private void loadStats() private void loadStats()
{ {
itemClient.getStats() try
.subscribeOn(Schedulers.io())
.subscribe(
m -> itemStats = m,
e -> log.warn("Error fetching stats", e),
() -> log.debug("Loaded {} stats", itemStats.size())
);
}
private void onGameStateChanged(final GameStateChanged event)
{
if (event.getGameState() == GameState.HOPPING || event.getGameState() == GameState.LOGIN_SCREEN)
{ {
itemDefinitions.invalidateAll(); final Map<Integer, ItemStats> stats = itemClient.getStats();
if (stats != null)
{
itemStats = ImmutableMap.copyOf(stats);
}
log.debug("Loaded {} stats", itemStats.size());
}
catch (IOException e)
{
log.warn("error loading stats!", e);
} }
} }
private void onPostItemDefinition(PostItemDefinition event)
@Subscribe
public void onGameStateChanged(final GameStateChanged event)
{ {
itemDefinitions.put(event.getItemDefinition().getId(), event.getItemDefinition()); if (event.getGameState() == GameState.HOPPING || event.getGameState() == GameState.LOGIN_SCREEN)
{
itemCompositions.invalidateAll();
}
}
@Subscribe
public void onPostItemComposition(PostItemComposition event)
{
itemCompositions.put(event.getItemComposition().getId(), event.getItemComposition());
} }
/** /**
* Invalidates internal item manager item composition cache (but not client item composition cache) * Invalidates internal item manager item composition cache (but not client item composition cache)
* * @see Client#getItemCompositionCache()
* @see Client#getItemDefinitionCache()
*/ */
public void invalidateItemDefinitionCache() public void invalidateItemCompositionCache()
{ {
itemDefinitions.invalidateAll(); itemCompositions.invalidateAll();
} }
/** /**
@@ -280,7 +292,7 @@ public class ItemManager
* @param itemID item id * @param itemID item id
* @param ignoreUntradeableMap should the price returned ignore items that are not tradeable for coins in regular way * @param ignoreUntradeableMap should the price returned ignore items that are not tradeable for coins in regular way
* @return item price * @return item price
* */ */
public int getItemPrice(int itemID, boolean ignoreUntradeableMap) public int getItemPrice(int itemID, boolean ignoreUntradeableMap)
{ {
if (itemID == COINS_995) if (itemID == COINS_995)
@@ -292,10 +304,10 @@ public class ItemManager
return 1000; return 1000;
} }
ItemDefinition itemDefinition = getItemDefinition(itemID); ItemComposition itemComposition = getItemComposition(itemID);
if (itemDefinition.getNote() != -1) if (itemComposition.getNote() != -1)
{ {
itemID = itemDefinition.getLinkedNoteId(); itemID = itemComposition.getLinkedNoteId();
} }
itemID = WORN_ITEMS.getOrDefault(itemID, itemID); itemID = WORN_ITEMS.getOrDefault(itemID, itemID);
@@ -328,67 +340,17 @@ public class ItemManager
return price; return price;
} }
public int getAlchValue(ItemDefinition composition)
{
if (composition.getId() == ItemID.COINS_995)
{
return 1;
}
if (composition.getId() == ItemID.PLATINUM_TOKEN)
{
return 1000;
}
return Math.max(1, composition.getHaPrice());
}
public int getAlchValue(int itemID)
{
if (itemID == ItemID.COINS_995)
{
return 1;
}
if (itemID == ItemID.PLATINUM_TOKEN)
{
return 1000;
}
return Math.max(1, getItemDefinition(itemID).getHaPrice());
}
public int getRepairValue(int itemId)
{
return getRepairValue(itemId, false);
}
private int getRepairValue(int itemId, boolean fullValue)
{
final ItemReclaimCost b = ItemReclaimCost.of(itemId);
if (b != null)
{
if (fullValue || b.getItemID() == GRANITE_MAUL_24225 || b.getItemID() == GRANITE_MAUL_24227)
{
return b.getValue();
}
return (int) (b.getValue() * (75.0f / 100.0f));
}
return 0;
}
/** /**
* Look up an item's stats * Look up an item's stats
*
* @param itemId item id * @param itemId item id
* @return item stats * @return item stats
*/ */
@Nullable @Nullable
public ItemStats getItemStats(int itemId, boolean allowNote) public ItemStats getItemStats(int itemId, boolean allowNote)
{ {
ItemDefinition itemDefinition = getItemDefinition(itemId); ItemComposition itemComposition = getItemComposition(itemId);
if (!allowNote && itemDefinition.getNote() != -1) if (itemComposition == null || itemComposition.getName() == null || (!allowNote && itemComposition.getNote() != -1))
{ {
return null; return null;
} }
@@ -425,10 +387,10 @@ public class ItemManager
* @return item composition * @return item composition
*/ */
@Nonnull @Nonnull
public ItemDefinition getItemDefinition(int itemId) public ItemComposition getItemComposition(int itemId)
{ {
assert client.isClientThread() : "getItemDefinition must be called on client thread"; assert client.isClientThread() : "getItemComposition must be called on client thread";
return itemDefinitions.getUnchecked(itemId); return itemCompositions.getUnchecked(itemId);
} }
/** /**
@@ -436,16 +398,16 @@ public class ItemManager
*/ */
public int canonicalize(int itemID) public int canonicalize(int itemID)
{ {
ItemDefinition itemDefinition = getItemDefinition(itemID); ItemComposition itemComposition = getItemComposition(itemID);
if (itemDefinition.getNote() != -1) if (itemComposition.getNote() != -1)
{ {
return itemDefinition.getLinkedNoteId(); return itemComposition.getLinkedNoteId();
} }
if (itemDefinition.getPlaceholderTemplateId() != -1) if (itemComposition.getPlaceholderTemplateId() != -1)
{ {
return itemDefinition.getPlaceholderId(); return itemComposition.getPlaceholderId();
} }
return WORN_ITEMS.getOrDefault(itemID, itemID); return WORN_ITEMS.getOrDefault(itemID, itemID);
@@ -466,7 +428,7 @@ public class ItemManager
{ {
return false; return false;
} }
Sprite sprite = client.createItemSprite(itemId, quantity, 1, Sprite.DEFAULT_SHADOW_COLOR, SpritePixels sprite = client.createItemSprite(itemId, quantity, 1, SpritePixels.DEFAULT_SHADOW_COLOR,
stackable ? 1 : 0, false, CLIENT_DEFAULT_ZOOM); stackable ? 1 : 0, false, CLIENT_DEFAULT_ZOOM);
if (sprite == null) if (sprite == null)
{ {
@@ -520,21 +482,21 @@ public class ItemManager
/** /**
* Create item sprite and applies an outline. * Create item sprite and applies an outline.
* *
* @param itemId item id * @param itemId item id
* @param itemQuantity item quantity * @param itemQuantity item quantity
* @param outlineColor outline color * @param outlineColor outline color
* @return image * @return image
*/ */
private BufferedImage loadItemOutline(final int itemId, final int itemQuantity, final Color outlineColor) private BufferedImage loadItemOutline(final int itemId, final int itemQuantity, final Color outlineColor)
{ {
final Sprite itemSprite = client.createItemSprite(itemId, itemQuantity, 1, 0, 0, false, CLIENT_DEFAULT_ZOOM); final SpritePixels itemSprite = client.createItemSprite(itemId, itemQuantity, 1, 0, 0, false, CLIENT_DEFAULT_ZOOM);
return itemSprite.toBufferedOutline(outlineColor); return itemSprite.toBufferedOutline(outlineColor);
} }
/** /**
* Get item outline with a specific color. * Get item outline with a specific color.
* *
* @param itemId item id * @param itemId item id
* @param itemQuantity item quantity * @param itemQuantity item quantity
* @param outlineColor outline color * @param outlineColor outline color
* @return image * @return image

View File

@@ -352,9 +352,4 @@ public enum ItemMapping
return mapping; return mapping;
} }
public static boolean isMapped(int itemId)
{
return MAPPINGS.containsValue(itemId);
}
} }

View File

@@ -1,132 +0,0 @@
/*
* 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 ItemReclaimCost
{
// Capes
FIRE_CAPE(ItemID.FIRE_CAPE, 50000),
FIRE_MAX_CAPE(ItemID.FIRE_MAX_CAPE, 99000),
INFERNAL_CAPE(ItemID.INFERNAL_CAPE, 50000),
INFERNAL_MAX_CAPE(ItemID.INFERNAL_MAX_CAPE, 99000),
AVAS_ASSEMBLER(ItemID.AVAS_ASSEMBLER, 75000),
ASSEMBLER_MAX_CAPE(ItemID.ASSEMBLER_MAX_CAPE, 99000),
IMBUED_GUTHIX_CAPE(ItemID.IMBUED_GUTHIX_CAPE, 75000),
IMBUED_GUTHIX_MAX_CAPE(ItemID.GUTHIX_MAX_CAPE, 99000),
IMBUED_SARADOMIN_CAPE(ItemID.IMBUED_SARADOMIN_CAPE, 75000),
IMBUED_SARADOMIN_MAX_CAPE(ItemID.SARADOMIN_MAX_CAPE, 99000),
IMBUED_ZAMORAK_CAPE(ItemID.IMBUED_ZAMORAK_CAPE, 75000),
IMBUED_ZAMORAK_MAX_CAPE(ItemID.ZAMORAK_MAX_CAPE, 99000),
// 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),
// Granite Maul
GRANITE_MAUL(ItemID.GRANITE_MAUL_24225, 375000),
GRANITE_MAUL_OR(ItemID.GRANITE_MAUL_24227, 375000);
private static final ImmutableMap<Integer, ItemReclaimCost> idMap;
static
{
ImmutableMap.Builder<Integer, ItemReclaimCost> builder = ImmutableMap.builder();
for (ItemReclaimCost items : values())
{
builder.put(items.itemID, items);
}
idMap = builder.build();
}
private final int itemID;
private final int value;
@Nullable
public static ItemReclaimCost of(int itemId)
{
return idMap.get(itemId);
}
public static boolean breaksOnDeath(int itemId)
{
return idMap.containsKey(itemId);
}
}

View File

@@ -98,9 +98,4 @@ public class ItemVariationMapping
{ {
return INVERTED_MAPPINGS.asMap().getOrDefault(itemId, Collections.singletonList(itemId)); return INVERTED_MAPPINGS.asMap().getOrDefault(itemId, Collections.singletonList(itemId));
} }
static int getSize()
{
return MAPPINGS.size();
}
} }

View File

@@ -41,7 +41,7 @@ import net.runelite.api.AnimationID;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.api.ItemID; import net.runelite.api.ItemID;
import net.runelite.api.NPC; import net.runelite.api.NPC;
import net.runelite.api.NPCDefinition; import net.runelite.api.NPCComposition;
import net.runelite.api.NpcID; import net.runelite.api.NpcID;
import net.runelite.api.Player; import net.runelite.api.Player;
import net.runelite.api.Tile; import net.runelite.api.Tile;
@@ -53,10 +53,11 @@ import net.runelite.api.events.GameTick;
import net.runelite.api.events.ItemDespawned; import net.runelite.api.events.ItemDespawned;
import net.runelite.api.events.ItemQuantityChanged; import net.runelite.api.events.ItemQuantityChanged;
import net.runelite.api.events.ItemSpawned; import net.runelite.api.events.ItemSpawned;
import net.runelite.api.events.NpcChanged;
import net.runelite.api.events.NpcDespawned; import net.runelite.api.events.NpcDespawned;
import net.runelite.api.events.PlayerDespawned; import net.runelite.api.events.PlayerDespawned;
import net.runelite.api.events.NpcDefinitionChanged;
import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.EventBus;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.events.NpcLootReceived; import net.runelite.client.events.NpcLootReceived;
import net.runelite.client.events.PlayerLootReceived; import net.runelite.client.events.PlayerLootReceived;
@@ -64,28 +65,9 @@ import net.runelite.client.events.PlayerLootReceived;
@Slf4j @Slf4j
public class LootManager public class LootManager
{ {
private static final Map<Integer, Integer> NPC_DEATH_ANIMATIONS = ImmutableMap.<Integer, Integer>builder() private static final Map<Integer, Integer> NPC_DEATH_ANIMATIONS = ImmutableMap.of(
.put(NpcID.CAVE_KRAKEN, AnimationID.CAVE_KRAKEN_DEATH) NpcID.CAVE_KRAKEN, AnimationID.CAVE_KRAKEN_DEATH
.put(NpcID.CRYSTALLINE_BAT, AnimationID.CRYSTALLINE_BAT_DEATH) );
.put(NpcID.CRYSTALLINE_RAT, AnimationID.CRYSTALLINE_RAT_DEATH)
.put(NpcID.CRYSTALLINE_SPIDER, AnimationID.CRYSTALLINE_SPIDER_DEATH)
.put(NpcID.CRYSTALLINE_WOLF, AnimationID.CRYSTALLINE_WOLF_DEATH)
.put(NpcID.CRYSTALLINE_UNICORN, AnimationID.CRYSTALLINE_UNICORN_DEATH)
.put(NpcID.CRYSTALLINE_SCORPION, AnimationID.CORRUPTED_SCORPION_DEATH)
.put(NpcID.CRYSTALLINE_DRAGON, AnimationID.CRYSTALLINE_DRAGON_DEATH)
.put(NpcID.CRYSTALLINE_DARK_BEAST, AnimationID.CRYSTALLINE_DARK_BEAST_DEATH)
.put(NpcID.CRYSTALLINE_BEAR, AnimationID.CRYSTALLINE_BEAR_DEATH)
.put(NpcID.CORRUPTED_BAT, AnimationID.CRYSTALLINE_BAT_DEATH)
.put(NpcID.CORRUPTED_RAT, AnimationID.CRYSTALLINE_RAT_DEATH)
.put(NpcID.CORRUPTED_SPIDER, AnimationID.CRYSTALLINE_SPIDER_DEATH)
.put(NpcID.CORRUPTED_WOLF, AnimationID.CRYSTALLINE_WOLF_DEATH)
.put(NpcID.CORRUPTED_UNICORN, AnimationID.CRYSTALLINE_UNICORN_DEATH)
.put(NpcID.CORRUPTED_SCORPION, AnimationID.CORRUPTED_SCORPION_DEATH)
.put(NpcID.CORRUPTED_DRAGON, AnimationID.CRYSTALLINE_DRAGON_DEATH)
.put(NpcID.CORRUPTED_DARK_BEAST, AnimationID.CRYSTALLINE_DARK_BEAST_DEATH)
.put(NpcID.CORRUPTED_BEAR, AnimationID.CRYSTALLINE_BEAR_DEATH)
.put(NpcID.THE_NIGHTMARE_9433, AnimationID.NIGHTMARE_DEATH)
.build();
private final EventBus eventBus; private final EventBus eventBus;
private final Client client; private final Client client;
@@ -98,25 +80,14 @@ public class LootManager
private int delayedLootTickLimit; private int delayedLootTickLimit;
@Inject @Inject
private LootManager( private LootManager(EventBus eventBus, Client client)
final EventBus eventBus,
final Client client
)
{ {
this.eventBus = eventBus; this.eventBus = eventBus;
this.client = client; 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);
eventBus.subscribe(NpcDefinitionChanged.class, this, this::onNpcDefinitionChanged);
} }
private void onNpcDespawned(NpcDespawned npcDespawned) @Subscribe
public void onNpcDespawned(NpcDespawned npcDespawned)
{ {
final NPC npc = npcDespawned.getNpc(); final NPC npc = npcDespawned.getNpc();
@@ -165,7 +136,8 @@ public class LootManager
processNpcLoot(npc); processNpcLoot(npc);
} }
private void onPlayerDespawned(PlayerDespawned playerDespawned) @Subscribe
public void onPlayerDespawned(PlayerDespawned playerDespawned)
{ {
final Player player = playerDespawned.getPlayer(); final Player player = playerDespawned.getPlayer();
// Only care about dead Players // Only care about dead Players
@@ -191,10 +163,11 @@ public class LootManager
} }
killPoints.add(location); killPoints.add(location);
eventBus.post(PlayerLootReceived.class, new PlayerLootReceived(player, items)); eventBus.post(new PlayerLootReceived(player, items));
} }
private void onItemSpawned(ItemSpawned itemSpawned) @Subscribe
public void onItemSpawned(ItemSpawned itemSpawned)
{ {
final TileItem item = itemSpawned.getItem(); final TileItem item = itemSpawned.getItem();
final Tile tile = itemSpawned.getTile(); final Tile tile = itemSpawned.getTile();
@@ -204,14 +177,16 @@ public class LootManager
log.debug("Item spawn {} ({}) location {}", item.getId(), item.getQuantity(), location); log.debug("Item spawn {} ({}) location {}", item.getId(), item.getQuantity(), location);
} }
private void onItemDespawned(ItemDespawned itemDespawned) @Subscribe
public void onItemDespawned(ItemDespawned itemDespawned)
{ {
final TileItem item = itemDespawned.getItem(); final TileItem item = itemDespawned.getItem();
final LocalPoint location = itemDespawned.getTile().getLocalLocation(); final LocalPoint location = itemDespawned.getTile().getLocalLocation();
log.debug("Item despawn {} ({}) location {}", item.getId(), item.getQuantity(), location); log.debug("Item despawn {} ({}) location {}", item.getId(), item.getQuantity(), location);
} }
private void onItemQuantityChanged(ItemQuantityChanged itemQuantityChanged) @Subscribe
public void onItemQuantityChanged(ItemQuantityChanged itemQuantityChanged)
{ {
final TileItem item = itemQuantityChanged.getItem(); final TileItem item = itemQuantityChanged.getItem();
final Tile tile = itemQuantityChanged.getTile(); final Tile tile = itemQuantityChanged.getTile();
@@ -227,7 +202,8 @@ public class LootManager
itemSpawns.put(packed, new ItemStack(item.getId(), diff, location)); itemSpawns.put(packed, new ItemStack(item.getId(), diff, location));
} }
private void onAnimationChanged(AnimationChanged e) @Subscribe
public void onAnimationChanged(AnimationChanged e)
{ {
if (!(e.getActor() instanceof NPC)) if (!(e.getActor() instanceof NPC))
{ {
@@ -256,7 +232,8 @@ public class LootManager
} }
} }
public void onNpcDefinitionChanged(NpcDefinitionChanged npcChanged) @Subscribe
public void onNpcChanged(NpcChanged npcChanged)
{ {
final NPC npc = npcChanged.getNpc(); final NPC npc = npcChanged.getNpc();
if (npc.getId() == NpcID.THE_NIGHTMARE_9433) if (npc.getId() == NpcID.THE_NIGHTMARE_9433)
@@ -266,7 +243,8 @@ public class LootManager
} }
} }
private void onGameTick(GameTick gameTick) @Subscribe
public void onGameTick(GameTick gameTick)
{ {
if (delayedLootNpc != null && delayedLootTickLimit-- > 0) if (delayedLootNpc != null && delayedLootTickLimit-- > 0)
{ {
@@ -274,6 +252,7 @@ public class LootManager
} }
playerLocationLastTick = client.getLocalPlayer().getWorldLocation(); playerLocationLastTick = client.getLocalPlayer().getWorldLocation();
itemSpawns.clear(); itemSpawns.clear();
killPoints.clear(); killPoints.clear();
} }
@@ -302,7 +281,7 @@ public class LootManager
} }
log.debug("Got delayed loot stack from {}: {}", delayedLootNpc.getName(), itemStacks); log.debug("Got delayed loot stack from {}: {}", delayedLootNpc.getName(), itemStacks);
eventBus.post(NpcLootReceived.class, new NpcLootReceived(delayedLootNpc, itemStacks)); eventBus.post(new NpcLootReceived(delayedLootNpc, itemStacks));
delayedLootNpc = null; delayedLootNpc = null;
delayedLootTickLimit = 0; delayedLootTickLimit = 0;
@@ -318,7 +297,7 @@ public class LootManager
final int x = location.getSceneX(); final int x = location.getSceneX();
final int y = location.getSceneY(); final int y = location.getSceneY();
final int size = npc.getDefinition().getSize(); final int size = npc.getComposition().getSize();
// Some NPCs drop items onto multiple tiles // Some NPCs drop items onto multiple tiles
final List<ItemStack> allItems = new ArrayList<>(); final List<ItemStack> allItems = new ArrayList<>();
@@ -338,7 +317,7 @@ public class LootManager
} }
killPoints.add(location); killPoints.add(location);
eventBus.post(NpcLootReceived.class, new NpcLootReceived(npc, allItems)); eventBus.post(new NpcLootReceived(npc, allItems));
} }
private WorldPoint getDropLocation(NPC npc, WorldPoint worldLocation) private WorldPoint getDropLocation(NPC npc, WorldPoint worldLocation)
@@ -400,7 +379,7 @@ public class LootManager
private WorldPoint getAdjacentSquareLootTile(NPC npc) private WorldPoint getAdjacentSquareLootTile(NPC npc)
{ {
final NPCDefinition composition = npc.getDefinition(); final NPCComposition composition = npc.getComposition();
final WorldPoint worldLocation = npc.getWorldLocation(); final WorldPoint worldLocation = npc.getWorldLocation();
int x = worldLocation.getX(); int x = worldLocation.getX();
int y = worldLocation.getY(); int y = worldLocation.getY();

View File

@@ -1,6 +1,5 @@
/* /*
* Copyright (c) 2018, Adam <Adam@sigterm.info> * Copyright (c) 2018, Adam <Adam@sigterm.info>
* Copyright (c) 2019, TheStonedTurtle <https://github.com/TheStonedTurtle>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -25,136 +24,54 @@
*/ */
package net.runelite.client.game; package net.runelite.client.game;
import com.google.common.collect.ImmutableMap;
import com.google.gson.stream.JsonReader;
import io.reactivex.rxjava3.core.Completable;
import io.reactivex.rxjava3.schedulers.Schedulers;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.util.Collections;
import java.nio.charset.StandardCharsets; import java.util.Map;
import java.util.Set; import java.util.concurrent.ScheduledExecutorService;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.runelite.api.NpcID; import net.runelite.http.api.npc.NpcInfo;
import net.runelite.http.api.npc.NpcInfoClient;
import okhttp3.OkHttpClient;
@Slf4j
@Singleton @Singleton
@Slf4j
public class NPCManager public class NPCManager
{ {
private static final Set<Integer> blacklistXpMultiplier = Set.of( private final OkHttpClient okHttpClient;
// Vorkath private Map<Integer, NpcInfo> npcMap = Collections.emptyMap();
NpcID.VORKATH, NpcID.VORKATH_8058, NpcID.VORKATH_8059, NpcID.VORKATH_8060, NpcID.VORKATH_8061,
// Grotesque Guardians
NpcID.DAWN, NpcID.DAWN_7852, NpcID.DAWN_7853, NpcID.DAWN_7884, NpcID.DAWN_7885,
NpcID.DUSK, NpcID.DUSK_7851, NpcID.DUSK_7854, NpcID.DUSK_7855, NpcID.DUSK_7882, NpcID.DUSK_7883, NpcID.DUSK_7886, NpcID.DUSK_7887, NpcID.DUSK_7888, NpcID.DUSK_7889,
// Kraken
NpcID.KRAKEN, NpcID.KRAKEN_6640, NpcID.KRAKEN_6656,
// Zulrah
NpcID.ZULRAH, NpcID.ZULRAH_2043, NpcID.ZULRAH_2044
);
private ImmutableMap<Integer, NPCStats> statsMap;
@Inject @Inject
private NPCManager() private NPCManager(OkHttpClient okHttpClient, ScheduledExecutorService scheduledExecutorService)
{ {
Completable.fromAction(this::loadStats) this.okHttpClient = okHttpClient;
.subscribeOn(Schedulers.computation()) scheduledExecutorService.execute(this::loadNpcs);
.subscribe(
() -> log.debug("Loaded {} NPC stats", statsMap.size()),
ex -> log.warn("Error loading NPC stats", ex)
);
} }
private void loadStats() throws IOException
{
try (JsonReader reader = new JsonReader(new InputStreamReader(NPCManager.class.getResourceAsStream("/npc_stats.json"), StandardCharsets.UTF_8)))
{
ImmutableMap.Builder<Integer, NPCStats> builder = ImmutableMap.builderWithExpectedSize(2821);
reader.beginObject();
while (reader.hasNext())
{
builder.put(
Integer.parseInt(reader.nextName()),
NPCStats.NPC_STATS_TYPE_ADAPTER.read(reader)
);
}
reader.endObject();
statsMap = builder.build();
}
}
/**
* Returns the {@link NPCStats} for target NPC id
*
* @param npcId NPC id
* @return the {@link NPCStats} or null if unknown
*/
@Nullable @Nullable
public NPCStats getStats(final int npcId) public NpcInfo getNpcInfo(int npcId)
{ {
return statsMap.get(npcId); return npcMap.get(npcId);
} }
/** @Nullable
* Returns health for target NPC ID public Integer getHealth(int npcId)
*
* @param npcId NPC id
* @return health or null if unknown
*/
public int getHealth(final int npcId)
{ {
final NPCStats s = statsMap.get(npcId); NpcInfo npcInfo = npcMap.get(npcId);
if (s == null || s.getHitpoints() == -1) return npcInfo == null ? null : npcInfo.getHitpoints();
{
return -1;
}
return s.getHitpoints();
} }
/** private void loadNpcs()
* 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); try
if (s == null || s.getAttackSpeed() == -1)
{ {
return -1; npcMap = new NpcInfoClient(okHttpClient).getNpcs();
} }
catch (IOException e)
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)
{
if (blacklistXpMultiplier.contains(npcId))
{ {
return 1; log.warn("error loading npc stats", e);
} }
final NPCStats s = statsMap.get(npcId);
if (s == null)
{
return 1;
}
return s.calculateXpModifier();
} }
} }

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