project: Java 17 support, update deps, rework some stupid logic

This commit is contained in:
Owain van Brakel
2021-09-22 14:09:38 +02:00
parent 7644d5e2d1
commit 6df0372290
85 changed files with 894 additions and 1448 deletions

View File

@@ -354,7 +354,7 @@ public class RuneLite
oprsExternalPluginManager.setOutdated(isOutdated);
// Update external plugins
oprsExternalPluginManager.update(); //TODO: Re-enable after fixing actions for new repo
oprsExternalPluginManager.update();
// Load the plugins, but does not start them yet.
// This will initialize configuration

View File

@@ -0,0 +1,24 @@
package net.runelite.client.plugins;
import java.nio.file.Path;
import lombok.extern.slf4j.Slf4j;
import org.pf4j.BasePluginLoader;
import org.pf4j.PluginClassLoader;
import org.pf4j.PluginClasspath;
import org.pf4j.PluginDescriptor;
import org.pf4j.PluginManager;
@Slf4j
class OPRSExternalBasePluginLoader extends BasePluginLoader
{
OPRSExternalBasePluginLoader(PluginManager pluginManager, PluginClasspath pluginClasspath)
{
super(pluginManager, pluginClasspath);
}
@Override
protected PluginClassLoader createPluginClassLoader(Path pluginPath, PluginDescriptor pluginDescriptor)
{
return new OPRSExternalClassLoader(pluginManager, pluginDescriptor, getClass().getClassLoader());
}
}

View File

@@ -0,0 +1,142 @@
package net.runelite.client.plugins;
import java.lang.invoke.MethodHandles;
import java.util.List;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import net.runelite.client.util.ReflectUtil;
import org.pf4j.ClassLoadingStrategy;
import org.pf4j.PluginClassLoader;
import org.pf4j.PluginDependency;
import org.pf4j.PluginDescriptor;
import org.pf4j.PluginManager;
@Slf4j
class OPRSExternalClassLoader extends PluginClassLoader implements ReflectUtil.PrivateLookupableClassLoader
{
private static final String JAVA_PACKAGE_PREFIX = "java.";
private static final String PLUGIN_PACKAGE_PREFIX = "org.pf4j.";
@Getter
@Setter
private MethodHandles.Lookup lookup;
private final PluginManager pluginManager;
private final PluginDescriptor pluginDescriptor;
private final ClassLoadingStrategy classLoadingStrategy;
OPRSExternalClassLoader(PluginManager pluginManager, PluginDescriptor pluginDescriptor, ClassLoader parent)
{
super(pluginManager, pluginDescriptor, parent);
this.pluginManager = pluginManager;
this.pluginDescriptor = pluginDescriptor;
this.classLoadingStrategy = ClassLoadingStrategy.PDA;
ReflectUtil.installLookupHelper(this);
}
@Override
public Class<?> defineClass0(String name, byte[] b, int off, int len) throws ClassFormatError
{
return super.defineClass(name, b, off, len);
}
@Override
protected Class<?> loadClassFromDependencies(String className)
{
log.trace("Search in dependencies for class '{}'", className);
List<org.pf4j.PluginDependency> dependencies = pluginDescriptor.getDependencies();
for (PluginDependency dependency : dependencies)
{
ClassLoader classLoader = pluginManager.getPluginClassLoader(dependency.getPluginId());
// If the dependency is marked as optional, its class loader might not be available.
if (classLoader == null && dependency.isOptional())
{
continue;
}
try
{
if (classLoader != null)
{
return classLoader.loadClass(className);
}
}
catch (ClassNotFoundException e)
{
// try next dependency
}
}
return null;
}
@Override
public Class<?> loadClass(String className) throws ClassNotFoundException
{
synchronized (getClassLoadingLock(className))
{
// first check whether it's a system class, delegate to the system loader
if (className.startsWith(JAVA_PACKAGE_PREFIX))
{
return findSystemClass(className);
}
// if the class is part of the plugin engine use parent class loader
if (className.startsWith(PLUGIN_PACKAGE_PREFIX) && !className.startsWith("org.pf4j.demo"))
{
// log.trace("Delegate the loading of PF4J class '{}' to parent", className);
return getParent().loadClass(className);
}
log.trace("Received request to load class '{}'", className);
// second check whether it's already been loaded
Class<?> loadedClass = findLoadedClass(className);
if (loadedClass != null)
{
log.trace("Found loaded class '{}'", className);
return loadedClass;
}
for (ClassLoadingStrategy.Source classLoadingSource : this.classLoadingStrategy.getSources())
{
Class<?> c = null;
try
{
switch (classLoadingSource)
{
case APPLICATION:
c = super.loadClass(className);
break;
case PLUGIN:
c = findClass(className);
break;
case DEPENDENCIES:
c = loadClassFromDependencies(className);
break;
}
}
catch (ClassNotFoundException ignored)
{
}
if (c != null)
{
log.trace("Found class '{}' in {} classpath", className, classLoadingSource);
return c;
}
else
{
log.trace("Couldn't find class '{}' in {} classpath", className, classLoadingSource);
}
}
throw new ClassNotFoundException(className);
}
}
}

