diff --git a/runelite-client/pom.xml b/runelite-client/pom.xml
index 843718a560..a8d49dd693 100644
--- a/runelite-client/pom.xml
+++ b/runelite-client/pom.xml
@@ -38,6 +38,7 @@
1.7.12
+ 4.1.0
true
@@ -62,6 +63,12 @@
com.google.guava
guava
+
+ com.google.inject
+ guice
+ ${guice.version}
+ no_aop
+
com.google.code.gson
gson
@@ -114,6 +121,18 @@
1.10.19
test
+
+ com.google.inject.extensions
+ guice-testlib
+ ${guice.version}
+ test
+
+
+ com.google.inject.extensions
+ guice-grapher
+ ${guice.version}
+ test
+
diff --git a/runelite-client/src/main/java/net/runelite/client/RuneLite.java b/runelite-client/src/main/java/net/runelite/client/RuneLite.java
index 1150027870..3b1cd1f257 100644
--- a/runelite-client/src/main/java/net/runelite/client/RuneLite.java
+++ b/runelite-client/src/main/java/net/runelite/client/RuneLite.java
@@ -26,8 +26,10 @@ package net.runelite.client;
import com.google.common.base.Strings;
import com.google.common.eventbus.EventBus;
-import com.google.common.eventbus.SubscriberExceptionContext;
import com.google.gson.Gson;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
import java.awt.AWTException;
import java.awt.Frame;
import java.awt.Image;
@@ -41,9 +43,9 @@ import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
-import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import javax.imageio.ImageIO;
+import javax.inject.Singleton;
import javax.swing.JFrame;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;
@@ -55,21 +57,17 @@ import net.runelite.api.Client;
import net.runelite.api.Query;
import net.runelite.client.account.AccountSession;
import net.runelite.client.config.ConfigManager;
-import net.runelite.client.config.RuneliteConfig;
import net.runelite.client.events.SessionClose;
import net.runelite.client.events.SessionOpen;
-import net.runelite.client.game.ItemManager;
import net.runelite.client.menus.MenuManager;
import net.runelite.client.plugins.PluginManager;
-import net.runelite.client.task.Scheduler;
import net.runelite.client.ui.ClientUI;
-import net.runelite.client.ui.overlay.OverlayRenderer;
-import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
import net.runelite.http.api.account.AccountClient;
import org.pushingpixels.substance.api.skin.SubstanceGraphiteLookAndFeel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+@Singleton
public class RuneLite
{
private static final Logger logger = LoggerFactory.getLogger(RuneLite.class);
@@ -80,26 +78,34 @@ public class RuneLite
public static Image ICON;
+ private static Injector injector;
+
private static OptionSet options;
- private static Client client;
private static RuneLite runelite;
private static TrayIcon trayIcon;
private final RuneliteProperties properties = new RuneliteProperties();
+ private Client client;
private ClientUI gui;
- private RuneliteConfig config;
+
+ @Inject
private PluginManager pluginManager;
- private final MenuManager menuManager = new MenuManager(this);
- private OverlayRenderer renderer;
- private final EventBus eventBus = new EventBus(this::eventExceptionHandler);
- private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
- private final Scheduler scheduler = new Scheduler(this);
+
+ @Inject
+ private MenuManager menuManager;
+
+ @Inject
+ private EventBus eventBus;
+
+ @Inject
+ private ConfigManager configManager;
+
+ @Inject
+ private ScheduledExecutorService executor;
+
private WSClient wsclient;
private AccountSession accountSession;
- private final ConfigManager configManager = new ConfigManager(eventBus);
- private final ItemManager itemManager = new ItemManager(this);
- private final InfoBoxManager infoBoxManager = new InfoBoxManager();
static
{
@@ -126,7 +132,8 @@ public class RuneLite
PROFILES_DIR.mkdirs();
- runelite = new RuneLite();
+ injector = Guice.createInjector(new RuneliteModule());
+ runelite = injector.getInstance(RuneLite.class);
runelite.start();
}
@@ -146,7 +153,7 @@ public class RuneLite
logger.warn("unable to set look and feel", ex);
}
- gui = new ClientUI();
+ gui = new ClientUI(this);
setTitle(null);
setupTrayIcon();
@@ -154,18 +161,13 @@ public class RuneLite
configManager.load();
- config = configManager.getConfig(RuneliteConfig.class);
-
eventBus.register(menuManager);
- renderer = new OverlayRenderer();
-
// Load the plugins, but does not start them yet.
// This will initialize configuration
- pluginManager = new PluginManager(this);
pluginManager.loadPlugins();
- // Plugins have registered their config, so set default config
+ // Plugins have provided their config, so set default config
// to main settings
configManager.loadDefault();
@@ -294,7 +296,7 @@ public class RuneLite
wsclient.close();
}
- wsclient = new WSClient(session);
+ wsclient = new WSClient(eventBus, executor, session);
wsclient.connect();
}
@@ -333,34 +335,14 @@ public class RuneLite
eventBus.post(new SessionClose());
}
- private void eventExceptionHandler(Throwable exception, SubscriberExceptionContext context)
- {
- logger.warn("uncaught exception in event subscriber", exception);
- }
-
- public static Client getClient()
+ public Client getClient()
{
return client;
}
- public static void setClient(Client client)
+ public void setClient(Client client)
{
- RuneLite.client = client;
- }
-
- public static RuneLite getRunelite()
- {
- return runelite;
- }
-
- public static void setRunelite(RuneLite runelite)
- {
- RuneLite.runelite = runelite;
- }
-
- public RuneliteProperties getProperties()
- {
- return properties;
+ this.client = client;
}
public ClientUI getGui()
@@ -368,24 +350,19 @@ public class RuneLite
return gui;
}
- public PluginManager getPluginManager()
+ public void setGui(ClientUI gui)
{
- return pluginManager;
+ this.gui = gui;
}
- public MenuManager getMenuManager()
+ public static Injector getInjector()
{
- return menuManager;
+ return injector;
}
- public OverlayRenderer getRenderer()
+ public static void setInjector(Injector injector)
{
- return renderer;
- }
-
- public EventBus getEventBus()
- {
- return eventBus;
+ RuneLite.injector = injector;
}
public static OptionSet getOptions()
@@ -393,14 +370,9 @@ public class RuneLite
return options;
}
- public ScheduledExecutorService getExecutor()
+ public static void setOptions(OptionSet options)
{
- return executor;
- }
-
- public Scheduler getScheduler()
- {
- return scheduler;
+ RuneLite.options = options;
}
public static TrayIcon getTrayIcon()
@@ -424,26 +396,6 @@ public class RuneLite
return accountSession;
}
- public ConfigManager getConfigManager()
- {
- return configManager;
- }
-
- public RuneliteConfig getConfig()
- {
- return config;
- }
-
- public ItemManager getItemManager()
- {
- return itemManager;
- }
-
- public InfoBoxManager getInfoBoxManager()
- {
- return infoBoxManager;
- }
-
public T[] runQuery(Query query)
{
return (T[]) query.result(client);
diff --git a/runelite-client/src/main/java/net/runelite/client/RuneliteModule.java b/runelite-client/src/main/java/net/runelite/client/RuneliteModule.java
new file mode 100644
index 0000000000..45be90976b
--- /dev/null
+++ b/runelite-client/src/main/java/net/runelite/client/RuneliteModule.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2016-2017, Adam
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.runelite.client;
+
+import com.google.common.eventbus.EventBus;
+import com.google.common.eventbus.SubscriberExceptionContext;
+import com.google.inject.AbstractModule;
+import com.google.inject.Provides;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import javax.inject.Singleton;
+import net.runelite.api.Client;
+import net.runelite.client.config.ConfigManager;
+import net.runelite.client.config.RuneliteConfig;
+import net.runelite.client.game.ItemManager;
+import net.runelite.client.menus.MenuManager;
+import net.runelite.client.plugins.PluginManager;
+import net.runelite.client.task.Scheduler;
+import net.runelite.client.ui.ClientUI;
+import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RuneliteModule extends AbstractModule
+{
+ private static final Logger logger = LoggerFactory.getLogger(RuneliteModule.class);
+
+ @Override
+ protected void configure()
+ {
+ bind(ScheduledExecutorService.class).toInstance(Executors.newSingleThreadScheduledExecutor());
+ bind(MenuManager.class);
+ bind(ItemManager.class);
+ bind(InfoBoxManager.class);
+ bind(Scheduler.class);
+ bind(PluginManager.class);
+ bind(RuneliteProperties.class);
+ }
+
+ @Provides
+ Client provideClient(RuneLite runelite)
+ {
+ return runelite.getClient();
+ }
+
+ @Provides
+ ClientUI provideClientUi(RuneLite runelite)
+ {
+ return runelite.getGui();
+ }
+
+ @Provides
+ @Singleton
+ RuneliteConfig provideConfig(ConfigManager configManager)
+ {
+ return configManager.getConfig(RuneliteConfig.class);
+ }
+
+ @Provides
+ @Singleton
+ EventBus provideEventBus()
+ {
+ return new EventBus(RuneliteModule::eventExceptionHandler);
+ }
+
+ private static void eventExceptionHandler(Throwable exception, SubscriberExceptionContext context)
+ {
+ logger.warn("uncaught exception in event subscriber", exception);
+ }
+}
diff --git a/runelite-client/src/main/java/net/runelite/client/WSClient.java b/runelite-client/src/main/java/net/runelite/client/WSClient.java
index 82a2141c19..2e00668a0d 100644
--- a/runelite-client/src/main/java/net/runelite/client/WSClient.java
+++ b/runelite-client/src/main/java/net/runelite/client/WSClient.java
@@ -52,17 +52,17 @@ public class WSClient extends WebSocketListener implements AutoCloseable
private static final Duration PING_TIME = Duration.ofSeconds(30);
private static final Gson gson = WebsocketGsonFactory.build();
- private static final EventBus eventBus = RuneLite.getRunelite().getEventBus();
- private static final ScheduledExecutorService executor = RuneLite.getRunelite().getExecutor();
private final OkHttpClient client = new OkHttpClient();
+ private final EventBus eventBus;
private final AccountSession session;
private WebSocket webSocket;
private final ScheduledFuture pingFuture;
- public WSClient(AccountSession session)
+ public WSClient(EventBus eventBus, ScheduledExecutorService executor, AccountSession session)
{
+ this.eventBus = eventBus;
this.session = session;
this.pingFuture = executor.scheduleWithFixedDelay(this::ping, PING_TIME.getSeconds(), PING_TIME.getSeconds(), TimeUnit.SECONDS);
}
diff --git a/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java b/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java
index b00076e8ce..8806a2f3c0 100644
--- a/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java
+++ b/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java
@@ -24,6 +24,8 @@
*/
package net.runelite.client.callback;
+import com.google.common.eventbus.EventBus;
+import com.google.inject.Injector;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import net.runelite.api.ChatMessageType;
@@ -47,8 +49,12 @@ public class Hooks
private static final long CHECK = 600; // ms - how often to run checks
- private static final RuneLite runelite = RuneLite.getRunelite();
- private static final DeathChecker death = new DeathChecker(runelite);
+ private static final Injector injector = RuneLite.getInjector();
+ private static final Client client = injector.getInstance(Client.class);
+ private static final EventBus eventBus = injector.getInstance(EventBus.class);
+ private static final Scheduler scheduler = injector.getInstance(Scheduler.class);
+ private static final InfoBoxManager infoBoxManager = injector.getInstance(InfoBoxManager.class);
+ private static final DeathChecker death = new DeathChecker(client, eventBus);
private static long lastCheck;
@@ -73,11 +79,9 @@ public class Hooks
}
// tick pending scheduled tasks
- Scheduler scheduler = runelite.getScheduler();
scheduler.tick();
// cull infoboxes
- InfoBoxManager infoBoxManager = runelite.getInfoBoxManager();
infoBoxManager.cull();
}
@@ -85,7 +89,7 @@ public class Hooks
{
BufferedImage image = (BufferedImage) mainBufferProvider.getImage();
- OverlayRenderer renderer = runelite.getRenderer();
+ OverlayRenderer renderer = injector.getInstance(OverlayRenderer.class);
try
{
@@ -99,12 +103,6 @@ public class Hooks
public static void callHook(String name, int idx, Object object)
{
- if (RuneLite.getClient() == null)
- {
- logger.warn("Event {} triggered prior to client being ready", name);
- return;
- }
-
switch (name)
{
case "experienceChanged":
@@ -117,7 +115,7 @@ public class Hooks
{
Skill updatedSkill = possibleSkills[idx];
experienceChanged.setSkill(updatedSkill);
- runelite.getEventBus().post(experienceChanged);
+ eventBus.post(experienceChanged);
}
break;
}
@@ -125,42 +123,42 @@ public class Hooks
{
MapRegionChanged regionChanged = new MapRegionChanged();
regionChanged.setIndex(idx);
- runelite.getEventBus().post(regionChanged);
+ eventBus.post(regionChanged);
break;
}
case "playerMenuOptionsChanged":
{
PlayerMenuOptionsChanged optionsChanged = new PlayerMenuOptionsChanged();
optionsChanged.setIndex(idx);
- runelite.getEventBus().post(optionsChanged);
+ eventBus.post(optionsChanged);
break;
}
case "animationChanged":
{
AnimationChanged animationChange = new AnimationChanged();
animationChange.setObject(object);
- runelite.getEventBus().post(animationChange);
+ eventBus.post(animationChange);
break;
}
case "gameStateChanged":
{
GameStateChanged gameStateChange = new GameStateChanged();
- gameStateChange.setGameState(RuneLite.getClient().getGameState());
- runelite.getEventBus().post(gameStateChange);
+ gameStateChange.setGameState(client.getGameState());
+ eventBus.post(gameStateChange);
break;
}
case "varbitChanged":
{
VarbitChanged varbitChanged = new VarbitChanged();
- runelite.getEventBus().post(varbitChanged);
+ eventBus.post(varbitChanged);
break;
}
case "resizeChanged":
{
//maybe couple with varbitChanged. resizeable may not be a varbit but it would fit with the other client settings.
ResizeableChanged resizeableChanged = new ResizeableChanged();
- resizeableChanged.setResized(RuneLite.getClient().isResized());
- runelite.getEventBus().post(resizeableChanged);
+ resizeableChanged.setResized(client.isResized());
+ eventBus.post(resizeableChanged);
break;
}
default:
@@ -196,7 +194,7 @@ public class Hooks
menuOptionClicked.setMenuAction(MenuAction.of(menuAction));
menuOptionClicked.setId(id);
- runelite.getEventBus().post(menuOptionClicked);
+ eventBus.post(menuOptionClicked);
}
public static void addChatMessage(int type, String sender, String message, String clan)
@@ -209,7 +207,7 @@ public class Hooks
ChatMessageType chatMessageType = ChatMessageType.of(type);
ChatMessage chatMessage = new ChatMessage(chatMessageType, sender, message, clan);
- runelite.getEventBus().post(chatMessage);
+ eventBus.post(chatMessage);
}
public static void setMessage(MessageNode messageNode, int type, String name, String sender, String value)
@@ -223,6 +221,6 @@ public class Hooks
setMessage.setSender(sender);
setMessage.setValue(value);
- runelite.getEventBus().post(setMessage);
+ eventBus.post(setMessage);
}
}
diff --git a/runelite-client/src/main/java/net/runelite/client/config/Config.java b/runelite-client/src/main/java/net/runelite/client/config/Config.java
new file mode 100644
index 0000000000..4c82282d7d
--- /dev/null
+++ b/runelite-client/src/main/java/net/runelite/client/config/Config.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2017, Adam
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.runelite.client.config;
+
+public interface Config
+{
+
+}
diff --git a/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java b/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java
index 5fd1f38d80..1ac4831d23 100644
--- a/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java
+++ b/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java
@@ -25,8 +25,9 @@
package net.runelite.client.config;
import com.google.common.eventbus.EventBus;
+import com.google.inject.Injector;
+import com.google.inject.Key;
import java.awt.Color;
-
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@@ -37,27 +38,38 @@ import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
import java.util.List;
import java.util.Properties;
+import java.util.concurrent.ScheduledExecutorService;
import java.util.stream.Collectors;
+import javax.inject.Inject;
+import javax.inject.Singleton;
import net.runelite.client.RuneLite;
import net.runelite.client.account.AccountSession;
import net.runelite.client.events.ConfigChanged;
+import net.runelite.client.plugins.PluginManager;
import net.runelite.http.api.config.ConfigClient;
import net.runelite.http.api.config.ConfigEntry;
import net.runelite.http.api.config.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+@Singleton
public class ConfigManager
{
private static final Logger logger = LoggerFactory.getLogger(ConfigManager.class);
private static final String SETTINGS_FILE_NAME = "settings.properties";
- private final EventBus eventBus;
+ @Inject
+ EventBus eventBus;
+
+ @Inject
+ ScheduledExecutorService executor;
+
+ @Inject
+ PluginManager pluginManager;
+
private AccountSession session;
private ConfigClient client;
private File propertiesFile;
@@ -65,11 +77,8 @@ public class ConfigManager
private final ConfigInvocationHandler handler = new ConfigInvocationHandler(this);
private final Properties properties = new Properties();
- private final List