rl-client: implement our pf4j plugins, extract pf4j out of net.runelite package. (#2883)

This commit is contained in:
Tyler Bochard
2020-12-26 19:28:30 -05:00
committed by GitHub
parent 7c021d2dcc
commit 53fe72452a
35 changed files with 4046 additions and 41 deletions

View File

@@ -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();

View File

@@ -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);
}
}

View File

@@ -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())

View File

@@ -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",

View File

@@ -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;