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 3e39149043..843fc579ac 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLite.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLite.java @@ -177,6 +177,7 @@ public class RuneLite final OptionParser parser = new OptionParser(); parser.accepts("developer-mode", "Enable developer tools"); parser.accepts("debug", "Show extra debugging output"); + parser.accepts("safe-mode", "Disables external plugins and the GPU plugin"); final ArgumentAcceptingOptionSpec sessionfile = parser.accepts("sessionfile", "Use a specified session file") .withRequiredArg() @@ -266,6 +267,7 @@ public class RuneLite injector = Guice.createInjector(new RuneLiteModule( clientLoader, developerMode, + options.has("safe-mode"), options.valueOf(sessionfile), options.valueOf(configfile))); diff --git a/runelite-client/src/main/java/net/runelite/client/RuneLiteModule.java b/runelite-client/src/main/java/net/runelite/client/RuneLiteModule.java index 7f8dd55ddb..c1489de882 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLiteModule.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLiteModule.java @@ -34,6 +34,7 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.function.Supplier; import javax.annotation.Nullable; import javax.inject.Singleton; +import lombok.AllArgsConstructor; import net.runelite.api.Client; import net.runelite.api.hooks.Callbacks; import net.runelite.client.account.SessionManager; @@ -53,27 +54,22 @@ import net.runelite.http.api.RuneLiteAPI; import okhttp3.Cache; import okhttp3.OkHttpClient; +@AllArgsConstructor public class RuneLiteModule extends AbstractModule { private static final int MAX_OKHTTP_CACHE_SIZE = 20 * 1024 * 1024; // 20mb private final Supplier clientLoader; private final boolean developerMode; + private final boolean safeMode; private final File sessionfile; private final File config; - public RuneLiteModule(Supplier clientLoader, boolean developerMode, File sessionfile, File config) - { - this.clientLoader = clientLoader; - this.developerMode = developerMode; - this.sessionfile = sessionfile; - this.config = config; - } - @Override protected void configure() { bindConstant().annotatedWith(Names.named("developerMode")).to(developerMode); + 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(ScheduledExecutorService.class).toInstance(new ExecutorServiceExceptionLogger(Executors.newSingleThreadScheduledExecutor())); diff --git a/runelite-client/src/main/java/net/runelite/client/externalplugins/ExternalPluginManager.java b/runelite-client/src/main/java/net/runelite/client/externalplugins/ExternalPluginManager.java index 197eb31a53..b2175f3973 100644 --- a/runelite-client/src/main/java/net/runelite/client/externalplugins/ExternalPluginManager.java +++ b/runelite-client/src/main/java/net/runelite/client/externalplugins/ExternalPluginManager.java @@ -44,6 +44,7 @@ import java.util.Set; import java.util.concurrent.ScheduledExecutorService; 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; @@ -75,6 +76,10 @@ public class ExternalPluginManager private static final String PLUGIN_LIST_KEY = "externalPlugins"; private static Class[] builtinExternals = null; + @Inject + @Named("safeMode") + private boolean safeMode; + @Inject private ConfigManager configManager; @@ -115,6 +120,12 @@ public class ExternalPluginManager private void refreshPlugins() { + if (safeMode) + { + log.debug("External plugins are disabled in safe mode!"); + return; + } + Multimap loadedExternalPlugins = HashMultimap.create(); for (Plugin p : pluginManager.getPlugins()) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/PluginDescriptor.java b/runelite-client/src/main/java/net/runelite/client/plugins/PluginDescriptor.java index 540adecc24..57a7a4718f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/PluginDescriptor.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/PluginDescriptor.java @@ -58,4 +58,6 @@ public @interface PluginDescriptor boolean developerPlugin() default false; boolean loadWhenOutdated() default false; + + boolean loadInSafeMode() default true; } 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 f48da0de17..d3f430259b 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 @@ -88,6 +88,7 @@ public class PluginManager private static final String PLUGIN_PACKAGE = "net.runelite.client.plugins"; private final boolean developerMode; + private final boolean safeMode; private final EventBus eventBus; private final Scheduler scheduler; private final ConfigManager configManager; @@ -103,6 +104,7 @@ public class PluginManager @VisibleForTesting PluginManager( @Named("developerMode") final boolean developerMode, + @Named("safeMode") final boolean safeMode, final EventBus eventBus, final Scheduler scheduler, final ConfigManager configManager, @@ -110,6 +112,7 @@ public class PluginManager final Provider sceneTileManager) { this.developerMode = developerMode; + this.safeMode = safeMode; this.eventBus = eventBus; this.scheduler = scheduler; this.configManager = configManager; @@ -309,6 +312,14 @@ public class PluginManager continue; } + if (safeMode && !pluginDescriptor.loadInSafeMode()) + { + log.debug("Disabling {} due to safe mode", clazz); + // also disable the plugin from autostarting later + configManager.unsetConfiguration(RuneLiteConfig.GROUP_NAME, clazz.getSimpleName().toLowerCase()); + continue; + } + Class pluginClass = (Class) clazz; graph.addNode(pluginClass); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java index 4e16ffd2e0..e728c7dfb4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java @@ -98,7 +98,8 @@ import net.runelite.client.util.OSType; name = "GPU", description = "Utilizes the GPU", enabledByDefault = false, - tags = {"fog", "draw distance"} + tags = {"fog", "draw distance"}, + loadInSafeMode = false ) @Slf4j public class GpuPlugin extends Plugin implements DrawCallbacks diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/PluginManagerTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/PluginManagerTest.java index 929d83bbd4..003e43361d 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/PluginManagerTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/PluginManagerTest.java @@ -83,7 +83,7 @@ public class PluginManagerTest public void before() throws IOException { Injector injector = Guice.createInjector(Modules - .override(new RuneLiteModule(() -> null, true, + .override(new RuneLiteModule(() -> null, true, false, RuneLite.DEFAULT_SESSION_FILE, RuneLite.DEFAULT_CONFIG_FILE)) .with(BoundFieldModule.of(this))); @@ -114,7 +114,7 @@ public class PluginManagerTest @Test public void testLoadPlugins() throws Exception { - PluginManager pluginManager = new PluginManager(false, null, null, null, null, null); + PluginManager pluginManager = new PluginManager(false, false, null, null, null, null, null); pluginManager.setOutdated(true); pluginManager.loadCorePlugins(); Collection plugins = pluginManager.getPlugins(); @@ -125,7 +125,7 @@ public class PluginManagerTest .count(); assertEquals(expected, plugins.size()); - pluginManager = new PluginManager(false, null, null, null, null, null); + pluginManager = new PluginManager(false, false, null, null, null, null, null); pluginManager.loadCorePlugins(); plugins = pluginManager.getPlugins(); @@ -146,11 +146,11 @@ public class PluginManagerTest { List modules = new ArrayList<>(); modules.add(new GraphvizModule()); - modules.add(new RuneLiteModule(() -> null, true, + modules.add(new RuneLiteModule(() -> null, true, false, RuneLite.DEFAULT_SESSION_FILE, RuneLite.DEFAULT_CONFIG_FILE)); - PluginManager pluginManager = new PluginManager(true, null, null, null, null, null); + PluginManager pluginManager = new PluginManager(true, false, null, null, null, null, null); pluginManager.loadCorePlugins(); for (Plugin p : pluginManager.getPlugins()) {