View File

@@ -0,0 +1,26 @@
package net.runelite.client.plugins;
import java.nio.file.Path;
import lombok.extern.slf4j.Slf4j;
import org.pf4j.JarPluginLoader;
import org.pf4j.PluginClassLoader;
import org.pf4j.PluginDescriptor;
import org.pf4j.PluginManager;
@Slf4j
class OPRSExternalJarPluginLoader extends JarPluginLoader
{
public OPRSExternalJarPluginLoader(PluginManager pluginManager)
{
super(pluginManager);
}
@Override
public ClassLoader loadPlugin(Path pluginPath, PluginDescriptor pluginDescriptor)
{
PluginClassLoader pluginClassLoader = new OPRSExternalClassLoader(pluginManager, pluginDescriptor, getClass().getClassLoader());
pluginClassLoader.addFile(pluginPath.toFile());
return pluginClassLoader;
}
}

View File

@@ -17,13 +17,11 @@ import java.util.Set;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import lombok.extern.slf4j.Slf4j;
import org.pf4j.BasePluginLoader;
import org.pf4j.CompoundPluginLoader;
import org.pf4j.CompoundPluginRepository;
import org.pf4j.DefaultPluginManager;
import org.pf4j.DependencyResolver;
import org.pf4j.DevelopmentPluginRepository;
import org.pf4j.JarPluginLoader;
import org.pf4j.JarPluginRepository;
import org.pf4j.ManifestPluginDescriptorFinder;
import org.pf4j.PluginAlreadyLoadedException;
@@ -105,8 +103,8 @@ class OPRSExternalPf4jPluginManager extends DefaultPluginManager
protected PluginLoader createPluginLoader()
{
return new CompoundPluginLoader()
.add(new BasePluginLoader(this, new OPRSExternalPluginClasspath()), this::isDevelopment)
.add(new JarPluginLoader(this), this::isNotDevelopment);
.add(new OPRSExternalBasePluginLoader(this, new OPRSExternalPluginClasspath()), this::isDevelopment)
.add(new OPRSExternalJarPluginLoader(this), this::isNotDevelopment);
}
@Override

View File

@@ -1203,4 +1203,4 @@ public class OPRSExternalPluginManager
{
return URLEncoder.encode(s, StandardCharsets.UTF_8);
}
}
}

View File

