diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 603358af77..2aeebfca58 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -27,7 +27,7 @@ object ProjectVersions { const val launcherVersion = "2.0.4" const val rlVersion = "1.6.7" - const val openosrsVersion = "3.0.3" + const val openosrsVersion = "3.0.4" const val rsversion = 188 const val cacheversion = 165 diff --git a/gradlew b/gradlew old mode 100755 new mode 100644 diff --git a/runelite-api/src/main/java/net/runelite/api/Client.java b/runelite-api/src/main/java/net/runelite/api/Client.java index af9197cdbb..10863f11b3 100644 --- a/runelite-api/src/main/java/net/runelite/api/Client.java +++ b/runelite-api/src/main/java/net/runelite/api/Client.java @@ -1985,4 +1985,19 @@ public interface Client extends GameShell void setMouseIdleTicks(int cycles); void setKeyboardIdleTicks(int cycles); + + /** + * Sets the result count for GE search + */ + void setGeSearchResultCount(int count); + + /** + * Sets the array of item ids for GE search + */ + void setGeSearchResultIds(short[] ids); + + /** + * Sets the starting index in the item id array for GE search + */ + void setGeSearchResultIndex(int index); } diff --git a/runelite-api/src/main/java/net/runelite/api/events/GrandExchangeSearched.java b/runelite-api/src/main/java/net/runelite/api/events/GrandExchangeSearched.java new file mode 100644 index 0000000000..b357240149 --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/events/GrandExchangeSearched.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2019, Ron Young + * 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.api.events; + +import lombok.Data; + +/** + * An event where the Grand Exchange has been searched. + */ +@Data +public class GrandExchangeSearched implements Event +{ + /** + * Whether or not the event has been consumed by a subscriber. + */ + private boolean consumed; + + /** + * Marks the event as having been consumed. + *

+ * Setting this state indicates that a plugin has set the GE + * search results and that the event will not be passed on + * for handling by vanilla client code. + */ + public void consume() + { + this.consumed = true; + } +} diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java index d16745baa9..e27eedfbe0 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java @@ -1179,6 +1179,7 @@ public class WidgetID static class SeedVault { + static final int INVENTORY_ITEM_CONTAINER = 1; static final int TITLE_CONTAINER = 2; static final int ITEM_CONTAINER = 15; static final int ITEM_TEXT = 16; diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java index 9269964aaf..97b032c07f 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java @@ -776,6 +776,7 @@ public enum WidgetInfo SEED_VAULT_TITLE_CONTAINER(WidgetID.SEED_VAULT_GROUP_ID, WidgetID.SeedVault.TITLE_CONTAINER), SEED_VAULT_ITEM_CONTAINER(WidgetID.SEED_VAULT_GROUP_ID, WidgetID.SeedVault.ITEM_CONTAINER), SEED_VAULT_ITEM_TEXT(WidgetID.SEED_VAULT_GROUP_ID, WidgetID.SeedVault.ITEM_TEXT), + SEED_VAULT_INVENTORY_ITEMS_CONTAINER(WidgetID.SEED_VAULT_INVENTORY_GROUP_ID, WidgetID.SeedVault.INVENTORY_ITEM_CONTAINER), JEWELLERY_BOX_DUEL_RING(WidgetID.JEWELLERY_BOX_GROUP_ID, WidgetID.JewelBox.DUEL_RING), JEWELLERY_BOX_GAME_NECK(WidgetID.JEWELLERY_BOX_GROUP_ID, WidgetID.JewelBox.GAME_NECK), diff --git a/runelite-client/src/main/java/net/runelite/client/Notifier.java b/runelite-client/src/main/java/net/runelite/client/Notifier.java index 40f9fba7af..01916190dd 100644 --- a/runelite-client/src/main/java/net/runelite/client/Notifier.java +++ b/runelite-client/src/main/java/net/runelite/client/Notifier.java @@ -63,6 +63,8 @@ import net.runelite.client.chat.ChatMessageManager; import net.runelite.client.chat.QueuedMessage; import net.runelite.client.config.FlashNotification; import net.runelite.client.config.RuneLiteConfig; +import net.runelite.client.eventbus.EventBus; +import net.runelite.client.events.NotificationFired; import net.runelite.client.ui.ClientUI; import net.runelite.client.util.OSType; @@ -106,6 +108,7 @@ public class Notifier private final ClientUI clientUI; private final ScheduledExecutorService executorService; private final ChatMessageManager chatMessageManager; + private final EventBus eventBus; private final Path notifyIconPath; private final boolean terminalNotifierAvailable; private Instant flashStart; @@ -117,13 +120,15 @@ public class Notifier final Client client, final RuneLiteConfig runeliteConfig, final ScheduledExecutorService executorService, - final ChatMessageManager chatMessageManager) + final ChatMessageManager chatMessageManager, + final EventBus eventBus) { this.client = client; this.clientUI = clientUI; this.runeLiteConfig = runeliteConfig; this.executorService = executorService; this.chatMessageManager = chatMessageManager; + this.eventBus = eventBus; this.notifyIconPath = RuneLite.RUNELITE_DIR.toPath().resolve("icon.png"); // First check if we are running in launcher @@ -139,6 +144,8 @@ public class Notifier public void notify(String message, TrayIcon.MessageType type) { + eventBus.post(NotificationFired.class, new NotificationFired(message, type)); + if (!runeLiteConfig.sendNotificationsWhenFocused() && clientUI.isFocused()) { return; diff --git a/runelite-client/src/main/java/net/runelite/client/events/NotificationFired.java b/runelite-client/src/main/java/net/runelite/client/events/NotificationFired.java new file mode 100644 index 0000000000..7508416562 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/events/NotificationFired.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2020, Trevor + * 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.events; + +import java.awt.TrayIcon; +import lombok.Value; +import net.runelite.api.events.Event; + +@Value +public class NotificationFired implements Event +{ + final String message; + final TrayIcon.MessageType type; +} diff --git a/runelite-client/src/main/java/net/runelite/client/game/AgilityShortcut.java b/runelite-client/src/main/java/net/runelite/client/game/AgilityShortcut.java index 8771076e1c..2b49cd6c9b 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/AgilityShortcut.java +++ b/runelite-client/src/main/java/net/runelite/client/game/AgilityShortcut.java @@ -175,7 +175,7 @@ public enum AgilityShortcut ELVEN_OVERPASS_MEDIUM_CLIFF(68, "Rocks", new WorldPoint(2337, 3288, 0), ROCKS_16514, ROCKS_16515), ELVEN_OVERPASS_MEDIUM_CLIFF_PRIFDDINAS(68, "Rocks", new WorldPoint(3361, 6040, 0), ROCKS_16514, ROCKS_16515), WEISS_OBSTACLES(68, "Shortcut", null, LITTLE_BOULDER, ROCKSLIDE_33184, ROCKSLIDE_33185, NULL_33327, NULL_33328, LEDGE_33190, ROCKSLIDE_33191, FALLEN_TREE_33192), - ARCEUUS_ESSENSE_NORTH(69, "Rock Climb", new WorldPoint(1761, 3873, 0), ROCKS_34741), + ARCEUUS_ESSENSE_NORTH(69, "Rock Climb", new WorldPoint(1759, 3873, 0), ROCKS_34741), TAVERLEY_DUNGEON_PIPE_BLUE_DRAGON(70, "Pipe Squeeze", new WorldPoint(2886, 9798, 0), OBSTACLE_PIPE_16509), TAVERLEY_DUNGEON_ROCKS_NORTH(70, "Rocks", new WorldPoint(2887, 9823, 0), ROCKS, ROCKS_14106), TAVERLEY_DUNGEON_ROCKS_SOUTH(70, "Rocks", new WorldPoint(2887, 9631, 0), ROCKS, ROCKS_14106), diff --git a/runelite-client/src/main/java/net/runelite/client/game/ItemVariationMapping.java b/runelite-client/src/main/java/net/runelite/client/game/ItemVariationMapping.java index 7c6a6e143e..0e0b4c85f7 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/ItemVariationMapping.java +++ b/runelite-client/src/main/java/net/runelite/client/game/ItemVariationMapping.java @@ -26,10 +26,14 @@ package net.runelite.client.game; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.Multimap; import com.google.gson.stream.JsonReader; import java.io.IOException; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.Collections; import java.util.Map; import lombok.extern.slf4j.Slf4j; @@ -40,6 +44,7 @@ import lombok.extern.slf4j.Slf4j; public class ItemVariationMapping { private static Map MAPPINGS; + private static Multimap INVERTED_MAPPINGS; /** * Get base item id for provided variation item id. @@ -52,11 +57,23 @@ public class ItemVariationMapping return MAPPINGS.getOrDefault(itemId, itemId); } + /** + * Get item ids for provided variation item id. + * + * @param itemId the item id + * @return the item ids + */ + public static Collection getVariations(int itemId) + { + return INVERTED_MAPPINGS.asMap().getOrDefault(itemId, Collections.singletonList(itemId)); + } + static void load() throws IOException { try (JsonReader reader = new JsonReader(new InputStreamReader(ItemVariationMapping.class.getResourceAsStream("/item_variations.min.json"), StandardCharsets.UTF_8))) { ImmutableMap.Builder builder = ImmutableMap.builderWithExpectedSize(5039); + ImmutableMultimap.Builder invertedBuilder = new ImmutableMultimap.Builder<>(); reader.beginObject(); while (reader.hasNext()) @@ -68,16 +85,20 @@ public class ItemVariationMapping int base = reader.nextInt(); while (reader.hasNext()) { - builder.put( - reader.nextInt(), - base - ); + final int id = reader.nextInt(); + + builder.put(id, base); + invertedBuilder.put(base, id); } + invertedBuilder.put(base, base); + reader.endArray(); } reader.endObject(); + + INVERTED_MAPPINGS = invertedBuilder.build(); MAPPINGS = builder.build(); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/ExternalPluginManager.java b/runelite-client/src/main/java/net/runelite/client/plugins/ExternalPluginManager.java index 421c408284..ecee004d6c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/ExternalPluginManager.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/ExternalPluginManager.java @@ -382,9 +382,13 @@ class ExternalPluginManager Plugin plugin; try { - plugin = clazz.newInstance(); + plugin = clazz.getDeclaredConstructor().newInstance(); } - catch (InstantiationException | IllegalAccessException ex) + catch (ThreadDeath e) + { + throw e; + } + catch (Throwable ex) { throw new PluginInstantiationException(ex); } 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 048731c74f..4fd7ee18ef 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 @@ -164,26 +164,39 @@ public class PluginManager public Config getPluginConfigProxy(Plugin plugin) { - final Injector injector = plugin.getInjector(); - - for (Key key : injector.getAllBindings().keySet()) + try { - Class type = key.getTypeLiteral().getRawType(); - if (Config.class.isAssignableFrom(type)) + final Injector injector = plugin.getInjector(); + + for (Key key : injector.getAllBindings().keySet()) { - return (Config) injector.getInstance(key); + Class type = key.getTypeLiteral().getRawType(); + if (Config.class.isAssignableFrom(type)) + { + return (Config) injector.getInstance(key); + } } } - + catch (ThreadDeath e) + { + throw e; + } + catch (Throwable e) + { + log.warn("Unable to get plugin config", e); + } return null; } - private List getPluginConfigProxies() + public List getPluginConfigProxies(Collection plugins) { List injectors = new ArrayList<>(); - injectors.add(RuneLite.getInjector()); - getPlugins().forEach(pl -> injectors.add(pl.getInjector())); - + if (plugins == null) + { + injectors.add(RuneLite.getInjector()); + plugins = getPlugins(); + } + plugins.forEach(pl -> injectors.add(pl.getInjector())); List list = new ArrayList<>(); for (Injector injector : injectors) { @@ -197,15 +210,25 @@ public class PluginManager } } } - return list; } public void loadDefaultPluginConfiguration() { - for (Object config : getPluginConfigProxies()) + try { - configManager.setDefaultConfiguration(config, false); + for (Object config : getPluginConfigProxies(plugins)) + { + configManager.setDefaultConfiguration(config, false); + } + } + catch (ThreadDeath e) + { + throw e; + } + catch (Throwable ex) + { + log.warn("Unable to reset plugin configuration", ex); } } @@ -409,7 +432,11 @@ public class PluginManager schedule(plugin); eventBus.post(PluginChanged.class, new PluginChanged(plugin, true)); } - catch (Exception ex) + catch (ThreadDeath e) + { + throw e; + } + catch (Throwable ex) { throw new PluginInstantiationException(ex); } @@ -484,9 +511,13 @@ public class PluginManager Plugin plugin; try { - plugin = clazz.newInstance(); + plugin = clazz.getDeclaredConstructor().newInstance(); } - catch (InstantiationException | IllegalAccessException ex) + catch (ThreadDeath e) + { + throw e; + } + catch (Throwable ex) { throw new PluginInstantiationException(ex); } diff --git a/runelite-client/src/main/java/net/runelite/client/util/RSTimeUnit.java b/runelite-client/src/main/java/net/runelite/client/util/RSTimeUnit.java new file mode 100644 index 0000000000..bbf5f832a3 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/util/RSTimeUnit.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2020, Jordan Atwood + * 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.time.Duration; +import java.time.temporal.Temporal; +import java.time.temporal.TemporalUnit; +import lombok.Getter; +import net.runelite.api.Constants; + +@Getter +public enum RSTimeUnit implements TemporalUnit +{ + CLIENT_TICKS("Client tick", Duration.ofMillis(Constants.CLIENT_TICK_LENGTH)), + GAME_TICKS("Game tick", Duration.ofMillis(Constants.GAME_TICK_LENGTH)), + ; + + private final String name; + private final Duration duration; + + RSTimeUnit(String name, Duration estimatedDuration) + { + this.name = name; + duration = estimatedDuration; + } + + @Override + public boolean isDurationEstimated() + { + return false; + } + + @Override + public boolean isDateBased() + { + return false; + } + + @Override + public boolean isTimeBased() + { + return true; + } + + @Override + public boolean isSupportedBy(Temporal temporal) + { + return temporal.isSupported(this); + } + + @Override + public R addTo(R temporal, long amount) + { + return (R) temporal.plus(amount, this); + } + + @Override + public long between(Temporal temporal1Inclusive, Temporal temporal2Exclusive) + { + return temporal1Inclusive.until(temporal2Exclusive, this); + } + + @Override + public String toString() + { + return name + " (" + duration.toMillis() + "ms)"; + } +} diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java index a079fbaa53..0a93258803 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java @@ -76,6 +76,7 @@ import net.runelite.api.events.ClientTick; import net.runelite.api.events.DraggingWidgetChanged; import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GrandExchangeOfferChanged; +import net.runelite.api.events.GrandExchangeSearched; import net.runelite.api.events.Menu; import net.runelite.api.events.MenuEntryAdded; import net.runelite.api.events.MenuOpened; @@ -1172,6 +1173,23 @@ public abstract class RSClientMixin implements RSClient } } + @Copy("findItemDefinitions") + public static void rs$findItemDefinitions(String var0, boolean var1) + { + throw new RuntimeException(); + } + + @Replace("findItemDefinitions") + public static void rl$findItemDefinitions(String var0, boolean var1) + { + GrandExchangeSearched event = new GrandExchangeSearched(); + client.getCallbacks().post(GrandExchangeSearched.class, event); + if (!event.isConsumed()) + { + rs$findItemDefinitions(var0, var1); + } + } + @Inject @FieldHook("grandExchangeOffers") public static void onGrandExchangeOffersChanged(int idx) diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java b/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java index 946e52b682..8727dfface 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java @@ -464,6 +464,18 @@ public interface RSClient extends RSGameShell, Client @Import("grandExchangeOffers") RSGrandExchangeOffer[] getGrandExchangeOffers(); + @Import("foundItemIdCount") + @Override + void setGeSearchResultCount(int count); + + @Import("foundItemIds") + @Override + void setGeSearchResultIds(short[] ids); + + @Import("foundItemIndex") + @Override + void setGeSearchResultIndex(int index); + @Import("isMenuOpen") @Override boolean isMenuOpen();