diff --git a/runelite-client/src/main/java/com/openosrs/client/util/Groups.java b/runelite-client/src/main/java/com/openosrs/client/util/Groups.java index 6cd128979f..15ef023a4f 100644 --- a/runelite-client/src/main/java/com/openosrs/client/util/Groups.java +++ b/runelite-client/src/main/java/com/openosrs/client/util/Groups.java @@ -1,7 +1,10 @@ package com.openosrs.client.util; import com.openosrs.client.OpenOSRS; +import com.openosrs.client.config.OpenOSRSConfig; +import com.openosrs.client.ui.OpenOSRSSplashScreen; import io.reactivex.rxjava3.subjects.PublishSubject; +import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; @@ -15,12 +18,10 @@ import lombok.AccessLevel; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import net.runelite.client.RuneLite; -import com.openosrs.client.config.OpenOSRSConfig; import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.events.ClientShutdown; import net.runelite.client.events.ConfigChanged; -import com.openosrs.client.ui.OpenOSRSSplashScreen; import org.jgroups.Address; import org.jgroups.JChannel; import org.jgroups.Message; @@ -33,8 +34,11 @@ import org.jgroups.util.Util; @Singleton public class Groups implements Receiver { - private final OpenOSRSConfig openOSRSConfig; - private final JChannel channel; + @Inject + private OpenOSRSConfig openOSRSConfig; + @Inject + private EventBus eventBus; + private JChannel channel; @Getter(AccessLevel.PUBLIC) private int instanceCount; @@ -47,31 +51,49 @@ public class Groups implements Receiver @Getter(AccessLevel.PUBLIC) private final PublishSubject messageObjectSubject = PublishSubject.create(); - @Inject - public Groups(OpenOSRSConfig openOSRSConfig, EventBus eventBus) throws Exception + public boolean init() { - this.openOSRSConfig = openOSRSConfig; - try (final InputStream is = RuneLite.class.getResourceAsStream("/udp-openosrs.xml")) { - this.channel = new JChannel(is) + channel = new JChannel(is) .setName(OpenOSRS.uuid) .setReceiver(this) .setDiscardOwnMessages(true) .connect("openosrs"); + + eventBus.register(this); + } + catch (IOException ex) + { + log.error("Failed to initialize groups, disabling so we don't crash.", ex); + // just in case the event bus was the thing that threw the error + eventBus.unregister(this); + channel = null; + return false; + } + catch (Exception ex) + { + log.error("Unforeseen exception while initializing groups, disabling.", ex); + eventBus.unregister(this); + channel = null; + return false; } - eventBus.register(this); + return true; } @Subscribe public void onClientShutdown(ClientShutdown event) { Future f = close(); - event.waitFor(f); + + if (f != null) + { + event.waitFor(f); + } } - public void broadcastSring(String command) + public void broadcastString(String command) { send(null, command); } @@ -119,7 +141,7 @@ public class Groups implements Receiver public void send(Address destination, String command) { - if (!openOSRSConfig.localSync() || OpenOSRSSplashScreen.showing() || instanceCount < 2) + if (!openOSRSConfig.localSync() || OpenOSRSSplashScreen.showing() || instanceCount < 2 || channel == null) { return; } @@ -162,6 +184,11 @@ public class Groups implements Receiver private CompletableFuture close() { + if (channel == null) + { + return null; + } + CompletableFuture future = new CompletableFuture<>(); try { 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 ff2f201e7d..594e413f2e 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLite.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLite.java @@ -347,6 +347,7 @@ public class RuneLite pluginManager.setOutdated(isOutdated); // Load external plugin manager + oprsExternalPluginManager.setupInstance(); oprsExternalPluginManager.startExternalUpdateManager(); oprsExternalPluginManager.startExternalPluginManager(); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/OPRSExternalPluginManager.java b/runelite-client/src/main/java/net/runelite/client/plugins/OPRSExternalPluginManager.java index 98b1cb2424..c42398c54f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/OPRSExternalPluginManager.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/OPRSExternalPluginManager.java @@ -92,6 +92,7 @@ import org.pf4j.update.PluginInfo; import org.pf4j.update.UpdateManager; import org.pf4j.update.UpdateRepository; +@SuppressWarnings("UnstableApiUsage") @Slf4j @Singleton public class OPRSExternalPluginManager @@ -100,50 +101,48 @@ public class OPRSExternalPluginManager static final String DEVELOPMENT_MANIFEST_PATH = "build/tmp/jar/MANIFEST.MF"; public static ArrayList pluginClassLoaders = new ArrayList<>(); - private final PluginManager runelitePluginManager; + @Inject + private PluginManager runelitePluginManager; @Getter(AccessLevel.PUBLIC) private org.pf4j.PluginManager externalPluginManager; @Getter(AccessLevel.PUBLIC) private final List repositories = new ArrayList<>(); - private final OpenOSRSConfig openOSRSConfig; - private final EventBus eventBus; - private final ExecutorService executorService; - private final ConfigManager configManager; + @Inject + private OpenOSRSConfig openOSRSConfig; + @Inject + private EventBus eventBus; + @Inject + private ExecutorService executorService; + @Inject + private ConfigManager configManager; private final Map pluginsMap = new HashMap<>(); @Getter(AccessLevel.PUBLIC) private static final boolean developmentMode = OpenOSRS.getPluginDevelopmentPath().length > 0; @Getter(AccessLevel.PUBLIC) private final Map> pluginsInfoMap = new HashMap<>(); - private final Groups groups; + @Inject + private Groups groups; @Getter(AccessLevel.PUBLIC) private UpdateManager updateManager; - private final boolean safeMode; - @Inject - public OPRSExternalPluginManager( - @Named("safeMode") final boolean safeMode, - PluginManager pluginManager, - OpenOSRSConfig openOSRSConfig, - EventBus eventBus, - ExecutorService executorService, - ConfigManager configManager, - Groups groups) - { - this.safeMode = safeMode; - this.runelitePluginManager = pluginManager; - this.openOSRSConfig = openOSRSConfig; - this.eventBus = eventBus; - this.executorService = executorService; - this.configManager = configManager; - this.groups = groups; + @Named("safeMode") + private boolean safeMode; + public void setupInstance() + { //noinspection ResultOfMethodCallIgnored EXTERNALPLUGIN_DIR.mkdirs(); initPluginManager(); - groups.getMessageStringSubject() - .subscribe(this::receive); + if (!groups.init()) + { + groups = null; + } + else + { + groups.getMessageStringSubject().subscribe(this::receive); + } } private void initPluginManager() @@ -478,7 +477,7 @@ public class OPRSExternalPluginManager { if (graph.nodes().contains(pluginDependency.value())) { - graph.putEdge(pluginClazz, (Class) pluginDependency.value()); + graph.putEdge(pluginClazz, pluginDependency.value()); } } } @@ -555,7 +554,7 @@ public class OPRSExternalPluginManager throw new PluginInstantiationException( "Unmet dependency for " + clazz.getSimpleName() + ": " + pluginDependency.value().getSimpleName()); } - deps.add((Plugin) dependency.get()); + deps.add(dependency.get()); } log.info("Loading plugin {}", clazz.getSimpleName()); @@ -703,7 +702,7 @@ public class OPRSExternalPluginManager scanAndInstantiate(scannedPlugins, false, false); - if (groups.getInstanceCount() > 1) + if (groups != null && groups.getInstanceCount() > 1) { for (String pluginId : getDisabledPluginIds()) { @@ -826,7 +825,10 @@ public class OPRSExternalPluginManager externalPluginManager.enablePlugin(pluginId); externalPluginManager.startPlugin(pluginId); - groups.broadcastSring("STARTEXTERNAL;" + pluginId); + if (groups != null) + { + groups.broadcastString("STARTEXTERNAL;" + pluginId); + } scanAndInstantiate(loadPlugin(pluginId), true, false); ExternalPluginsChanged event = new ExternalPluginsChanged(null); eventBus.post(event); @@ -876,7 +878,10 @@ public class OPRSExternalPluginManager ExternalPluginsChanged event = new ExternalPluginsChanged(null); eventBus.post(event); - groups.broadcastSring("STARTEXTERNAL;" + pluginId); + if (groups != null) + { + groups.broadcastString("STARTEXTERNAL;" + pluginId); + } } catch (DependencyResolver.DependenciesNotFoundException ex) { @@ -913,7 +918,7 @@ public class OPRSExternalPluginManager return true; } - if (groups.getInstanceCount() > 1) + if (groups != null && groups.getInstanceCount() > 1) { groups.sendString("STOPEXTERNAL;" + pluginId); } @@ -927,7 +932,7 @@ public class OPRSExternalPluginManager public void update() { - if (groups.getInstanceCount() > 1) + if (groups != null && groups.getInstanceCount() > 1) { // Do not update when there is more than one client open -> api might contain changes log.info("Not updating external plugins since there is more than 1 client open"); @@ -1037,10 +1042,12 @@ public class OPRSExternalPluginManager checkDepsAndStart(combinedList, scannedPlugins, pluginWrapper); } - scanAndInstantiate(scannedPlugins, true, false); - groups.broadcastSring("STARTEXTERNAL;" + pluginId); + if (groups != null) + { + groups.broadcastString("STARTEXTERNAL;" + pluginId); + } return true; } @@ -1052,6 +1059,12 @@ public class OPRSExternalPluginManager return; } + if (groups == null) + { + // Can't receive messages if groups is null anyway, but IntelliJ will complain about potential NPE + return; + } + String[] messageObject = ((String) message.getObject()).split(";"); if (messageObject.length < 2)