diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/Plugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/Plugin.java index a3eb45c1f5..1463c973be 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/Plugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/Plugin.java @@ -25,9 +25,13 @@ package net.runelite.client.plugins; +import com.google.common.util.concurrent.AbstractIdleService; import net.runelite.client.ui.overlay.Overlay; -public abstract class Plugin +public abstract class Plugin extends AbstractIdleService { - public abstract Overlay getOverlay(); + public Overlay getOverlay() + { + return null; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/PluginManager.java b/runelite-client/src/main/java/net/runelite/client/plugins/PluginManager.java index 8c9b57d5ed..dc7f1d7115 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/PluginManager.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/PluginManager.java @@ -24,9 +24,13 @@ */ package net.runelite.client.plugins; +import com.google.common.util.concurrent.MoreExecutors; +import com.google.common.util.concurrent.Service; +import com.google.common.util.concurrent.ServiceManager; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.stream.Collectors; import net.runelite.client.RuneLite; import net.runelite.client.plugins.boosts.Boosts; import net.runelite.client.plugins.bosstimer.BossTimers; @@ -45,7 +49,7 @@ public class PluginManager private static final Logger logger = LoggerFactory.getLogger(PluginManager.class); private final RuneLite runelite; - private final List plugins = new ArrayList<>(); + private ServiceManager manager; public PluginManager(RuneLite runelite) { @@ -54,30 +58,67 @@ public class PluginManager public void loadAll() { - load(new Boosts()); - load(new OpponentInfo()); - load(new FPS()); - load(new Hiscore()); - load(new BossTimers()); - load(new Xtea()); - load(new IdleNotifier()); - load(new Runecraft()); + List plugins = new ArrayList<>(); + plugins.add(new Boosts()); + plugins.add(new OpponentInfo()); + plugins.add(new FPS()); + plugins.add(new Hiscore()); + plugins.add(new BossTimers()); + plugins.add(new Xtea()); + plugins.add(new IdleNotifier()); + plugins.add(new Runecraft()); if (RuneLite.getOptions().has("developer-mode")) { logger.info("Loading developer plugins"); - load(new DevTools()); + plugins.add(new DevTools()); } - } - private void load(Plugin plugin) - { - plugins.add(plugin); - runelite.getEventBus().register(plugin); + // Add plugin listeners + for (Plugin plugin : plugins) + { + Service.Listener listener = new Service.Listener() + { + @Override + public void running() + { + logger.debug("Plugin {} is now running", plugin); + runelite.getEventBus().register(plugin); + } + + @Override + public void stopping(Service.State from) + { + logger.debug("Plugin {} is stopping", plugin); + runelite.getEventBus().unregister(logger); + } + + @Override + public void failed(Service.State from, Throwable failure) + { + logger.warn("Plugin {} has failed", plugin, failure); + + if (from == Service.State.RUNNING) + { + runelite.getEventBus().unregister(logger); + } + } + }; + + plugin.addListener(listener, MoreExecutors.directExecutor()); + } + + manager = new ServiceManager(plugins); + + logger.debug("Starting plugins..."); + manager.startAsync(); } public Collection getPlugins() { - return plugins; + return manager.servicesByState().get(Service.State.RUNNING) + .stream() + .map(s -> (Plugin) s) + .collect(Collectors.toList()); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/boosts/Boosts.java b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/Boosts.java index 04b2faf45b..a131cf8f86 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/boosts/Boosts.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/Boosts.java @@ -37,4 +37,14 @@ public class Boosts extends Plugin { return overlay; } + + @Override + protected void startUp() throws Exception + { + } + + @Override + protected void shutDown() throws Exception + { + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/bosstimer/BossTimers.java b/runelite-client/src/main/java/net/runelite/client/plugins/bosstimer/BossTimers.java index 7eed7531b3..b0742f1904 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/bosstimer/BossTimers.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/bosstimer/BossTimers.java @@ -46,6 +46,16 @@ public class BossTimers extends Plugin private final List bosses = loadBossData(); + @Override + protected void startUp() throws Exception + { + } + + @Override + protected void shutDown() throws Exception + { + } + @Override public Overlay getOverlay() { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevTools.java b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevTools.java index 6a2b7315b3..7b170b1478 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevTools.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevTools.java @@ -25,10 +25,8 @@ package net.runelite.client.plugins.devtools; import java.awt.Font; -import java.awt.FontFormatException; import java.awt.GraphicsEnvironment; import java.awt.event.ActionEvent; -import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.ImageIcon; import net.runelite.client.RuneLite; @@ -60,34 +58,26 @@ public class DevTools extends Plugin private Font font; - public DevTools() + @Override + protected void startUp() throws Exception { navButton.getButton().addActionListener(this::setPluginPanel); - try - { - ImageIcon icon = new ImageIcon(ImageIO.read(getClass().getResourceAsStream("devtools_icon.png"))); - navButton.getButton().setIcon(icon); - } - catch (IOException ex) - { - logger.warn("Unable to load devtools icon", ex); - } + ImageIcon icon = new ImageIcon(ImageIO.read(getClass().getResourceAsStream("devtools_icon.png"))); + navButton.getButton().setIcon(icon); ui.getNavigationPanel().addNavigation(navButton); - try - { - font = Font.createFont(Font.TRUETYPE_FONT, getClass().getResourceAsStream("runescape.ttf")); + font = Font.createFont(Font.TRUETYPE_FONT, getClass().getResourceAsStream("runescape.ttf")); - font = font.deriveFont(Font.PLAIN, 16); - GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); - ge.registerFont(font); - } - catch (FontFormatException | IOException ex) - { - logger.warn("Unable to load font", ex); - } + font = font.deriveFont(Font.PLAIN, 16); + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + ge.registerFont(font); + } + + @Override + protected void shutDown() throws Exception + { } @Override diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fpsinfo/FPS.java b/runelite-client/src/main/java/net/runelite/client/plugins/fpsinfo/FPS.java index 56ec9470d7..bbffb754a1 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/fpsinfo/FPS.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fpsinfo/FPS.java @@ -37,4 +37,14 @@ public class FPS extends Plugin { return overlay; } + + @Override + protected void startUp() throws Exception + { + } + + @Override + protected void shutDown() throws Exception + { + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/Hiscore.java b/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/Hiscore.java index a5c4d7fb1a..ef9d75c9e2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/Hiscore.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/Hiscore.java @@ -26,7 +26,6 @@ package net.runelite.client.plugins.hiscore; import com.google.common.eventbus.Subscribe; import java.awt.event.ActionEvent; -import java.io.IOException; import java.util.concurrent.ScheduledExecutorService; import javax.imageio.ImageIO; import javax.swing.ImageIcon; @@ -35,7 +34,6 @@ import net.runelite.client.events.PlayerMenuOptionClicked; import net.runelite.client.plugins.Plugin; import net.runelite.client.ui.ClientUI; import net.runelite.client.ui.NavigationButton; -import net.runelite.client.ui.overlay.Overlay; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -51,19 +49,13 @@ public class Hiscore extends Plugin private final RuneLite runeLite = RuneLite.getRunelite(); private final ClientUI ui = runeLite.getGui(); - public Hiscore() + @Override + protected void startUp() throws Exception { navButton.getButton().addActionListener(this::setPluginPanel); - try - { - ImageIcon icon = new ImageIcon(ImageIO.read(getClass().getResourceAsStream("hiscore.gif"))); - navButton.getButton().setIcon(icon); - } - catch (IOException ex) - { - logger.warn(null, ex); - } + ImageIcon icon = new ImageIcon(ImageIO.read(getClass().getResourceAsStream("hiscore.gif"))); + navButton.getButton().setIcon(icon); ui.getNavigationPanel().addNavigation(navButton); @@ -71,9 +63,8 @@ public class Hiscore extends Plugin } @Override - public Overlay getOverlay() + protected void shutDown() throws Exception { - return null; } private void setPluginPanel(ActionEvent e) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifier.java b/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifier.java index 967f8b322a..8a3774eac4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifier.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifier.java @@ -30,6 +30,7 @@ import java.awt.TrayIcon; import java.time.Duration; import java.time.Instant; import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import static net.runelite.api.AnimationID.*; import net.runelite.api.Client; @@ -37,7 +38,6 @@ import net.runelite.api.GameState; import net.runelite.client.RuneLite; import net.runelite.client.events.AnimationChanged; import net.runelite.client.plugins.Plugin; -import net.runelite.client.ui.overlay.Overlay; public class IdleNotifier extends Plugin { @@ -48,19 +48,21 @@ public class IdleNotifier extends Plugin private final Client client = RuneLite.getClient(); private final TrayIcon trayIcon = RuneLite.getTrayIcon(); + private ScheduledFuture future; private Instant lastAnimating; private boolean notifyIdle = false; @Override - public Overlay getOverlay() - { - return null; - } - - public IdleNotifier() + protected void startUp() throws Exception { ScheduledExecutorService executor = RuneLite.getRunelite().getExecutor(); - executor.scheduleAtFixedRate(this::checkIdle, CHECK_INTERVAL, CHECK_INTERVAL, TimeUnit.SECONDS); + future = executor.scheduleAtFixedRate(this::checkIdle, CHECK_INTERVAL, CHECK_INTERVAL, TimeUnit.SECONDS); + } + + @Override + protected void shutDown() throws Exception + { + future.cancel(true); } @Subscribe @@ -124,7 +126,7 @@ public class IdleNotifier extends Plugin private void checkIdle() { if (notifyIdle && client.getLocalPlayer().getAnimation() == IDLE - && Instant.now().compareTo(lastAnimating.plus(WAIT_DURATION)) >= 0) + && Instant.now().compareTo(lastAnimating.plus(WAIT_DURATION)) >= 0) { trayIcon.displayMessage("RuneLite", "You are now idle.", TrayIcon.MessageType.NONE); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfo.java b/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfo.java index a36f840b60..8a25fcb71b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfo.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfo.java @@ -22,7 +22,6 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - package net.runelite.client.plugins.opponentinfo; import com.google.common.reflect.TypeToken; @@ -44,6 +43,16 @@ public class OpponentInfo extends Plugin return overlay; } + @Override + protected void startUp() throws Exception + { + } + + @Override + protected void shutDown() throws Exception + { + } + public static Map loadNpcHealth() { Gson gson = new Gson(); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/Runecraft.java b/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/Runecraft.java index 637f7e49c7..b12abcc1e2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/Runecraft.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/Runecraft.java @@ -37,4 +37,13 @@ public class Runecraft extends Plugin return overlay; } + @Override + protected void startUp() throws Exception + { + } + + @Override + protected void shutDown() throws Exception + { + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xtea/Xtea.java b/runelite-client/src/main/java/net/runelite/client/plugins/xtea/Xtea.java index cfe405bdb4..a22eb33a8c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xtea/Xtea.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xtea/Xtea.java @@ -51,9 +51,13 @@ public class Xtea extends Plugin private final Set sentRegions = new HashSet<>(); @Override - public Overlay getOverlay() + protected void startUp() throws Exception + { + } + + @Override + protected void shutDown() throws Exception { - return null; } @Subscribe