From 1117eba6205ee5929fb164446dd39e1991a6e4b9 Mon Sep 17 00:00:00 2001 From: Lucwousin Date: Sun, 15 Dec 2019 01:16:59 +0100 Subject: [PATCH 1/5] Change source level to 11, remove reflectutil --- build.gradle.kts | 9 ++- .../config/ConfigInvocationHandler.java | 4 +- .../net/runelite/client/util/ReflectUtil.java | 72 ------------------- runelite-mixins/runelite-mixins.gradle.kts | 10 ++- .../net/runelite/mixins/RSWidgetMixin.java | 38 ++++------ 5 files changed, 26 insertions(+), 107 deletions(-) delete mode 100644 runelite-client/src/main/java/net/runelite/client/util/ReflectUtil.java diff --git a/build.gradle.kts b/build.gradle.kts index 6ffad698ea..d2c29e1231 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -44,7 +44,6 @@ plugins { id(Plugins.latestVersion.first) version Plugins.latestVersion.second id(Plugins.grgit.first) version Plugins.grgit.second - checkstyle application } @@ -83,9 +82,9 @@ subprojects { project.extra["rootPath"] = rootDir.toString().replace("\\", "/") if (this.name != "runescape-client") { - apply(plugin = "checkstyle") + apply() - checkstyle { + configure { maxWarnings = 0 toolVersion = "8.25" isShowViolations = true @@ -114,8 +113,8 @@ subprojects { tasks { java { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 } withType { diff --git a/runelite-client/src/main/java/net/runelite/client/config/ConfigInvocationHandler.java b/runelite-client/src/main/java/net/runelite/client/config/ConfigInvocationHandler.java index 26844922cd..e3adf0fb71 100644 --- a/runelite-client/src/main/java/net/runelite/client/config/ConfigInvocationHandler.java +++ b/runelite-client/src/main/java/net/runelite/client/config/ConfigInvocationHandler.java @@ -26,11 +26,11 @@ package net.runelite.client.config; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; +import java.lang.invoke.MethodHandles; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.util.Objects; import lombok.extern.slf4j.Slf4j; -import net.runelite.client.util.ReflectUtil; @Slf4j class ConfigInvocationHandler implements InvocationHandler @@ -169,7 +169,7 @@ class ConfigInvocationHandler implements InvocationHandler static Object callDefaultMethod(Object proxy, Method method, Object[] args) throws Throwable { Class declaringClass = method.getDeclaringClass(); - return ReflectUtil.privateLookupIn(declaringClass) + return MethodHandles.privateLookupIn(declaringClass, MethodHandles.lookup()) .unreflectSpecial(method, declaringClass) .bindTo(proxy) .invokeWithArguments(args); diff --git a/runelite-client/src/main/java/net/runelite/client/util/ReflectUtil.java b/runelite-client/src/main/java/net/runelite/client/util/ReflectUtil.java deleted file mode 100644 index 76530b6ab6..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/util/ReflectUtil.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2018, Tomas Slusny - * Copyright (c) 2018, 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.util; - -import java.lang.invoke.MethodHandles; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -public class ReflectUtil -{ - private ReflectUtil() - { - } - - public static MethodHandles.Lookup privateLookupIn(Class clazz) - { - try - { - // Java 9+ has privateLookupIn method on MethodHandles, but since we are shipping and using Java 8 - // we need to access it via reflection. This is preferred way because it's Java 9+ public api and is - // likely to not change - final Method privateLookupIn = MethodHandles.class.getMethod("privateLookupIn", Class.class, MethodHandles.Lookup.class); - return (MethodHandles.Lookup) privateLookupIn.invoke(null, clazz, MethodHandles.lookup()); - } - catch (InvocationTargetException | IllegalAccessException e) - { - throw new RuntimeException(e); - } - catch (NoSuchMethodException e) - { - try - { - // In Java 8 we first do standard lookupIn class - final MethodHandles.Lookup lookupIn = MethodHandles.lookup().in(clazz); - - // and then we mark it as trusted for private lookup via reflection on private field - final Field modes = MethodHandles.Lookup.class.getDeclaredField("allowedModes"); - modes.setAccessible(true); - modes.setInt(lookupIn, -1); // -1 == TRUSTED - return lookupIn; - } - catch (ReflectiveOperationException ex) - { - throw new RuntimeException(ex); - } - } - } -} diff --git a/runelite-mixins/runelite-mixins.gradle.kts b/runelite-mixins/runelite-mixins.gradle.kts index 671ec4055f..1a07f77286 100644 --- a/runelite-mixins/runelite-mixins.gradle.kts +++ b/runelite-mixins/runelite-mixins.gradle.kts @@ -29,12 +29,16 @@ dependencies { compileOnly(Libraries.guava) compileOnly(Libraries.javaxInject) compileOnly(Libraries.slf4jApi) - - implementation(project(":runescape-api")) + compileOnly(project(":runescape-api")) } tasks { + java { + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 + disableAutoTargetJvm() + } withType { - options.compilerArgs.addAll(arrayOf("-source", "7", "-Xlint:-unchecked")) + options.compilerArgs.addAll(arrayOf("-Xlint:-unchecked")) } } diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSWidgetMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSWidgetMixin.java index 8135716926..466baf67d1 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSWidgetMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSWidgetMixin.java @@ -24,6 +24,11 @@ */ package net.runelite.mixins; +import java.awt.Rectangle; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; import net.runelite.api.HashTable; import net.runelite.api.Node; import net.runelite.api.Point; @@ -31,20 +36,15 @@ import net.runelite.api.WidgetNode; import net.runelite.api.events.WidgetHiddenChanged; import net.runelite.api.events.WidgetPositioned; import net.runelite.api.mixins.Copy; +import net.runelite.api.mixins.FieldHook; +import net.runelite.api.mixins.Inject; +import net.runelite.api.mixins.Mixin; import net.runelite.api.mixins.Replace; +import net.runelite.api.mixins.Shadow; import net.runelite.api.widgets.Widget; import static net.runelite.api.widgets.WidgetInfo.TO_CHILD; import static net.runelite.api.widgets.WidgetInfo.TO_GROUP; import net.runelite.api.widgets.WidgetItem; -import java.awt.Rectangle; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import net.runelite.api.mixins.FieldHook; -import net.runelite.api.mixins.Inject; -import net.runelite.api.mixins.Mixin; -import net.runelite.api.mixins.Shadow; import net.runelite.rs.api.RSClient; import net.runelite.rs.api.RSModel; import net.runelite.rs.api.RSNode; @@ -215,22 +215,10 @@ public abstract class RSWidgetMixin implements RSWidget Widget parent = getParent(); - if (parent == null) - { - if (TO_GROUP(getId()) != client.getWidgetRoot()) - { - // Widget has no parent and is not the root widget (which is always visible), - // so it's not visible. - return true; - } - } - else if (parent.isHidden()) - { - // If the parent is hidden, this widget is also hidden. - return true; - } - - return false; + // If the parent is hidden, this widget is also hidden. + // Widget has no parent and is not the root widget (which is always visible), + // so it's not visible. + return parent == null ? TO_GROUP(getId()) != client.getWidgetRoot() : parent.isHidden(); } @Inject From 60f26a8c417b94a0e4ed0157656b3bfc3d120fb6 Mon Sep 17 00:00:00 2001 From: Lucwousin Date: Sun, 15 Dec 2019 01:21:52 +0100 Subject: [PATCH 2/5] Make Schedulers::single use client thread --- .../java/net/runelite/client/ClientSessionManager.java | 6 +++--- .../src/main/java/net/runelite/client/RuneLite.java | 2 +- .../java/net/runelite/client/callback/ClientThread.java | 8 ++++++++ .../client/plugins/alchemicalhydra/HydraPlugin.java | 2 +- .../client/plugins/blackjack/BlackjackPlugin.java | 5 ++--- .../client/plugins/chatcommands/ChatCommandsPlugin.java | 2 +- .../runelite/client/plugins/examine/ExaminePlugin.java | 2 +- .../client/plugins/grandexchange/GrandExchangePlugin.java | 2 +- 8 files changed, 18 insertions(+), 11 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/ClientSessionManager.java b/runelite-client/src/main/java/net/runelite/client/ClientSessionManager.java index 057a386b13..577a3ba272 100644 --- a/runelite-client/src/main/java/net/runelite/client/ClientSessionManager.java +++ b/runelite-client/src/main/java/net/runelite/client/ClientSessionManager.java @@ -53,7 +53,7 @@ public class ClientSessionManager { sessionClient.openSession() .subscribeOn(Schedulers.io()) - .observeOn(Schedulers.from(clientThread)) + .observeOn(Schedulers.single()) .subscribe(this::setUuid, this::error); } @@ -68,7 +68,7 @@ public class ClientSessionManager sessionClient.pingSession(sessionId) .subscribeOn(Schedulers.io()) - .observeOn(Schedulers.from(clientThread)) + .observeOn(Schedulers.single()) .doOnError(this::error) .subscribe(); } @@ -79,7 +79,7 @@ public class ClientSessionManager { sessionClient.delete(sessionId) .subscribeOn(Schedulers.io()) - .observeOn(Schedulers.from(clientThread)) + .observeOn(Schedulers.single()) .doOnError(this::error) .subscribe(); diff --git a/runelite-client/src/main/java/net/runelite/client/RuneLite.java b/runelite-client/src/main/java/net/runelite/client/RuneLite.java index 1b5a09d14e..86de7943c7 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLite.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLite.java @@ -258,7 +258,7 @@ public class RuneLite final ClientLoader clientLoader = new ClientLoader(options.valueOf(updateMode)); Completable.fromAction(clientLoader::get) - .subscribeOn(Schedulers.single()) + .subscribeOn(Schedulers.computation()) .subscribe(); Completable.fromAction(ClassPreloader::preload) diff --git a/runelite-client/src/main/java/net/runelite/client/callback/ClientThread.java b/runelite-client/src/main/java/net/runelite/client/callback/ClientThread.java index 7e9bb4106d..68378ebbea 100644 --- a/runelite-client/src/main/java/net/runelite/client/callback/ClientThread.java +++ b/runelite-client/src/main/java/net/runelite/client/callback/ClientThread.java @@ -25,6 +25,8 @@ package net.runelite.client.callback; import com.google.inject.Inject; +import io.reactivex.plugins.RxJavaPlugins; +import io.reactivex.schedulers.Schedulers; import java.util.Iterator; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Executor; @@ -45,6 +47,12 @@ public class ClientThread implements Executor @Nullable private Client client; + @Inject + private ClientThread() + { + RxJavaPlugins.setSingleSchedulerHandler(old -> Schedulers.from(this)); + } + public void invoke(Runnable r) { invoke(() -> diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraPlugin.java index 10ad4af459..39f0cf3a52 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/alchemicalhydra/HydraPlugin.java @@ -93,7 +93,7 @@ public class HydraPlugin extends Plugin private boolean inHydraInstance; private int lastAttackTick; - + @Inject private Client client; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/blackjack/BlackjackPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/blackjack/BlackjackPlugin.java index 8be40b6da6..f3faea9086 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/blackjack/BlackjackPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/blackjack/BlackjackPlugin.java @@ -185,9 +185,8 @@ public class BlackjackPlugin extends Plugin @Override public boolean matches(MenuEntry entry) { - return - Text.removeTags(entry.getTarget(), true).equalsIgnoreCase(this.getTarget()) && - entry.getOption().equalsIgnoreCase(this.getOption()); + return entry.getOption().equalsIgnoreCase(this.getOption()) && + Text.removeTags(entry.getTarget(), true).equalsIgnoreCase(this.getTarget()); } } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java index 1a0e2fb9ac..b5c326c28f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java @@ -1025,7 +1025,7 @@ public class ChatCommandsPlugin extends Plugin ItemPrice item = retrieveFromList(results, search); CLIENT.lookupItem(item.getId()) .subscribeOn(Schedulers.io()) - .observeOn(Schedulers.from(clientThread)) + .observeOn(Schedulers.single()) .subscribe( (osbresult) -> { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/examine/ExaminePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/examine/ExaminePlugin.java index a7db4ca64f..648bd8f451 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/examine/ExaminePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/examine/ExaminePlugin.java @@ -362,7 +362,7 @@ public class ExaminePlugin extends Plugin int finalQuantity = quantity; CLIENT.lookupItem(id) .subscribeOn(Schedulers.io()) - .observeOn(Schedulers.from(clientThread)) + .observeOn(Schedulers.single()) .subscribe( (osbresult) -> { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePlugin.java index de7eceef43..6fbe6cbe7f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePlugin.java @@ -605,7 +605,7 @@ public class GrandExchangePlugin extends Plugin { CLIENT.lookupItem(itemId) .subscribeOn(Schedulers.io()) - .observeOn(Schedulers.from(clientThread)) + .observeOn(Schedulers.single()) .subscribe( (osbresult) -> { From c691351825ed632d0e8f1685f59dd9de7f838c7b Mon Sep 17 00:00:00 2001 From: Lucwousin Date: Sun, 15 Dec 2019 01:23:09 +0100 Subject: [PATCH 3/5] Add Scheduler suppliers directly to EventScheduler enum --- .../runelite/client/eventbus/EventBus.java | 39 +------------------ .../client/eventbus/EventScheduler.java | 26 ++++++++----- 2 files changed, 17 insertions(+), 48 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/eventbus/EventBus.java b/runelite-client/src/main/java/net/runelite/client/eventbus/EventBus.java index d5dea07576..2bcde713dd 100644 --- a/runelite-client/src/main/java/net/runelite/client/eventbus/EventBus.java +++ b/runelite-client/src/main/java/net/runelite/client/eventbus/EventBus.java @@ -9,7 +9,6 @@ import io.reactivex.annotations.Nullable; import io.reactivex.disposables.CompositeDisposable; import io.reactivex.disposables.Disposable; import io.reactivex.functions.Consumer; -import io.reactivex.schedulers.Schedulers; import io.sentry.Sentry; import java.util.HashMap; import java.util.Map; @@ -19,7 +18,6 @@ import javax.inject.Singleton; import lombok.extern.slf4j.Slf4j; import net.runelite.api.events.Event; import net.runelite.client.RuneLiteProperties; -import net.runelite.client.callback.ClientThread; import net.runelite.client.config.OpenOSRSConfig; @Slf4j @@ -33,9 +31,6 @@ public class EventBus implements EventBusInterface @Inject private OpenOSRSConfig openOSRSConfig; - @Inject - private ClientThread clientThread; - @NonNull private Relay getSubject(Class eventClass) { @@ -60,41 +55,9 @@ public class EventBus implements EventBusInterface return observable -> until > 0 ? observable.take(until) : observable; } - private Scheduler getScheduler(EventScheduler scheduler) - { - Scheduler subscribeScheduler; - switch (scheduler) - { - case COMPUTATION: - subscribeScheduler = Schedulers.computation(); - break; - case IO: - subscribeScheduler = Schedulers.io(); - break; - case NEWTHREAD: - subscribeScheduler = Schedulers.newThread(); - break; - case SINGLE: - subscribeScheduler = Schedulers.single(); - break; - case TRAMPOLINE: - subscribeScheduler = Schedulers.trampoline(); - break; - case CLIENT: - subscribeScheduler = Schedulers.from(clientThread); - break; - case DEFAULT: - default: - subscribeScheduler = null; - break; - } - - return subscribeScheduler; - } - private ObservableTransformer applyScheduler(EventScheduler eventScheduler, boolean subscribe) { - Scheduler scheduler = getScheduler(eventScheduler); + Scheduler scheduler = eventScheduler.get(); return observable -> scheduler == null ? observable : subscribe ? observable.subscribeOn(scheduler) : observable.observeOn(scheduler); } diff --git a/runelite-client/src/main/java/net/runelite/client/eventbus/EventScheduler.java b/runelite-client/src/main/java/net/runelite/client/eventbus/EventScheduler.java index 7923cc17c8..5a0278ae50 100644 --- a/runelite-client/src/main/java/net/runelite/client/eventbus/EventScheduler.java +++ b/runelite-client/src/main/java/net/runelite/client/eventbus/EventScheduler.java @@ -1,21 +1,27 @@ package net.runelite.client.eventbus; +import io.reactivex.Scheduler; import io.reactivex.annotations.Nullable; +import io.reactivex.schedulers.Schedulers; +import java.util.function.Supplier; +import lombok.AllArgsConstructor; +@AllArgsConstructor public enum EventScheduler { - DEFAULT(null), - COMPUTATION("computation"), - IO("io"), - NEWTHREAD("newThread"), - SINGLE("single"), - TRAMPOLINE("trampoline"), - CLIENT("client"); + DEFAULT(() -> null), + COMPUTATION(Schedulers::computation), + IO(Schedulers::io), + NEWTHREAD(Schedulers::newThread), + SINGLE(Schedulers::single), + TRAMPOLINE(Schedulers::trampoline), + CLIENT(Schedulers::single); - public final String scheduler; + private Supplier scheduler; - EventScheduler(@Nullable String scheduler) + @Nullable + public Scheduler get() { - this.scheduler = scheduler; + return scheduler.get(); } } From 8724311d206e7165876bee3ed67effcdeae53fd2 Mon Sep 17 00:00:00 2001 From: Lucwousin Date: Sun, 15 Dec 2019 01:26:19 +0100 Subject: [PATCH 4/5] Use LambdaMetaFactory to generate accessors for @Subscribe annotations --- .../net/runelite/api/config/Constants.java | 105 ------------------ .../client/eventbus/AccessorGenerator.java | 85 ++++++++++++++ .../client/eventbus/Subscription.java | 20 ++++ .../net/runelite/client/plugins/Plugin.java | 66 ++++------- .../client/plugins/PluginManager.java | 11 +- 5 files changed, 136 insertions(+), 151 deletions(-) delete mode 100644 runelite-api/src/main/java/net/runelite/api/config/Constants.java create mode 100644 runelite-client/src/main/java/net/runelite/client/eventbus/AccessorGenerator.java create mode 100644 runelite-client/src/main/java/net/runelite/client/eventbus/Subscription.java diff --git a/runelite-api/src/main/java/net/runelite/api/config/Constants.java b/runelite-api/src/main/java/net/runelite/api/config/Constants.java deleted file mode 100644 index 7d385420ee..0000000000 --- a/runelite-api/src/main/java/net/runelite/api/config/Constants.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2018, Lotto - * 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 HOLDER 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.api.config; - -import java.awt.Dimension; - -/** - * A utility class containing constant values. - */ -public class Constants -{ - /** - * The original width of the game when running in fixed mode. - */ - public static final int GAME_FIXED_WIDTH = 765; - - /** - * The original height of the game when running in fixed mode. - */ - public static final int GAME_FIXED_HEIGHT = 503; - - /** - * Dimension representation of the width and height of the game in fixed mode. - */ - public static final Dimension GAME_FIXED_SIZE = new Dimension(GAME_FIXED_WIDTH, GAME_FIXED_HEIGHT); - - /** - * The aspect ratio of the game when running in fixed mode. - */ - public static final double GAME_FIXED_ASPECT_RATIO = (double) GAME_FIXED_WIDTH / (double) GAME_FIXED_HEIGHT; - - /** - * The default camera zoom value. - */ - public static final int CLIENT_DEFAULT_ZOOM = 512; - - /** - * The width and length of a chunk (8x8 tiles). - */ - public static final int CHUNK_SIZE = 8; - - /** - * The width and length of a map region (64x64 tiles). - */ - public static final int REGION_SIZE = 64; - - /** - * The width and length of the scene (13 chunks x 8 tiles). - */ - public static final int SCENE_SIZE = 104; - - /** - * The max allowed plane by the game. - *

- * This value is exclusive. The plane is set by 2 bits which restricts - * the plane value to 0-3. - */ - public static final int MAX_Z = 4; - - public static final int TILE_FLAG_BRIDGE = 2; - - /** - * The number of milliseconds in a client tick. - *

- * This is the length of a single frame when the client is running at - * the maximum framerate of 50 fps. - */ - public static final int CLIENT_TICK_LENGTH = 20; - - /** - * The number of milliseconds in a server game tick. - *

- * This is the length of a single game cycle under ideal conditions. - * All game-play actions operate within multiples of this duration. - */ - public static final int GAME_TICK_LENGTH = 600; - - /** - * Used when getting High Alchemy value - multiplied by general store price. - */ - public static final float HIGH_ALCHEMY_CONSTANT = 0.6f; -} diff --git a/runelite-client/src/main/java/net/runelite/client/eventbus/AccessorGenerator.java b/runelite-client/src/main/java/net/runelite/client/eventbus/AccessorGenerator.java new file mode 100644 index 0000000000..a87f9cd191 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/eventbus/AccessorGenerator.java @@ -0,0 +1,85 @@ +package net.runelite.client.eventbus; + +import com.google.common.collect.ImmutableSet; +import io.reactivex.functions.Consumer; +import java.lang.invoke.CallSite; +import java.lang.invoke.LambdaMetafactory; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodHandles.Lookup; +import java.lang.invoke.MethodType; +import static java.lang.invoke.MethodType.methodType; +import java.lang.reflect.Method; +import java.util.Set; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.events.Event; + +@Slf4j +public class AccessorGenerator +{ + public static Set scanSubscribes(Lookup caller, Object ref) + { + ImmutableSet.Builder builder = ImmutableSet.builder(); + + final Class refClass = ref.getClass(); + caller = getPrivateAccess(refClass, caller).in(refClass); + + for (Method method : refClass.getDeclaredMethods()) + { + Subscribe sub = method.getAnnotation(Subscribe.class); + if (sub != null) + { + final Consumer accessor; + final Class paramType = method.getParameterTypes()[0]; + + try + { + accessor = getConsumerFor(caller, ref, method); + } + catch (Throwable t) + { + log.warn("Creating consumer lambda for {} failed!", method, t); + continue; + } + + builder.add(new Subscription(paramType, accessor, sub.takeUntil(), sub.subscribe(), sub.observe())); + } + } + return builder.build(); + } + + @SuppressWarnings("unchecked") + private static Consumer getConsumerFor(Lookup caller, Object ref, Method method) throws Throwable + { + final MethodHandle methodHandle = caller.unreflect(method); + + final MethodType actualConsumer = methodHandle.type().dropParameterTypes(0, 1); + final MethodType eventsConsumer = actualConsumer.erase(); + final MethodType factoryType = methodType(Consumer.class, ref.getClass()); + + final CallSite callsite = LambdaMetafactory.metafactory( + caller, // To get past security checks + "accept", // The name of the method to implement inside the lambda type + factoryType, // Signature of the factory method + eventsConsumer, // Signature of function implementation + methodHandle, // Target method + actualConsumer // Target method signature + ); + + final MethodHandle factory = callsite.getTarget(); + return (Consumer) factory.invoke(ref); + } + + private static Lookup getPrivateAccess(Class into, Lookup from) + { + try + { + return MethodHandles.privateLookupIn(into, from); + } + catch (IllegalAccessException a) + { + log.warn("Failed to get private access in {} from {}", into, from, a); + return from; + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/eventbus/Subscription.java b/runelite-client/src/main/java/net/runelite/client/eventbus/Subscription.java new file mode 100644 index 0000000000..22acf41126 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/eventbus/Subscription.java @@ -0,0 +1,20 @@ +package net.runelite.client.eventbus; + +import io.reactivex.functions.Consumer; +import lombok.Value; + +@Value +public class Subscription +{ + private final Class type; + private final Consumer method; + private final int takeUntil; + private final EventScheduler subscribe; + private final EventScheduler observe; + + @SuppressWarnings("unchecked") + public void subscribe(EventBus eventBus, Object lifecycle) + { + eventBus.subscribe(type, lifecycle, method, takeUntil, subscribe, observe); + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/Plugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/Plugin.java index 6ff4642b8f..fddb364e9e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/Plugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/Plugin.java @@ -24,25 +24,23 @@ */ package net.runelite.client.plugins; -import com.google.common.collect.ImmutableSet; import com.google.inject.Binder; import com.google.inject.Injector; import com.google.inject.Module; -import io.reactivex.functions.Consumer; -import java.lang.reflect.Method; +import io.reactivex.Observable; +import io.reactivex.schedulers.Schedulers; +import java.lang.invoke.MethodHandles; +import java.util.Collection; import java.util.Set; import lombok.AccessLevel; import lombok.Getter; -import lombok.Value; -import net.runelite.api.events.Event; +import net.runelite.client.eventbus.AccessorGenerator; import net.runelite.client.eventbus.EventBus; -import net.runelite.client.eventbus.EventScheduler; -import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.eventbus.Subscription; public abstract class Plugin implements Module { - private final Set annotatedSubscriptions = findSubscriptions(); - private final Object annotatedSubsLock = new Object(); + private Set annotatedSubscriptions = null; @Getter(AccessLevel.PROTECTED) protected Injector injector; @@ -60,53 +58,33 @@ public abstract class Plugin implements Module { } - @SuppressWarnings("unchecked") final void addAnnotatedSubscriptions(EventBus eventBus) { - annotatedSubscriptions.forEach(sub -> eventBus.subscribe(sub.type, annotatedSubsLock, sub.method, sub.takeUntil, sub.subscribe, sub.observe)); + if (annotatedSubscriptions == null) + { + Observable.fromCallable(this::findSubscriptions) + .subscribeOn(Schedulers.computation()) + .observeOn(Schedulers.single()) + .subscribe(subs -> addSubs(eventBus, (annotatedSubscriptions = subs))); + } + else + { + addSubs(eventBus, annotatedSubscriptions); + } } final void removeAnnotatedSubscriptions(EventBus eventBus) { - eventBus.unregister(annotatedSubsLock); + eventBus.unregister(this); } private Set findSubscriptions() { - ImmutableSet.Builder builder = ImmutableSet.builder(); - - for (Method method : this.getClass().getDeclaredMethods()) - { - Subscribe annotation = method.getAnnotation(Subscribe.class); - if (annotation == null) - { - continue; - } - - assert method.getParameterCount() == 1 : "Methods annotated with @Subscribe should have only one parameter"; - - Class type = method.getParameterTypes()[0]; - - assert Event.class.isAssignableFrom(type) : "Parameters of methods annotated with @Subscribe should implement net.runelite.api.events.Event"; - assert method.getReturnType() == void.class : "Methods annotated with @Subscribe should have a void return type"; - - method.setAccessible(true); - - Subscription sub = new Subscription(type.asSubclass(Event.class), event -> method.invoke(this, event), annotation.takeUntil(), annotation.subscribe(), annotation.observe()); - - builder.add(sub); - } - - return builder.build(); + return AccessorGenerator.scanSubscribes(MethodHandles.lookup(), this); } - @Value - private static class Subscription + private void addSubs(EventBus eventBus, Collection subs) { - private final Class type; - private final Consumer method; - private final int takeUntil; - private final EventScheduler subscribe; - private final EventScheduler observe; + subs.forEach(s -> s.subscribe(eventBus, this)); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/PluginManager.java b/runelite-client/src/main/java/net/runelite/client/plugins/PluginManager.java index 0e19d0b66c..ebca9bc207 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/PluginManager.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/PluginManager.java @@ -25,6 +25,7 @@ package net.runelite.client.plugins; import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Stopwatch; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; import com.google.common.graph.Graph; @@ -218,13 +219,17 @@ public class PluginManager public void startCorePlugins() { List scannedPlugins = new ArrayList<>(plugins); - int loaded = 0; + int loaded = 0, started = 0; + final Stopwatch timer = Stopwatch.createStarted(); for (Plugin plugin : scannedPlugins) { try { - startPlugin(plugin); + if (startPlugin(plugin)) + { + ++started; + } } catch (PluginInstantiationException ex) { @@ -236,6 +241,8 @@ public class PluginManager RuneLiteSplashScreen.stage(.80, 1, "Starting plugins", loaded, scannedPlugins.size()); } + + log.debug("Started {}/{} plugins in {}", started, loaded, timer); } @SuppressWarnings("unchecked") From 0c1c461139ece02b649bccebf718142d286de2a8 Mon Sep 17 00:00:00 2001 From: Lucwousin Date: Sun, 15 Dec 2019 21:25:25 +0100 Subject: [PATCH 5/5] Fix pluginmanagertest for async subbing (and some enhancements which don't really belong in this pr but shhh about that) --- deobfuscator/deobfuscator.gradle.kts | 13 ++++++++++++- .../net/runelite/client/config/ConfigManager.java | 8 ++++++++ .../runelite/client/plugins/PluginManagerTest.java | 5 ++++- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/deobfuscator/deobfuscator.gradle.kts b/deobfuscator/deobfuscator.gradle.kts index d8e3b092db..1758a6f8d3 100644 --- a/deobfuscator/deobfuscator.gradle.kts +++ b/deobfuscator/deobfuscator.gradle.kts @@ -59,7 +59,7 @@ tasks { "rs.client" to deobjars.find { it.name.startsWith("runescape-client") }.toString().replace("\\", "/") ) - processResources { + processResources { finalizedBy("filterResources") } @@ -112,3 +112,14 @@ tasks { main = "net.runelite.deob.updater.UpdateMappings" } } + +publishing { + repositories { + mavenLocal() + } + publications { + register("asd", MavenPublication::class) { + from(components["java"]) + } + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java b/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java index a4a0765cc3..076bb9234e 100644 --- a/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java +++ b/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java @@ -449,6 +449,10 @@ public class ConfigManager { return Integer.parseInt(str); } + if (type == long.class) + { + return Long.parseLong(str); + } if (type == Color.class) { return ColorUtil.fromString(str); @@ -615,6 +619,10 @@ public class ConfigManager { return ((EnumSet) object).toArray()[0].getClass().getCanonicalName() + "{" + object.toString() + "}"; } + if (object instanceof Number) + { + return String.valueOf(object); + } return object.toString(); } diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/PluginManagerTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/PluginManagerTest.java index 6db1801b14..b52f3cbf02 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/PluginManagerTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/PluginManagerTest.java @@ -38,6 +38,7 @@ import java.applet.Applet; import java.io.File; import java.io.IOException; import java.io.PrintWriter; +import java.lang.invoke.MethodHandles; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; @@ -51,6 +52,7 @@ import net.runelite.client.RuneLite; import net.runelite.client.RuneLiteModule; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigItem; +import net.runelite.client.eventbus.AccessorGenerator; import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.Subscribe; import static org.junit.Assert.assertEquals; @@ -218,7 +220,8 @@ public class PluginManagerTest } TestPlugin plugin = new TestPlugin(); - pluginManager.startPlugin(plugin); + AccessorGenerator.scanSubscribes(MethodHandles.lookup(), plugin) + .forEach(s -> s.subscribe(eventbus, plugin)); eventbus.post(TestEvent.class, new TestEvent()); assert plugin.thisShouldBeTrue; }