@@ -39,7 +39,13 @@ import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import java.io.IOException;
import java.lang.invoke.CallSite;
import java.lang.invoke.LambdaMetafactory;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
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;
@@ -69,9 +75,12 @@ import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.events.PluginChanged;
import net.runelite.client.events.SessionClose;
import net.runelite.client.events.SessionOpen;
import net.runelite.client.task.Schedule;
import net.runelite.client.task.ScheduledMethod;
import net.runelite.client.task.Scheduler;
import net.runelite.client.ui.SplashScreen;
import net.runelite.client.util.GameEventManager;
import net.runelite.client.util.ReflectUtil;
@Singleton
@Slf4j
@@ -651,14 +660,59 @@ public class PluginManager
private void schedule(Plugin plugin)
{
// note to devs: this method will almost certainly merge conflict in the future, just apply the changes in the scheduler instead
scheduler.registerObject(plugin);
for (Method method : plugin.getClass().getMethods())
{
Schedule schedule = method.getAnnotation(Schedule.class);
if (schedule == null)
{
continue;
}
Runnable runnable = null;
try
{
final Class<?> clazz = method.getDeclaringClass();
final MethodHandles.Lookup caller = ReflectUtil.privateLookupIn(clazz);
final MethodType subscription = MethodType.methodType(method.getReturnType(), method.getParameterTypes());
final MethodHandle target = caller.findVirtual(clazz, method.getName(), subscription);
final CallSite site = LambdaMetafactory.metafactory(
caller,
"run",
MethodType.methodType(Runnable.class, clazz),
subscription,
target,
subscription);
final MethodHandle factory = site.getTarget();
runnable = (Runnable) factory.bindTo(plugin).invokeExact();
}
catch (Throwable e)
{
log.warn("Unable to create lambda for method {}", method, e);
}
ScheduledMethod scheduledMethod = new ScheduledMethod(schedule, method, plugin, runnable);
log.debug("Scheduled task {}", scheduledMethod);
scheduler.addScheduledMethod(scheduledMethod);
}
}
private void unschedule(Plugin plugin)
{
// note to devs: this method will almost certainly merge conflict in the future, just apply the changes in the scheduler instead
scheduler.unregisterObject(plugin);
List<ScheduledMethod> methods = new ArrayList<>(scheduler.getScheduledMethods());
for (ScheduledMethod method : methods)
{
if (method.getObject() != plugin)
{
continue;
}
log.debug("Removing scheduled task {}", method);
scheduler.removeScheduledMethod(method);
}
}
/**
@@ -734,4 +788,4 @@ public class PluginManager
})
.collect(Collectors.toList());
}
}
}

View File

@@ -115,6 +115,7 @@ import net.runelite.client.ui.FontManager;
import net.runelite.client.ui.PluginPanel;
import net.runelite.client.ui.components.ColorJButton;
import net.runelite.client.ui.components.ComboBoxListRenderer;
import net.runelite.client.ui.components.ToggleButton;
import net.runelite.client.ui.components.colorpicker.ColorPickerManager;
import net.runelite.client.ui.components.colorpicker.RuneliteColorPicker;
import net.runelite.client.util.ColorUtil;
@@ -487,8 +488,7 @@ class ConfigPanel extends PluginPanel
if (cid.getType() == boolean.class)
{
JCheckBox checkbox = new JCheckBox();
checkbox.setBackground(ColorScheme.LIGHT_GRAY_COLOR);
JCheckBox checkbox = new ToggleButton();
checkbox.setSelected(Boolean.parseBoolean(configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName())));
checkbox.addActionListener(ae -> changeConfiguration(checkbox, cd, cid));
@@ -864,8 +864,8 @@ class ConfigPanel extends PluginPanel
{
String option = String.valueOf(obj).toLowerCase().replace("_", " ");
JCheckBox checkbox = new JCheckBox(option);
checkbox.setBackground(ColorScheme.LIGHT_GRAY_COLOR);
JCheckBox checkbox = new ToggleButton(option);
checkbox.setBackground(ColorScheme.DARK_GRAY_COLOR);
checkbox.setSelected(enumSet.contains(obj));
jcheckboxes.add(checkbox);

View File

@@ -26,41 +26,18 @@
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.ui.ColorScheme;
import net.runelite.client.util.ImageUtil;
import net.runelite.client.util.SwingUtil;
import net.runelite.client.ui.components.ToggleButton;
class PluginToggleButton extends JToggleButton
class PluginToggleButton extends ToggleButton
{
private static final ImageIcon ON_SWITCHER;
private static final ImageIcon OFF_SWITCHER;
static
{
BufferedImage onSwitcher = ImageUtil.loadImageResource(ConfigPanel.class, "switcher_on.png");
ON_SWITCHER = new ImageIcon(ImageUtil.recolorImage(onSwitcher, ColorScheme.BRAND_BLUE));
OFF_SWITCHER = new ImageIcon(ImageUtil.flipImage(
ImageUtil.luminanceScale(
ImageUtil.grayscaleImage(onSwitcher),
0.61f
),
true,
false
));
}
private String conflictString = "";
public PluginToggleButton()
{
super(OFF_SWITCHER);
setSelectedIcon(ON_SWITCHER);
SwingUtil.removeButtonDecorations(this);
super();
setPreferredSize(new Dimension(25, 0));
addItemListener(l -> updateTooltip());
updateTooltip();
}

View File

@@ -78,7 +78,7 @@ import okhttp3.Response;
public class ClientLoader implements Supplier<Applet>
{
private static final String INJECTED_CLIENT_NAME = "/injected-client.oprs";
private static final int NUM_ATTEMPTS = 6;
private static final int NUM_ATTEMPTS = 0;
private static File LOCK_FILE = new File(RuneLite.CACHE_DIR, "cache.lock");
private static File VANILLA_CACHE = new File(RuneLite.CACHE_DIR, "vanilla.cache");
private static File PATCHED_CACHE = new File(RuneLite.CACHE_DIR, "patched.cache");

View File

@@ -24,16 +24,10 @@
*/
package net.runelite.client.task;
import java.lang.invoke.CallSite;
import java.lang.invoke.LambdaMetafactory;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -66,63 +60,6 @@ public class Scheduler
return Collections.unmodifiableList(scheduledMethods);
}
public void registerObject(Object obj)
{
for (Method method : obj.getClass().getMethods())
{
Schedule schedule = method.getAnnotation(Schedule.class);
if (schedule == null)
{
continue;
}
Runnable runnable = null;
try
{
final Class<?> clazz = method.getDeclaringClass();
final MethodHandles.Lookup caller = MethodHandles.privateLookupIn(clazz, MethodHandles.lookup());
final MethodType subscription = MethodType.methodType(method.getReturnType(), method.getParameterTypes());
final MethodHandle target = caller.findVirtual(clazz, method.getName(), subscription);
final CallSite site = LambdaMetafactory.metafactory(
caller,
"run",
MethodType.methodType(Runnable.class, clazz),
subscription,
target,
subscription);
final MethodHandle factory = site.getTarget();
runnable = (Runnable) factory.bindTo(obj).invokeExact();
}
catch (Throwable e)
{
log.warn("Unable to create lambda for method {}", method, e);
}
ScheduledMethod scheduledMethod = new ScheduledMethod(schedule, method, obj, runnable);
log.debug("Scheduled task {}", scheduledMethod);
addScheduledMethod(scheduledMethod);
}
}
public void unregisterObject(Object obj)
{
List<ScheduledMethod> methods = new ArrayList<>(getScheduledMethods());
for (ScheduledMethod method : methods)
{
if (method.getObject() != obj)
{
continue;
}
log.debug("Removing scheduled task {}", method);
removeScheduledMethod(method);
}
}
public void tick()
{
Instant now = Instant.now();

View File

@@ -0,0 +1,78 @@
/*
* Copyright (c) 2019 Abex
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.client.ui.components;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JCheckBox;
import net.runelite.client.ui.ColorScheme;
import net.runelite.client.util.ImageUtil;
import net.runelite.client.util.SwingUtil;
public class ToggleButton extends JCheckBox
{
private static final ImageIcon ON_SWITCHER;
private static final ImageIcon OFF_SWITCHER;
private static final ImageIcon DISABLED_SWITCHER;
static
{
BufferedImage onSwitcher = ImageUtil.loadImageResource(ToggleButton.class, "switcher_on.png");
ON_SWITCHER = new ImageIcon(ImageUtil.recolorImage(onSwitcher, ColorScheme.BRAND_BLUE));
OFF_SWITCHER = new ImageIcon(ImageUtil.flipImage(
ImageUtil.luminanceScale(
ImageUtil.grayscaleImage(onSwitcher),
0.61f
),
true,
false
));
DISABLED_SWITCHER = new ImageIcon(ImageUtil.flipImage(
ImageUtil.luminanceScale(
ImageUtil.grayscaleImage(onSwitcher),
0.4f
),
true,
false
));
}
public ToggleButton()
{
super(OFF_SWITCHER);
setSelectedIcon(ON_SWITCHER);
setDisabledIcon(DISABLED_SWITCHER);
SwingUtil.removeButtonDecorations(this);
}
public ToggleButton(String text)
{
super(text, OFF_SWITCHER, false);
setSelectedIcon(ON_SWITCHER);
setDisabledIcon(DISABLED_SWITCHER);
SwingUtil.removeButtonDecorations(this);
}
}

View File

@@ -59,7 +59,7 @@ public class ObsidianSkin extends SubstanceSkin
ObsidianSkin()
{
final SubstanceSkin.ColorSchemes schemes = SubstanceSkin
.getColorSchemes(getClass().getResource(NAME + ".colorschemes"));
.getColorSchemes(getClass().getResourceAsStream(NAME + ".colorschemes"));
final SubstanceColorScheme activeScheme = schemes.get("RuneLite Active");
final SubstanceColorScheme enabledScheme = schemes.get("RuneLite Enabled");
@@ -119,7 +119,7 @@ public class ObsidianSkin extends SubstanceSkin
.get("RuneLite Decorations Watermark");
this.registerDecorationAreaSchemeBundle(decorationsSchemeBundle, decorationsWatermarkScheme,
DecorationAreaType.TOOLBAR, DecorationAreaType.GENERAL, DecorationAreaType.FOOTER);
DecorationAreaType.TOOLBAR, DecorationAreaType.CONTROL_PANE, DecorationAreaType.FOOTER);
final SubstanceColorSchemeBundle headerSchemeBundle = new SubstanceColorSchemeBundle(activeScheme,
enabledScheme, enabledScheme);
@@ -184,7 +184,6 @@ public class ObsidianSkin extends SubstanceSkin
}
};
this.watermark = null;
this.fillPainter = new FractionBasedFillPainter("RuneLite",
new float[]{0.0f, 0.5f, 1.0f},
new ColorSchemeSingleColorQuery[]{ColorSchemeSingleColorQuery.ULTRALIGHT,

View File

@@ -24,10 +24,9 @@
*/
package net.runelite.client.util;
import com.apple.eawt.Application;
import com.apple.eawt.FullScreenUtilities;
import javax.swing.JFrame;
import lombok.extern.slf4j.Slf4j;
import org.madlonkay.desktopsupport.DesktopSupport;
/**
* A class with OSX-specific functions to improve integration.
@@ -44,7 +43,7 @@ public class OSXUtil
{
if (OSType.getOSType() == OSType.MacOS)
{
FullScreenUtilities.setWindowCanFullScreen(gui, true);
DesktopSupport.getSupport().setWindowCanFullScreen(gui, true);
log.debug("Enabled fullscreen on macOS");
}
}
@@ -54,8 +53,7 @@ public class OSXUtil
*/
public static void requestUserAttention()
{
Application app = Application.getApplication();
app.requestUserAttention(true);
DesktopSupport.getSupport().requestUserAttention(true);
log.debug("Requested user attention on macOS");
}
@@ -64,8 +62,7 @@ public class OSXUtil
*/
public static void requestForeground()
{
Application app = Application.getApplication();
app.requestForeground(true);
DesktopSupport.getSupport().requestForeground(true);
log.debug("Forced focus on macOS");
}
}

View File

@@ -62,6 +62,7 @@ import net.runelite.client.ui.ColorScheme;
import net.runelite.client.ui.NavigationButton;
import net.runelite.client.ui.components.CustomScrollBarUI;
import net.runelite.client.ui.components.SliderUI;
import org.pushingpixels.substance.api.SubstanceSlices;
import org.pushingpixels.substance.internal.SubstanceSynapse;
/**
@@ -217,7 +218,7 @@ public class SwingUtil
button.setSize(scaledImage.getWidth(), scaledImage.getHeight());
button.setToolTipText(navigationButton.getTooltip());
button.setIcon(new ImageIcon(scaledImage));
button.putClientProperty(SubstanceSynapse.FLAT_LOOK, Boolean.TRUE);
button.putClientProperty(SubstanceSynapse.BACKGROUND_APPEARANCE_STRATEGY, SubstanceSlices.BackgroundAppearanceStrategy.FLAT);
button.setFocusable(false);
button.addActionListener(e ->
{