externals: cache externals classloaders, fix finding enums
This commit is contained in:
@@ -45,6 +45,7 @@ import java.nio.channels.FileLock;
|
|||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -63,6 +64,8 @@ import net.runelite.client.RuneLite;
|
|||||||
import static net.runelite.client.RuneLite.PROFILES_DIR;
|
import static net.runelite.client.RuneLite.PROFILES_DIR;
|
||||||
import net.runelite.client.eventbus.EventBus;
|
import net.runelite.client.eventbus.EventBus;
|
||||||
import net.runelite.client.events.ConfigChanged;
|
import net.runelite.client.events.ConfigChanged;
|
||||||
|
import net.runelite.client.plugins.ExternalPluginManager;
|
||||||
|
import net.runelite.client.plugins.Plugin;
|
||||||
import net.runelite.client.util.ColorUtil;
|
import net.runelite.client.util.ColorUtil;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
@@ -74,13 +77,11 @@ public class ConfigManager
|
|||||||
private static final String STANDARD_SETTINGS_FILE_NAME = "settings.properties";
|
private static final String STANDARD_SETTINGS_FILE_NAME = "settings.properties";
|
||||||
private static final File SETTINGS_FILE = new File(RuneLite.RUNELITE_DIR, SETTINGS_FILE_NAME);
|
private static final File SETTINGS_FILE = new File(RuneLite.RUNELITE_DIR, SETTINGS_FILE_NAME);
|
||||||
private static final File STANDARD_SETTINGS_FILE = new File(RuneLite.RUNELITE_DIR, STANDARD_SETTINGS_FILE_NAME);
|
private static final File STANDARD_SETTINGS_FILE = new File(RuneLite.RUNELITE_DIR, STANDARD_SETTINGS_FILE_NAME);
|
||||||
|
|
||||||
@Inject
|
|
||||||
EventBus eventBus;
|
|
||||||
|
|
||||||
private final ConfigInvocationHandler handler = new ConfigInvocationHandler(this);
|
private final ConfigInvocationHandler handler = new ConfigInvocationHandler(this);
|
||||||
private final Properties properties = new Properties();
|
private final Properties properties = new Properties();
|
||||||
private final Map<String, String> pendingChanges = new HashMap<>();
|
private final Map<String, String> pendingChanges = new HashMap<>();
|
||||||
|
@Inject
|
||||||
|
EventBus eventBus;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ConfigManager(ScheduledExecutorService scheduledExecutorService)
|
public ConfigManager(ScheduledExecutorService scheduledExecutorService)
|
||||||
@@ -88,6 +89,261 @@ public class ConfigManager
|
|||||||
scheduledExecutorService.scheduleWithFixedDelay(this::sendConfig, 30, 30, TimeUnit.SECONDS);
|
scheduledExecutorService.scheduleWithFixedDelay(this::sendConfig, 30, 30, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
static Object stringToObject(String str, Class<?> type)
|
||||||
|
{
|
||||||
|
if (type == boolean.class || type == Boolean.class)
|
||||||
|
{
|
||||||
|
return Boolean.parseBoolean(str);
|
||||||
|
}
|
||||||
|
if (type == int.class)
|
||||||
|
{
|
||||||
|
return Integer.parseInt(str);
|
||||||
|
}
|
||||||
|
if (type == long.class)
|
||||||
|
{
|
||||||
|
return Long.parseLong(str);
|
||||||
|
}
|
||||||
|
if (type == Color.class)
|
||||||
|
{
|
||||||
|
return ColorUtil.fromString(str);
|
||||||
|
}
|
||||||
|
if (type == Dimension.class)
|
||||||
|
{
|
||||||
|
String[] splitStr = str.split("x");
|
||||||
|
int width = Integer.parseInt(splitStr[0]);
|
||||||
|
int height = Integer.parseInt(splitStr[1]);
|
||||||
|
return new Dimension(width, height);
|
||||||
|
}
|
||||||
|
if (type == Point.class)
|
||||||
|
{
|
||||||
|
String[] splitStr = str.split(":");
|
||||||
|
int width = Integer.parseInt(splitStr[0]);
|
||||||
|
int height = Integer.parseInt(splitStr[1]);
|
||||||
|
return new Point(width, height);
|
||||||
|
}
|
||||||
|
if (type == Rectangle.class)
|
||||||
|
{
|
||||||
|
String[] splitStr = str.split(":");
|
||||||
|
int x = Integer.parseInt(splitStr[0]);
|
||||||
|
int y = Integer.parseInt(splitStr[1]);
|
||||||
|
int width = Integer.parseInt(splitStr[2]);
|
||||||
|
int height = Integer.parseInt(splitStr[3]);
|
||||||
|
return new Rectangle(x, y, width, height);
|
||||||
|
}
|
||||||
|
if (type.isEnum())
|
||||||
|
{
|
||||||
|
return Enum.valueOf((Class<? extends Enum>) type, str);
|
||||||
|
}
|
||||||
|
if (type == Instant.class)
|
||||||
|
{
|
||||||
|
return Instant.parse(str);
|
||||||
|
}
|
||||||
|
if (type == Keybind.class || type == ModifierlessKeybind.class)
|
||||||
|
{
|
||||||
|
String[] splitStr = str.split(":");
|
||||||
|
int code = Integer.parseInt(splitStr[0]);
|
||||||
|
int mods = Integer.parseInt(splitStr[1]);
|
||||||
|
if (type == ModifierlessKeybind.class)
|
||||||
|
{
|
||||||
|
return new ModifierlessKeybind(code, mods);
|
||||||
|
}
|
||||||
|
return new Keybind(code, mods);
|
||||||
|
}
|
||||||
|
if (type == WorldPoint.class)
|
||||||
|
{
|
||||||
|
String[] splitStr = str.split(":");
|
||||||
|
int x = Integer.parseInt(splitStr[0]);
|
||||||
|
int y = Integer.parseInt(splitStr[1]);
|
||||||
|
int plane = Integer.parseInt(splitStr[2]);
|
||||||
|
return new WorldPoint(x, y, plane);
|
||||||
|
}
|
||||||
|
if (type == Duration.class)
|
||||||
|
{
|
||||||
|
return Duration.ofMillis(Long.parseLong(str));
|
||||||
|
}
|
||||||
|
if (type == int[].class)
|
||||||
|
{
|
||||||
|
if (str.contains(","))
|
||||||
|
{
|
||||||
|
return Arrays.stream(str.split(",")).mapToInt(Integer::valueOf).toArray();
|
||||||
|
}
|
||||||
|
return new int[]{Integer.parseInt(str)};
|
||||||
|
}
|
||||||
|
if (type == EnumSet.class)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String substring = str.substring(str.indexOf("{") + 1, str.length() - 1);
|
||||||
|
String[] splitStr = substring.split(", ");
|
||||||
|
Class<? extends Enum> enumClass = null;
|
||||||
|
if (!str.contains("{"))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
enumClass = findEnumClass(str, ExternalPluginManager.pluginClassLoaders);
|
||||||
|
|
||||||
|
EnumSet enumSet = EnumSet.noneOf(enumClass);
|
||||||
|
for (String s : splitStr)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
enumSet.add(Enum.valueOf(enumClass, s.replace("[", "").replace("]", "")));
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException ignore)
|
||||||
|
{
|
||||||
|
return EnumSet.noneOf(enumClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return enumSet;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (type == Map.class)
|
||||||
|
{
|
||||||
|
Map<String, String> output = new HashMap<>();
|
||||||
|
str = str.substring(1, str.length() - 1);
|
||||||
|
String[] splitStr = str.split(", ");
|
||||||
|
for (String s : splitStr)
|
||||||
|
{
|
||||||
|
String[] keyVal = s.split("=");
|
||||||
|
if (keyVal.length > 1)
|
||||||
|
{
|
||||||
|
output.put(keyVal[0], keyVal[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
static String objectToString(Object object)
|
||||||
|
{
|
||||||
|
if (object instanceof Color)
|
||||||
|
{
|
||||||
|
return String.valueOf(((Color) object).getRGB());
|
||||||
|
}
|
||||||
|
if (object instanceof Enum)
|
||||||
|
{
|
||||||
|
return ((Enum) object).name();
|
||||||
|
}
|
||||||
|
if (object instanceof Dimension)
|
||||||
|
{
|
||||||
|
Dimension d = (Dimension) object;
|
||||||
|
return d.width + "x" + d.height;
|
||||||
|
}
|
||||||
|
if (object instanceof Point)
|
||||||
|
{
|
||||||
|
Point p = (Point) object;
|
||||||
|
return p.x + ":" + p.y;
|
||||||
|
}
|
||||||
|
if (object instanceof Rectangle)
|
||||||
|
{
|
||||||
|
Rectangle r = (Rectangle) object;
|
||||||
|
return r.x + ":" + r.y + ":" + r.width + ":" + r.height;
|
||||||
|
}
|
||||||
|
if (object instanceof Instant)
|
||||||
|
{
|
||||||
|
return ((Instant) object).toString();
|
||||||
|
}
|
||||||
|
if (object instanceof Keybind)
|
||||||
|
{
|
||||||
|
Keybind k = (Keybind) object;
|
||||||
|
return k.getKeyCode() + ":" + k.getModifiers();
|
||||||
|
}
|
||||||
|
if (object instanceof WorldPoint)
|
||||||
|
{
|
||||||
|
WorldPoint wp = (WorldPoint) object;
|
||||||
|
return wp.getX() + ":" + wp.getY() + ":" + wp.getPlane();
|
||||||
|
}
|
||||||
|
if (object instanceof Duration)
|
||||||
|
{
|
||||||
|
return Long.toString(((Duration) object).toMillis());
|
||||||
|
}
|
||||||
|
if (object instanceof int[])
|
||||||
|
{
|
||||||
|
if (((int[]) object).length == 0)
|
||||||
|
{
|
||||||
|
return String.valueOf(object);
|
||||||
|
}
|
||||||
|
return StringUtils.join(object, ",");
|
||||||
|
}
|
||||||
|
if (object instanceof EnumSet)
|
||||||
|
{
|
||||||
|
if (((EnumSet) object).size() == 0)
|
||||||
|
{
|
||||||
|
return getElementType((EnumSet) object).getCanonicalName() + "{}";
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((EnumSet) object).toArray()[0].getClass().getCanonicalName() + "{" + object.toString() + "}";
|
||||||
|
}
|
||||||
|
if (object instanceof Number)
|
||||||
|
{
|
||||||
|
return String.valueOf(object);
|
||||||
|
}
|
||||||
|
return object.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends Enum<T>> Class<T> getElementType(EnumSet<T> enumSet)
|
||||||
|
{
|
||||||
|
if (enumSet.isEmpty())
|
||||||
|
{
|
||||||
|
enumSet = EnumSet.complementOf(enumSet);
|
||||||
|
}
|
||||||
|
return enumSet.iterator().next().getDeclaringClass();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Class<? extends Enum> findEnumClass(String clasz, ArrayList<ClassLoader> classLoaders)
|
||||||
|
{
|
||||||
|
StringBuilder transformedString = new StringBuilder();
|
||||||
|
for (ClassLoader cl : classLoaders)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String[] strings = clasz.substring(0, clasz.indexOf("{")).split("\\.");
|
||||||
|
int i = 0;
|
||||||
|
while (i != strings.length)
|
||||||
|
{
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
transformedString.append(strings[i]);
|
||||||
|
}
|
||||||
|
else if (i == strings.length - 1)
|
||||||
|
{
|
||||||
|
transformedString.append("$").append(strings[i]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
transformedString.append(".").append(strings[i]);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return (Class<? extends Enum>) cl.loadClass(transformedString.toString());
|
||||||
|
}
|
||||||
|
catch (Exception e2)
|
||||||
|
{
|
||||||
|
// Will likely fail a lot
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return (Class<? extends Enum>) cl.loadClass(clasz.substring(0, clasz.indexOf("{")));
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
// Will likely fail a lot
|
||||||
|
}
|
||||||
|
transformedString = new StringBuilder();
|
||||||
|
}
|
||||||
|
throw new RuntimeException("Failed to find Enum for " + clasz.substring(0, clasz.indexOf("{")));
|
||||||
|
}
|
||||||
|
|
||||||
public final void switchSession()
|
public final void switchSession()
|
||||||
{
|
{
|
||||||
// Ensure existing config is saved
|
// Ensure existing config is saved
|
||||||
@@ -439,213 +695,81 @@ public class ConfigManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
/**
|
||||||
static Object stringToObject(String str, Class<?> type)
|
* Initialize the configuration from the default settings, for an external Plugin
|
||||||
|
*
|
||||||
|
* @param proxy
|
||||||
|
*/
|
||||||
|
public void setDefaultConfiguration(Object proxy, boolean override, Plugin plugin)
|
||||||
{
|
{
|
||||||
if (type == boolean.class || type == Boolean.class)
|
Class<?> clazz = proxy.getClass().getInterfaces()[0];
|
||||||
|
ConfigGroup group = clazz.getAnnotation(ConfigGroup.class);
|
||||||
|
|
||||||
|
if (group == null)
|
||||||
{
|
{
|
||||||
return Boolean.parseBoolean(str);
|
return;
|
||||||
}
|
}
|
||||||
if (type == int.class)
|
|
||||||
|
for (Method method : clazz.getDeclaredMethods())
|
||||||
{
|
{
|
||||||
return Integer.parseInt(str);
|
ConfigItem item = method.getAnnotation(ConfigItem.class);
|
||||||
}
|
|
||||||
if (type == long.class)
|
// only apply default configuration for methods which read configuration (0 args)
|
||||||
{
|
if (item == null || method.getParameterCount() != 0)
|
||||||
return Long.parseLong(str);
|
|
||||||
}
|
|
||||||
if (type == Color.class)
|
|
||||||
{
|
|
||||||
return ColorUtil.fromString(str);
|
|
||||||
}
|
|
||||||
if (type == Dimension.class)
|
|
||||||
{
|
|
||||||
String[] splitStr = str.split("x");
|
|
||||||
int width = Integer.parseInt(splitStr[0]);
|
|
||||||
int height = Integer.parseInt(splitStr[1]);
|
|
||||||
return new Dimension(width, height);
|
|
||||||
}
|
|
||||||
if (type == Point.class)
|
|
||||||
{
|
|
||||||
String[] splitStr = str.split(":");
|
|
||||||
int width = Integer.parseInt(splitStr[0]);
|
|
||||||
int height = Integer.parseInt(splitStr[1]);
|
|
||||||
return new Point(width, height);
|
|
||||||
}
|
|
||||||
if (type == Rectangle.class)
|
|
||||||
{
|
|
||||||
String[] splitStr = str.split(":");
|
|
||||||
int x = Integer.parseInt(splitStr[0]);
|
|
||||||
int y = Integer.parseInt(splitStr[1]);
|
|
||||||
int width = Integer.parseInt(splitStr[2]);
|
|
||||||
int height = Integer.parseInt(splitStr[3]);
|
|
||||||
return new Rectangle(x, y, width, height);
|
|
||||||
}
|
|
||||||
if (type.isEnum())
|
|
||||||
{
|
|
||||||
return Enum.valueOf((Class<? extends Enum>) type, str);
|
|
||||||
}
|
|
||||||
if (type == Instant.class)
|
|
||||||
{
|
|
||||||
return Instant.parse(str);
|
|
||||||
}
|
|
||||||
if (type == Keybind.class || type == ModifierlessKeybind.class)
|
|
||||||
{
|
|
||||||
String[] splitStr = str.split(":");
|
|
||||||
int code = Integer.parseInt(splitStr[0]);
|
|
||||||
int mods = Integer.parseInt(splitStr[1]);
|
|
||||||
if (type == ModifierlessKeybind.class)
|
|
||||||
{
|
{
|
||||||
return new ModifierlessKeybind(code, mods);
|
continue;
|
||||||
}
|
}
|
||||||
return new Keybind(code, mods);
|
|
||||||
}
|
if (!method.isDefault())
|
||||||
if (type == WorldPoint.class)
|
|
||||||
{
|
|
||||||
String[] splitStr = str.split(":");
|
|
||||||
int x = Integer.parseInt(splitStr[0]);
|
|
||||||
int y = Integer.parseInt(splitStr[1]);
|
|
||||||
int plane = Integer.parseInt(splitStr[2]);
|
|
||||||
return new WorldPoint(x, y, plane);
|
|
||||||
}
|
|
||||||
if (type == Duration.class)
|
|
||||||
{
|
|
||||||
return Duration.ofMillis(Long.parseLong(str));
|
|
||||||
}
|
|
||||||
if (type == int[].class)
|
|
||||||
{
|
|
||||||
if (str.contains(","))
|
|
||||||
{
|
{
|
||||||
return Arrays.stream(str.split(",")).mapToInt(Integer::valueOf).toArray();
|
if (override)
|
||||||
|
{
|
||||||
|
String current = getConfiguration(group.value(), item.keyName());
|
||||||
|
// only unset if already set
|
||||||
|
if (current != null)
|
||||||
|
{
|
||||||
|
unsetConfiguration(group.value(), item.keyName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
return new int[]{Integer.parseInt(str)};
|
|
||||||
}
|
if (!override)
|
||||||
if (type == EnumSet.class)
|
{
|
||||||
{
|
// This checks if it is set and is also unmarshallable to the correct type; so
|
||||||
|
// we will overwrite invalid config values with the default
|
||||||
|
Object current = getConfiguration(group.value(), item.keyName(), method.getReturnType());
|
||||||
|
if (current != null)
|
||||||
|
{
|
||||||
|
continue; // something else is already set
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Object defaultValue;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
String substring = str.substring(str.indexOf("{") + 1, str.length() - 1);
|
defaultValue = ConfigInvocationHandler.callDefaultMethod(proxy, method, null);
|
||||||
String[] splitStr = substring.split(", ");
|
|
||||||
final Class<? extends Enum> enumClass;
|
|
||||||
if (!str.contains("{"))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
enumClass = (Class<? extends Enum>) Class.forName(str.substring(0, str.indexOf("{")));
|
|
||||||
EnumSet enumSet = EnumSet.noneOf(enumClass);
|
|
||||||
for (String s : splitStr)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
enumSet.add(Enum.valueOf(enumClass, s.replace("[", "").replace("]", "")));
|
|
||||||
}
|
|
||||||
catch (IllegalArgumentException ignore)
|
|
||||||
{
|
|
||||||
return EnumSet.noneOf(enumClass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return enumSet;
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Throwable ex)
|
||||||
{
|
{
|
||||||
e.printStackTrace();
|
log.warn(null, ex);
|
||||||
return null;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
String current = getConfiguration(group.value(), item.keyName());
|
||||||
if (type == Map.class)
|
String valueString = objectToString(defaultValue);
|
||||||
{
|
// null and the empty string are treated identically in sendConfig and treated as an unset
|
||||||
Map<String, String> output = new HashMap<>();
|
// If a config value defaults to "" and the current value is null, it will cause an extra
|
||||||
str = str.substring(1, str.length() - 1);
|
// unset to be sent, so treat them as equal
|
||||||
String[] splitStr = str.split(", ");
|
if (Objects.equals(current, valueString) || (Strings.isNullOrEmpty(current) && Strings.isNullOrEmpty(valueString)))
|
||||||
for (String s : splitStr)
|
|
||||||
{
|
{
|
||||||
String[] keyVal = s.split("=");
|
continue; // already set to the default value
|
||||||
if (keyVal.length > 1)
|
|
||||||
{
|
|
||||||
output.put(keyVal[0], keyVal[1]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
log.debug("Setting default configuration value for {}.{} to {}", group.value(), item.keyName(), defaultValue);
|
||||||
}
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
static String objectToString(Object object)
|
setConfiguration(group.value(), item.keyName(), valueString);
|
||||||
{
|
|
||||||
if (object instanceof Color)
|
|
||||||
{
|
|
||||||
return String.valueOf(((Color) object).getRGB());
|
|
||||||
}
|
}
|
||||||
if (object instanceof Enum)
|
|
||||||
{
|
|
||||||
return ((Enum) object).name();
|
|
||||||
}
|
|
||||||
if (object instanceof Dimension)
|
|
||||||
{
|
|
||||||
Dimension d = (Dimension) object;
|
|
||||||
return d.width + "x" + d.height;
|
|
||||||
}
|
|
||||||
if (object instanceof Point)
|
|
||||||
{
|
|
||||||
Point p = (Point) object;
|
|
||||||
return p.x + ":" + p.y;
|
|
||||||
}
|
|
||||||
if (object instanceof Rectangle)
|
|
||||||
{
|
|
||||||
Rectangle r = (Rectangle) object;
|
|
||||||
return r.x + ":" + r.y + ":" + r.width + ":" + r.height;
|
|
||||||
}
|
|
||||||
if (object instanceof Instant)
|
|
||||||
{
|
|
||||||
return ((Instant) object).toString();
|
|
||||||
}
|
|
||||||
if (object instanceof Keybind)
|
|
||||||
{
|
|
||||||
Keybind k = (Keybind) object;
|
|
||||||
return k.getKeyCode() + ":" + k.getModifiers();
|
|
||||||
}
|
|
||||||
if (object instanceof WorldPoint)
|
|
||||||
{
|
|
||||||
WorldPoint wp = (WorldPoint) object;
|
|
||||||
return wp.getX() + ":" + wp.getY() + ":" + wp.getPlane();
|
|
||||||
}
|
|
||||||
if (object instanceof Duration)
|
|
||||||
{
|
|
||||||
return Long.toString(((Duration) object).toMillis());
|
|
||||||
}
|
|
||||||
if (object instanceof int[])
|
|
||||||
{
|
|
||||||
if (((int[]) object).length == 0)
|
|
||||||
{
|
|
||||||
return String.valueOf(object);
|
|
||||||
}
|
|
||||||
return StringUtils.join(object, ",");
|
|
||||||
}
|
|
||||||
if (object instanceof EnumSet)
|
|
||||||
{
|
|
||||||
if (((EnumSet) object).size() == 0)
|
|
||||||
{
|
|
||||||
return getElementType((EnumSet) object).getCanonicalName() + "{}";
|
|
||||||
}
|
|
||||||
|
|
||||||
return ((EnumSet) object).toArray()[0].getClass().getCanonicalName() + "{" + object.toString() + "}";
|
|
||||||
}
|
|
||||||
if (object instanceof Number)
|
|
||||||
{
|
|
||||||
return String.valueOf(object);
|
|
||||||
}
|
|
||||||
return object.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T extends Enum<T>> Class<T> getElementType(EnumSet<T> enumSet)
|
|
||||||
{
|
|
||||||
if (enumSet.isEmpty())
|
|
||||||
{
|
|
||||||
enumSet = EnumSet.complementOf(enumSet);
|
|
||||||
}
|
|
||||||
return enumSet.iterator().next().getDeclaringClass();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendConfig()
|
public void sendConfig()
|
||||||
|
|||||||
@@ -58,9 +58,9 @@ import org.pf4j.update.VerifyException;
|
|||||||
public
|
public
|
||||||
class ExternalPluginManager
|
class ExternalPluginManager
|
||||||
{
|
{
|
||||||
|
public static ArrayList<ClassLoader> pluginClassLoaders = new ArrayList<>();
|
||||||
private final PluginManager runelitePluginManager;
|
private final PluginManager runelitePluginManager;
|
||||||
private final org.pf4j.PluginManager externalPluginManager;
|
private final 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;
|
private final OpenOSRSConfig openOSRSConfig;
|
||||||
@@ -304,6 +304,7 @@ class ExternalPluginManager
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
pluginClassLoaders.add(plugin.getClass().getClassLoader());
|
||||||
instantiatePlugin(pluginId, plugin);
|
instantiatePlugin(pluginId, plugin);
|
||||||
}
|
}
|
||||||
catch (PluginInstantiationException e)
|
catch (PluginInstantiationException e)
|
||||||
|
|||||||
Reference in New Issue
Block a user