rl-client: add plugin conflict support
This commit is contained in:
@@ -53,6 +53,18 @@ public @interface PluginDescriptor
|
||||
*/
|
||||
String[] tags() default {};
|
||||
|
||||
/**
|
||||
* A list of plugin names that are mutually exclusive with this plugin. Any plugins
|
||||
* with a name or conflicts value that matches this will be disabled when this plugin
|
||||
* is started
|
||||
*/
|
||||
String[] conflicts() default {};
|
||||
|
||||
/**
|
||||
* If this plugin should be defaulted to on. Plugin-Hub plugins should always
|
||||
* have this set to true (the default), since having them off by defaults means
|
||||
* the user has to install the plugin, then separately enable it, which is confusing.
|
||||
*/
|
||||
boolean enabledByDefault() default true;
|
||||
|
||||
/**
|
||||
@@ -62,6 +74,9 @@ public @interface PluginDescriptor
|
||||
|
||||
boolean developerPlugin() default false;
|
||||
|
||||
/**
|
||||
* If this plugin should be loaded when there is no {@link net.runelite.api.Client}
|
||||
*/
|
||||
boolean loadWhenOutdated() default false;
|
||||
|
||||
boolean loadInSafeMode() default true;
|
||||
|
||||
@@ -47,7 +47,9 @@ import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@@ -380,6 +382,19 @@ public class PluginManager
|
||||
return false;
|
||||
}
|
||||
|
||||
List<Plugin> conflicts = conflictsForPlugin(plugin);
|
||||
for (Plugin conflict : conflicts)
|
||||
{
|
||||
if (isPluginEnabled(conflict))
|
||||
{
|
||||
setPluginEnabled(conflict, false);
|
||||
}
|
||||
if (activePlugins.contains(conflict))
|
||||
{
|
||||
stopPlugin(conflict);
|
||||
}
|
||||
}
|
||||
|
||||
activePlugins.add(plugin);
|
||||
|
||||
try
|
||||
@@ -445,6 +460,18 @@ public class PluginManager
|
||||
final PluginDescriptor pluginDescriptor = plugin.getClass().getAnnotation(PluginDescriptor.class);
|
||||
final String keyName = Strings.isNullOrEmpty(pluginDescriptor.configName()) ? plugin.getClass().getSimpleName() : pluginDescriptor.configName();
|
||||
configManager.setConfiguration(RuneLiteConfig.GROUP_NAME, keyName.toLowerCase(), String.valueOf(enabled));
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
List<Plugin> conflicts = conflictsForPlugin(plugin);
|
||||
for (Plugin conflict : conflicts)
|
||||
{
|
||||
if (isPluginEnabled(conflict))
|
||||
{
|
||||
setPluginEnabled(conflict, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isPluginEnabled(Plugin plugin)
|
||||
@@ -638,4 +665,40 @@ public class PluginManager
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
public List<Plugin> conflictsForPlugin(Plugin plugin)
|
||||
{
|
||||
Set<String> conflicts;
|
||||
{
|
||||
PluginDescriptor desc = plugin.getClass().getAnnotation(PluginDescriptor.class);
|
||||
conflicts = new HashSet<>(Arrays.asList(desc.conflicts()));
|
||||
conflicts.add(desc.name());
|
||||
}
|
||||
|
||||
return plugins.stream()
|
||||
.filter(p ->
|
||||
{
|
||||
if (p == plugin)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
PluginDescriptor desc = p.getClass().getAnnotation(PluginDescriptor.class);
|
||||
if (conflicts.contains(desc.name()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
for (String conflict : desc.conflicts())
|
||||
{
|
||||
if (conflicts.contains(conflict))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,6 +211,7 @@ class ConfigPanel extends PluginPanel
|
||||
|
||||
if (pluginConfig.getPlugin() != null)
|
||||
{
|
||||
pluginToggle.setConflicts(pluginConfig.getConflicts());
|
||||
pluginToggle.setSelected(pluginManager.isPluginEnabled(pluginConfig.getPlugin()));
|
||||
pluginToggle.addItemListener(i ->
|
||||
{
|
||||
|
||||
@@ -75,11 +75,11 @@ public class ConfigPlugin extends Plugin
|
||||
pluginListPanel.addFakePlugin(new PluginConfigurationDescriptor(
|
||||
"RuneLite", "RuneLite client settings",
|
||||
new String[]{"client", "notification", "size", "position", "window", "chrome", "focus", "font", "overlay", "tooltip", "infobox"},
|
||||
null, runeLiteConfig, configManager.getConfigDescriptor(runeLiteConfig)
|
||||
runeLiteConfig, configManager.getConfigDescriptor(runeLiteConfig)
|
||||
),
|
||||
new PluginConfigurationDescriptor(
|
||||
"Chat Color", "Recolor chat text", new String[]{"colour", "messages"},
|
||||
null, chatColorConfig, configManager.getConfigDescriptor(chatColorConfig)
|
||||
chatColorConfig, configManager.getConfigDescriptor(chatColorConfig)
|
||||
));
|
||||
pluginListPanel.rebuildPluginList();
|
||||
|
||||
|
||||
@@ -24,8 +24,10 @@
|
||||
*/
|
||||
package net.runelite.client.plugins.config;
|
||||
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.swing.JMenuItem;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Value;
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigDescriptor;
|
||||
@@ -35,6 +37,7 @@ import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.util.LinkBrowser;
|
||||
|
||||
@Value
|
||||
@RequiredArgsConstructor
|
||||
class PluginConfigurationDescriptor
|
||||
{
|
||||
private final String name;
|
||||
@@ -52,11 +55,19 @@ class PluginConfigurationDescriptor
|
||||
@Nullable
|
||||
private final ConfigDescriptor configDescriptor;
|
||||
|
||||
@Nullable
|
||||
private final List<String> conflicts;
|
||||
|
||||
boolean hasConfigurables()
|
||||
{
|
||||
return configDescriptor != null && !configDescriptor.getItems().stream().allMatch(item -> item.getItem().hidden());
|
||||
}
|
||||
|
||||
PluginConfigurationDescriptor(String name, String description, String[] tags, Config config, ConfigDescriptor configDescriptor)
|
||||
{
|
||||
this(name, description, tags, null, config, configDescriptor, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a menu item for linking to a support page for the plugin
|
||||
*
|
||||
|
||||
@@ -69,7 +69,7 @@ class PluginListItem extends JPanel implements SearchablePlugin
|
||||
private final List<String> keywords = new ArrayList<>();
|
||||
|
||||
private final JToggleButton pinButton;
|
||||
private final JToggleButton onOffToggle;
|
||||
private final PluginToggleButton onOffToggle;
|
||||
|
||||
static
|
||||
{
|
||||
@@ -167,6 +167,7 @@ class PluginListItem extends JPanel implements SearchablePlugin
|
||||
add(nameLabel, BorderLayout.CENTER);
|
||||
|
||||
onOffToggle = new PluginToggleButton();
|
||||
onOffToggle.setConflicts(pluginConfig.getConflicts());
|
||||
buttonPanel.add(onOffToggle);
|
||||
if (pluginConfig.getPlugin() != null)
|
||||
{
|
||||
|
||||
@@ -202,6 +202,9 @@ class PluginListPanel extends PluginPanel
|
||||
PluginDescriptor descriptor = plugin.getClass().getAnnotation(PluginDescriptor.class);
|
||||
Config config = pluginManager.getPluginConfigProxy(plugin);
|
||||
ConfigDescriptor configDescriptor = config == null ? null : configManager.getConfigDescriptor(config);
|
||||
List<String> conflicts = pluginManager.conflictsForPlugin(plugin).stream()
|
||||
.map(Plugin::getName)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return new PluginConfigurationDescriptor(
|
||||
descriptor.name(),
|
||||
@@ -209,7 +212,8 @@ class PluginListPanel extends PluginPanel
|
||||
descriptor.tags(),
|
||||
plugin,
|
||||
config,
|
||||
configDescriptor);
|
||||
configDescriptor,
|
||||
conflicts);
|
||||
})
|
||||
)
|
||||
.map(desc ->
|
||||
|
||||
@@ -27,6 +27,7 @@ package net.runelite.client.plugins.config;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.List;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JToggleButton;
|
||||
import net.runelite.client.util.ImageUtil;
|
||||
@@ -51,12 +52,47 @@ class PluginToggleButton extends JToggleButton
|
||||
));
|
||||
}
|
||||
|
||||
private String conflictString = "";
|
||||
|
||||
public PluginToggleButton()
|
||||
{
|
||||
super(OFF_SWITCHER);
|
||||
setSelectedIcon(ON_SWITCHER);
|
||||
SwingUtil.removeButtonDecorations(this);
|
||||
setPreferredSize(new Dimension(25, 0));
|
||||
SwingUtil.addModalTooltip(this, "Disable plugin", "Enable plugin");
|
||||
addItemListener(l -> updateTooltip());
|
||||
updateTooltip();
|
||||
}
|
||||
|
||||
private void updateTooltip()
|
||||
{
|
||||
setToolTipText(isSelected() ? "Disable plugin" : "<html>Enable plugin" + conflictString);
|
||||
}
|
||||
|
||||
public void setConflicts(List<String> conflicts)
|
||||
{
|
||||
if (conflicts != null && !conflicts.isEmpty())
|
||||
{
|
||||
StringBuilder sb = new StringBuilder("<br>Conflicts with ");
|
||||
for (int i = 0; i < conflicts.size() - 2; i++)
|
||||
{
|
||||
sb.append(conflicts.get(i));
|
||||
sb.append(", ");
|
||||
}
|
||||
if (conflicts.size() > 2)
|
||||
{
|
||||
sb.append(conflicts.get(conflicts.size() - 2));
|
||||
sb.append(" and ");
|
||||
}
|
||||
|
||||
sb.append(conflicts.get(conflicts.size() - 1));
|
||||
conflictString = sb.toString();
|
||||
}
|
||||
else
|
||||
{
|
||||
conflictString = "";
|
||||
}
|
||||
|
||||
updateTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user