rl-client: implement our pf4j plugins, extract pf4j out of net.runelite package. (#2883)
This commit is contained in:
@@ -30,7 +30,7 @@ import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Injector;
|
||||
import com.openosrs.client.PluginManager;
|
||||
import com.openosrs.client.plugins.BuiltInPluginManager;
|
||||
import java.io.File;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.RuntimeMXBean;
|
||||
@@ -112,6 +112,9 @@ public class RuneLite
|
||||
@Inject
|
||||
private ExternalPluginManager externalPluginManager;
|
||||
|
||||
@Inject
|
||||
private com.openosrs.client.plugins.ExternalPluginManager oprsExternalPluginManager;
|
||||
|
||||
@Inject
|
||||
private EventBus eventBus;
|
||||
|
||||
@@ -322,9 +325,19 @@ public class RuneLite
|
||||
// Tell the plugin manager if client is outdated or not
|
||||
pluginManager.setOutdated(isOutdated);
|
||||
|
||||
// Load external plugin manager
|
||||
oprsExternalPluginManager.startExternalUpdateManager();
|
||||
oprsExternalPluginManager.startExternalPluginManager();
|
||||
|
||||
// Update external plugins
|
||||
//oprsExternalPluginManager.update(); //TODO: Re-enable after fixing actions for new repo
|
||||
|
||||
// Load the plugins, but does not start them yet.
|
||||
// This will initialize configuration
|
||||
pluginManager.loadCorePlugins();
|
||||
|
||||
oprsExternalPluginManager.loadPlugins();
|
||||
|
||||
externalPluginManager.loadExternalPlugins();
|
||||
|
||||
SplashScreen.stage(.70, null, "Finalizing configuration");
|
||||
@@ -377,8 +390,8 @@ public class RuneLite
|
||||
overlayManager.add(tooltipOverlay.get());
|
||||
}
|
||||
|
||||
//Load OPRS plugins
|
||||
PluginManager.loadPlugins();
|
||||
//Load built-in OPRS plugins
|
||||
BuiltInPluginManager.loadPlugins();
|
||||
|
||||
// Start plugins
|
||||
pluginManager.startPlugins();
|
||||
|
||||
@@ -24,13 +24,20 @@
|
||||
*/
|
||||
package net.runelite.client;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Provides;
|
||||
import com.google.inject.name.Names;
|
||||
import com.openosrs.client.config.OpenOSRSConfig;
|
||||
import com.openosrs.client.util.NonScheduledExecutorServiceExceptionLogger;
|
||||
import java.applet.Applet;
|
||||
import java.io.File;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Supplier;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Singleton;
|
||||
@@ -129,4 +136,28 @@ public class RuneLiteModule extends AbstractModule
|
||||
{
|
||||
return new ChatClient(okHttpClient);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
OpenOSRSConfig provideOpenOSRSConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(OpenOSRSConfig.class);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
ExecutorService provideExecutorService()
|
||||
{
|
||||
int poolSize = 2 * Runtime.getRuntime().availableProcessors();
|
||||
|
||||
// Will start up to poolSize threads (because of allowCoreThreadTimeOut) as necessary, and times out
|
||||
// unused threads after 1 minute
|
||||
ThreadPoolExecutor executor = new ThreadPoolExecutor(poolSize, poolSize,
|
||||
60L, TimeUnit.SECONDS,
|
||||
new LinkedBlockingQueue<>(),
|
||||
new ThreadFactoryBuilder().setNameFormat("worker-%d").build());
|
||||
executor.allowCoreThreadTimeOut(true);
|
||||
|
||||
return new NonScheduledExecutorServiceExceptionLogger(executor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,8 +47,10 @@ import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
@@ -97,6 +99,7 @@ public class PluginManager
|
||||
|
||||
@Setter
|
||||
boolean isOutdated;
|
||||
private Collection<com.openosrs.client.plugins.Plugin> oprsPlugins;
|
||||
|
||||
@Inject
|
||||
@VisibleForTesting
|
||||
@@ -191,7 +194,26 @@ public class PluginManager
|
||||
injectors.add(RuneLite.getInjector());
|
||||
plugins = getPlugins();
|
||||
}
|
||||
plugins.forEach(pl -> injectors.add(pl.getInjector()));
|
||||
plugins.forEach(pl ->
|
||||
{
|
||||
//TODO: Not sure why this is necessary but it is. The Injector isn't null when its handed off from our ExternalPluginManager.
|
||||
// Hopefully we can figure out the root cause of the underlying issue.
|
||||
if (pl.injector == null)
|
||||
{
|
||||
// Create injector for the module
|
||||
Module pluginModule = (Binder binder) ->
|
||||
{
|
||||
// Since the plugin itself is a module, it won't bind itself, so we'll bind it here
|
||||
binder.bind(com.openosrs.client.plugins.Plugin.class).toInstance((com.openosrs.client.plugins.Plugin)pl);
|
||||
binder.install(pl);
|
||||
};
|
||||
Injector pluginInjector = RuneLite.getInjector().createChildInjector(pluginModule);
|
||||
pluginInjector.injectMembers(pl);
|
||||
pl.injector = pluginInjector;
|
||||
}
|
||||
|
||||
injectors.add(pl.getInjector());
|
||||
});
|
||||
|
||||
List<Config> list = new ArrayList<>();
|
||||
for (Injector injector : injectors)
|
||||
@@ -547,6 +569,64 @@ public class PluginManager
|
||||
return plugins;
|
||||
}
|
||||
|
||||
public Collection<com.openosrs.client.plugins.Plugin> getOprsPlugins()
|
||||
{
|
||||
return oprsPlugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Topologically sort a graph into separate groups.
|
||||
* Each group represents the dependency level of the plugins.
|
||||
* Plugins in group (index) 0 has no dependents.
|
||||
* Plugins in group 1 has dependents in group 0.
|
||||
* Plugins in group 2 has dependents in group 1, etc.
|
||||
* This allows for loading dependent groups serially, starting from the last group,
|
||||
* while loading plugins within each group in parallel.
|
||||
*
|
||||
* @param graph
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public static <T> List<List<T>> topologicalGroupSort(Graph<T> graph)
|
||||
{
|
||||
final Set<T> root = graph.nodes().stream()
|
||||
.filter(node -> graph.inDegree(node) == 0)
|
||||
.collect(Collectors.toSet());
|
||||
final Map<T, Integer> dependencyCount = new HashMap<>();
|
||||
|
||||
root.forEach(n -> dependencyCount.put(n, 0));
|
||||
root.forEach(n -> graph.successors(n)
|
||||
.forEach(m -> incrementChildren(graph, dependencyCount, m, dependencyCount.get(n) + 1)));
|
||||
|
||||
// create list<list> dependency grouping
|
||||
final List<List<T>> dependencyGroups = new ArrayList<>();
|
||||
final int[] curGroup = {-1};
|
||||
|
||||
dependencyCount.entrySet().stream()
|
||||
.sorted(Map.Entry.comparingByValue())
|
||||
.forEach(entry ->
|
||||
{
|
||||
if (entry.getValue() != curGroup[0])
|
||||
{
|
||||
curGroup[0] = entry.getValue();
|
||||
dependencyGroups.add(new ArrayList<>());
|
||||
}
|
||||
dependencyGroups.get(dependencyGroups.size() - 1).add(entry.getKey());
|
||||
});
|
||||
|
||||
return dependencyGroups;
|
||||
}
|
||||
|
||||
private static <T> void incrementChildren(Graph<T> graph, Map<T, Integer> dependencyCount, T n, int val)
|
||||
{
|
||||
if (!dependencyCount.containsKey(n) || dependencyCount.get(n) < val)
|
||||
{
|
||||
dependencyCount.put(n, val);
|
||||
graph.successors(n).forEach(m ->
|
||||
incrementChildren(graph, dependencyCount, m, val + 1));
|
||||
}
|
||||
}
|
||||
|
||||
private void schedule(Plugin plugin)
|
||||
{
|
||||
for (Method method : plugin.getClass().getMethods())
|
||||
|
||||
@@ -76,6 +76,7 @@ class PluginListPanel extends PluginPanel
|
||||
private static final String RUNELITE_GROUP_NAME = RuneLiteConfig.class.getAnnotation(ConfigGroup.class).value();
|
||||
private static final String PINNED_PLUGINS_CONFIG_KEY = "pinnedPlugins";
|
||||
private static final ImmutableList<String> CATEGORY_TAGS = ImmutableList.of(
|
||||
"OpenOSRS",
|
||||
"Combat",
|
||||
"Chat",
|
||||
"Item",
|
||||
|
||||
@@ -128,7 +128,8 @@ public class ClientUI
|
||||
private boolean withTitleBar;
|
||||
private BufferedImage sidebarOpenIcon;
|
||||
private BufferedImage sidebarClosedIcon;
|
||||
private ContainableFrame frame;
|
||||
@Getter
|
||||
private static ContainableFrame frame;
|
||||
private JPanel navContainer;
|
||||
private PluginPanel pluginPanel;
|
||||
private ClientPluginToolbar pluginToolbar;
|
||||
|
||||
Reference in New Issue
Block a user