diff --git a/runelite-api/src/main/java/net/runelite/api/GameEngine.java b/runelite-api/src/main/java/net/runelite/api/GameEngine.java index 7a09406875..1e1ffacbde 100644 --- a/runelite-api/src/main/java/net/runelite/api/GameEngine.java +++ b/runelite-api/src/main/java/net/runelite/api/GameEngine.java @@ -51,4 +51,9 @@ public interface GameEngine * @return true if on the main thread, false otherwise */ boolean isClientThread(); + + /** + * Shut downs all open connections and files in client and serializes not serialized data. + */ + void shutDown(); } 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 986cf46a6d..229eec62c8 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLite.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLite.java @@ -35,6 +35,7 @@ import java.io.File; import java.lang.management.ManagementFactory; import java.lang.management.RuntimeMXBean; import java.util.Locale; +import java.util.concurrent.ScheduledExecutorService; import javax.annotation.Nullable; import javax.inject.Provider; import javax.inject.Singleton; @@ -111,6 +112,9 @@ public class RuneLite @Inject private OverlayManager overlayManager; + @Inject + private ScheduledExecutorService executorService; + @Inject private Provider itemManager; @@ -292,8 +296,10 @@ public class RuneLite public void shutdown() { + pluginManager.stopCorePlugins(); clientSessionManager.shutdown(); discordService.close(); + executorService.shutdown(); } @VisibleForTesting 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 5b0fc62e46..fd7cec8c81 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 @@ -214,6 +214,23 @@ public class PluginManager } } + public void stopCorePlugins() + { + List scannedPlugins = new ArrayList<>(plugins); + for (Plugin plugin : scannedPlugins) + { + try + { + stopPlugin(plugin); + plugins.remove(plugin); + } + catch (PluginInstantiationException ex) + { + log.warn("Unable to stop plugin {}. {}", plugin.getClass().getSimpleName(), ex); + } + } + } + List scanAndInstantiate(ClassLoader classLoader, String packageName) throws IOException { MutableGraph> graph = GraphBuilder diff --git a/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java b/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java index 755f71a245..7f71a362a2 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java @@ -36,6 +36,7 @@ import java.awt.Graphics; import java.awt.GraphicsConfiguration; import java.awt.LayoutManager; import java.awt.Rectangle; +import java.awt.SystemTray; import java.awt.TrayIcon; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; @@ -271,6 +272,21 @@ public class ClientUI { saveClientBoundsConfig(); runelite.shutdown(); + + if (SystemTray.isSupported()) + { + SystemTray.getSystemTray().remove(trayIcon); + } + + if (client != null) + { + client.stop(); + } + + if (client instanceof Client) + { + ((Client)client).shutDown(); + } }, this::showWarningOnExit ); diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSGameEngine.java b/runescape-api/src/main/java/net/runelite/rs/api/RSGameEngine.java index 93f091c0c9..9c14fd82fd 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSGameEngine.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSGameEngine.java @@ -32,4 +32,7 @@ public interface RSGameEngine extends GameEngine { @Import("canvas") Canvas getCanvas(); + + @Import("shutDown") + void shutDown(); }