client: don't crash if we can't create a local socket

This commit is contained in:
ThatGamerBlue
2021-05-24 23:15:54 +01:00
parent 90e332ab82
commit 26864092c8
3 changed files with 89 additions and 48 deletions

View File

@@ -1,7 +1,10 @@
package com.openosrs.client.util; package com.openosrs.client.util;
import com.openosrs.client.OpenOSRS; import com.openosrs.client.OpenOSRS;
import com.openosrs.client.config.OpenOSRSConfig;
import com.openosrs.client.ui.OpenOSRSSplashScreen;
import io.reactivex.rxjava3.subjects.PublishSubject; import io.reactivex.rxjava3.subjects.PublishSubject;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@@ -15,12 +18,10 @@ import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.runelite.client.RuneLite; import net.runelite.client.RuneLite;
import com.openosrs.client.config.OpenOSRSConfig;
import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.EventBus;
import net.runelite.client.eventbus.Subscribe; import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.events.ClientShutdown; import net.runelite.client.events.ClientShutdown;
import net.runelite.client.events.ConfigChanged; import net.runelite.client.events.ConfigChanged;
import com.openosrs.client.ui.OpenOSRSSplashScreen;
import org.jgroups.Address; import org.jgroups.Address;
import org.jgroups.JChannel; import org.jgroups.JChannel;
import org.jgroups.Message; import org.jgroups.Message;
@@ -33,8 +34,11 @@ import org.jgroups.util.Util;
@Singleton @Singleton
public class Groups implements Receiver public class Groups implements Receiver
{ {
private final OpenOSRSConfig openOSRSConfig; @Inject
private final JChannel channel; private OpenOSRSConfig openOSRSConfig;
@Inject
private EventBus eventBus;
private JChannel channel;
@Getter(AccessLevel.PUBLIC) @Getter(AccessLevel.PUBLIC)
private int instanceCount; private int instanceCount;
@@ -47,31 +51,49 @@ public class Groups implements Receiver
@Getter(AccessLevel.PUBLIC) @Getter(AccessLevel.PUBLIC)
private final PublishSubject<Message> messageObjectSubject = PublishSubject.create(); private final PublishSubject<Message> messageObjectSubject = PublishSubject.create();
@Inject public boolean init()
public Groups(OpenOSRSConfig openOSRSConfig, EventBus eventBus) throws Exception
{ {
this.openOSRSConfig = openOSRSConfig;
try (final InputStream is = RuneLite.class.getResourceAsStream("/udp-openosrs.xml")) try (final InputStream is = RuneLite.class.getResourceAsStream("/udp-openosrs.xml"))
{ {
this.channel = new JChannel(is) channel = new JChannel(is)
.setName(OpenOSRS.uuid) .setName(OpenOSRS.uuid)
.setReceiver(this) .setReceiver(this)
.setDiscardOwnMessages(true) .setDiscardOwnMessages(true)
.connect("openosrs"); .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 @Subscribe
public void onClientShutdown(ClientShutdown event) public void onClientShutdown(ClientShutdown event)
{ {
Future<Void> f = close(); Future<Void> f = close();
event.waitFor(f);
if (f != null)
{
event.waitFor(f);
}
} }
public void broadcastSring(String command) public void broadcastString(String command)
{ {
send(null, command); send(null, command);
} }
@@ -119,7 +141,7 @@ public class Groups implements Receiver
public void send(Address destination, String command) public void send(Address destination, String command)
{ {
if (!openOSRSConfig.localSync() || OpenOSRSSplashScreen.showing() || instanceCount < 2) if (!openOSRSConfig.localSync() || OpenOSRSSplashScreen.showing() || instanceCount < 2 || channel == null)
{ {
return; return;
} }
@@ -162,6 +184,11 @@ public class Groups implements Receiver
private CompletableFuture<Void> close() private CompletableFuture<Void> close()
{ {
if (channel == null)
{
return null;
}
CompletableFuture<Void> future = new CompletableFuture<>(); CompletableFuture<Void> future = new CompletableFuture<>();
try try
{ {

View File

@@ -347,6 +347,7 @@ public class RuneLite
pluginManager.setOutdated(isOutdated); pluginManager.setOutdated(isOutdated);
// Load external plugin manager // Load external plugin manager
oprsExternalPluginManager.setupInstance();
oprsExternalPluginManager.startExternalUpdateManager(); oprsExternalPluginManager.startExternalUpdateManager();
oprsExternalPluginManager.startExternalPluginManager(); oprsExternalPluginManager.startExternalPluginManager();

View File

@@ -92,6 +92,7 @@ import org.pf4j.update.PluginInfo;
import org.pf4j.update.UpdateManager; import org.pf4j.update.UpdateManager;
import org.pf4j.update.UpdateRepository; import org.pf4j.update.UpdateRepository;
@SuppressWarnings("UnstableApiUsage")
@Slf4j @Slf4j
@Singleton @Singleton
public class OPRSExternalPluginManager public class OPRSExternalPluginManager
@@ -100,50 +101,48 @@ public class OPRSExternalPluginManager
static final String DEVELOPMENT_MANIFEST_PATH = "build/tmp/jar/MANIFEST.MF"; static final String DEVELOPMENT_MANIFEST_PATH = "build/tmp/jar/MANIFEST.MF";
public static ArrayList<ClassLoader> pluginClassLoaders = new ArrayList<>(); public static ArrayList<ClassLoader> pluginClassLoaders = new ArrayList<>();
private final PluginManager runelitePluginManager; @Inject
private PluginManager runelitePluginManager;
@Getter(AccessLevel.PUBLIC) @Getter(AccessLevel.PUBLIC)
private org.pf4j.PluginManager externalPluginManager; private org.pf4j.PluginManager externalPluginManager;
@Getter(AccessLevel.PUBLIC) @Getter(AccessLevel.PUBLIC)
private final List<UpdateRepository> repositories = new ArrayList<>(); private final List<UpdateRepository> repositories = new ArrayList<>();
private final OpenOSRSConfig openOSRSConfig; @Inject
private final EventBus eventBus; private OpenOSRSConfig openOSRSConfig;
private final ExecutorService executorService; @Inject
private final ConfigManager configManager; private EventBus eventBus;
@Inject
private ExecutorService executorService;
@Inject
private ConfigManager configManager;
private final Map<String, String> pluginsMap = new HashMap<>(); private final Map<String, String> pluginsMap = new HashMap<>();
@Getter(AccessLevel.PUBLIC) @Getter(AccessLevel.PUBLIC)
private static final boolean developmentMode = OpenOSRS.getPluginDevelopmentPath().length > 0; private static final boolean developmentMode = OpenOSRS.getPluginDevelopmentPath().length > 0;
@Getter(AccessLevel.PUBLIC) @Getter(AccessLevel.PUBLIC)
private final Map<String, Map<String, String>> pluginsInfoMap = new HashMap<>(); private final Map<String, Map<String, String>> pluginsInfoMap = new HashMap<>();
private final Groups groups; @Inject
private Groups groups;
@Getter(AccessLevel.PUBLIC) @Getter(AccessLevel.PUBLIC)
private UpdateManager updateManager; private UpdateManager updateManager;
private final boolean safeMode;
@Inject @Inject
public OPRSExternalPluginManager( @Named("safeMode")
@Named("safeMode") final boolean safeMode, private 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;
public void setupInstance()
{
//noinspection ResultOfMethodCallIgnored //noinspection ResultOfMethodCallIgnored
EXTERNALPLUGIN_DIR.mkdirs(); EXTERNALPLUGIN_DIR.mkdirs();
initPluginManager(); initPluginManager();
groups.getMessageStringSubject() if (!groups.init())
.subscribe(this::receive); {
groups = null;
}
else
{
groups.getMessageStringSubject().subscribe(this::receive);
}
} }
private void initPluginManager() private void initPluginManager()
@@ -478,7 +477,7 @@ public class OPRSExternalPluginManager
{ {
if (graph.nodes().contains(pluginDependency.value())) if (graph.nodes().contains(pluginDependency.value()))
{ {
graph.putEdge(pluginClazz, (Class<? extends Plugin>) pluginDependency.value()); graph.putEdge(pluginClazz, pluginDependency.value());
} }
} }
} }
@@ -555,7 +554,7 @@ public class OPRSExternalPluginManager
throw new PluginInstantiationException( throw new PluginInstantiationException(
"Unmet dependency for " + clazz.getSimpleName() + ": " + pluginDependency.value().getSimpleName()); "Unmet dependency for " + clazz.getSimpleName() + ": " + pluginDependency.value().getSimpleName());
} }
deps.add((Plugin) dependency.get()); deps.add(dependency.get());
} }
log.info("Loading plugin {}", clazz.getSimpleName()); log.info("Loading plugin {}", clazz.getSimpleName());
@@ -703,7 +702,7 @@ public class OPRSExternalPluginManager
scanAndInstantiate(scannedPlugins, false, false); scanAndInstantiate(scannedPlugins, false, false);
if (groups.getInstanceCount() > 1) if (groups != null && groups.getInstanceCount() > 1)
{ {
for (String pluginId : getDisabledPluginIds()) for (String pluginId : getDisabledPluginIds())
{ {
@@ -826,7 +825,10 @@ public class OPRSExternalPluginManager
externalPluginManager.enablePlugin(pluginId); externalPluginManager.enablePlugin(pluginId);
externalPluginManager.startPlugin(pluginId); externalPluginManager.startPlugin(pluginId);
groups.broadcastSring("STARTEXTERNAL;" + pluginId); if (groups != null)
{
groups.broadcastString("STARTEXTERNAL;" + pluginId);
}
scanAndInstantiate(loadPlugin(pluginId), true, false); scanAndInstantiate(loadPlugin(pluginId), true, false);
ExternalPluginsChanged event = new ExternalPluginsChanged(null); ExternalPluginsChanged event = new ExternalPluginsChanged(null);
eventBus.post(event); eventBus.post(event);
@@ -876,7 +878,10 @@ public class OPRSExternalPluginManager
ExternalPluginsChanged event = new ExternalPluginsChanged(null); ExternalPluginsChanged event = new ExternalPluginsChanged(null);
eventBus.post(event); eventBus.post(event);
groups.broadcastSring("STARTEXTERNAL;" + pluginId); if (groups != null)
{
groups.broadcastString("STARTEXTERNAL;" + pluginId);
}
} }
catch (DependencyResolver.DependenciesNotFoundException ex) catch (DependencyResolver.DependenciesNotFoundException ex)
{ {
@@ -913,7 +918,7 @@ public class OPRSExternalPluginManager
return true; return true;
} }
if (groups.getInstanceCount() > 1) if (groups != null && groups.getInstanceCount() > 1)
{ {
groups.sendString("STOPEXTERNAL;" + pluginId); groups.sendString("STOPEXTERNAL;" + pluginId);
} }
@@ -927,7 +932,7 @@ public class OPRSExternalPluginManager
public void update() 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 // 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"); 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); checkDepsAndStart(combinedList, scannedPlugins, pluginWrapper);
} }
scanAndInstantiate(scannedPlugins, true, false); scanAndInstantiate(scannedPlugins, true, false);
groups.broadcastSring("STARTEXTERNAL;" + pluginId); if (groups != null)
{
groups.broadcastString("STARTEXTERNAL;" + pluginId);
}
return true; return true;
} }
@@ -1052,6 +1059,12 @@ public class OPRSExternalPluginManager
return; 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(";"); String[] messageObject = ((String) message.getObject()).split(";");
if (messageObject.length < 2) if (messageObject.length < 2)