From 931cb7adf26a3c4166cd3d49aa2c713421a0d222 Mon Sep 17 00:00:00 2001 From: rfick Date: Thu, 19 Mar 2020 11:44:56 -0700 Subject: [PATCH 01/13] kourendlibrary: Indicate books not in inventory This commit changes the Kourend library panel to show a different color for books which are not the target based on whether they are in the player's inventory or not. Previously, the target book would be shown in green and all other books would be listed in white. Now, non-target books in the player's inventory are shown in white and those the player does not have are shown in orange. Co-authored-by: Jordan Atwood --- .../client/plugins/kourendlibrary/BookPanel.java | 10 +++++++++- .../plugins/kourendlibrary/KourendLibraryPanel.java | 10 ++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/BookPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/BookPanel.java index a82cee5814..6842b34e7d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/BookPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/BookPanel.java @@ -77,6 +77,14 @@ class BookPanel extends JPanel void setIsTarget(boolean target) { - location.setForeground(target ? Color.GREEN : Color.WHITE); + location.setForeground(target ? Color.GREEN : Color.ORANGE); + } + + void setIsHeld(boolean held) + { + if (held) + { + location.setForeground(Color.WHITE); + } } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryPanel.java index 8480328c47..bf5cffb417 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryPanel.java @@ -52,6 +52,7 @@ class KourendLibraryPanel extends PluginPanel private static final ImageIcon RESET_ICON; private static final ImageIcon RESET_HOVER_ICON; + private final KourendLibraryPlugin plugin; private final KourendLibraryConfig config; private final Library library; @@ -65,10 +66,11 @@ class KourendLibraryPanel extends PluginPanel } @Inject - KourendLibraryPanel(KourendLibraryConfig config, Library library) + KourendLibraryPanel(KourendLibraryPlugin plugin, KourendLibraryConfig config, Library library) { super(); + this.plugin = plugin; this.config = config; this.library = library; } @@ -117,7 +119,11 @@ class KourendLibraryPanel extends PluginPanel Book customerBook = library.getCustomerBook(); for (Map.Entry b : bookPanels.entrySet()) { - b.getValue().setIsTarget(customerBook == b.getKey()); + final Book book = b.getKey(); + final BookPanel panel = b.getValue(); + + panel.setIsTarget(customerBook == book); + panel.setIsHeld(plugin.doesPlayerContainBook(book)); } HashMap> bookLocations = new HashMap<>(); From 4369d8baa8edcd5526528a73f8c1fa3a04d95de4 Mon Sep 17 00:00:00 2001 From: rfick Date: Thu, 19 Mar 2020 11:49:14 -0700 Subject: [PATCH 02/13] kourendlibrary: Show a hint arrow above target book This commit adds a configuration to the Kourend library plugin to display a hint arrow above the target bookcase. (when it is known) Co-authored-by: Jordan Atwood --- .../kourendlibrary/KourendLibraryConfig.java | 10 ++++ .../kourendlibrary/KourendLibraryPlugin.java | 60 +++++++++++++++++-- 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryConfig.java index 2abb7c2255..6c2bd860d3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryConfig.java @@ -72,4 +72,14 @@ public interface KourendLibraryConfig extends Config { return true; } + + @ConfigItem( + keyName = "showTargetHintArrow", + name = "Show target book arrow", + description = "Show a hint arrow pointing to the target bookcase" + ) + default boolean showTargetHintArrow() + { + return true; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryPlugin.java index a6221462c3..6b81bd9f18 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryPlugin.java @@ -199,6 +199,15 @@ public class KourendLibraryPlugin extends Plugin } }); } + else if (ev.getKey().equals("showTargetHintArrow")) + { + if (client.getLocalPlayer() == null || client.getLocalPlayer().getWorldLocation().getRegionID() != REGION) + { + return; + } + + updateBookcaseHintArrow(); + } } @Subscribe @@ -227,7 +236,7 @@ public class KourendLibraryPlugin extends Plugin if (event.getMessage().equals("You don't find anything useful here.")) { library.mark(lastBookcaseAnimatedOn, null); - panel.update(); + updateBooksPanel(); lastBookcaseAnimatedOn = null; } } @@ -277,7 +286,7 @@ public class KourendLibraryPlugin extends Plugin if (book != null) { library.mark(lastBookcaseAnimatedOn, book); - panel.update(); + updateBooksPanel(); lastBookcaseAnimatedOn = null; } } @@ -302,12 +311,12 @@ public class KourendLibraryPlugin extends Plugin } library.setCustomer(npcHead.getModelId(), book); - panel.update(); + updateBooksPanel(); } else if (text.contains("You can have this other book") || text.contains("please accept a token of my thanks.") || text.contains("Thanks, I'll get on with reading it.")) { library.setCustomer(-1, null); - panel.update(); + updateBooksPanel(); } } } @@ -361,6 +370,49 @@ public class KourendLibraryPlugin extends Plugin } } + private void updateBooksPanel() + { + panel.update(); + updateBookcaseHintArrow(); + } + + private void updateBookcaseHintArrow() + { + final Book customerBook = library.getCustomerBook(); + final SolvedState state = library.getState(); + + // Clear the hint arrow if the player has no book requested of them + // or if the player is already holding the correct book + // or if this plugin is configured not to show the target book hint arrow + if (customerBook == null || doesPlayerContainBook(customerBook) || !config.showTargetHintArrow()) + { + client.clearHintArrow(); + } + else if (state == SolvedState.COMPLETE && client.getHintArrowPoint() == null) + { + // Show a hint arrow pointing toward the target book if all book locations are known + // and a hint arrow is not already being displayed + for (Bookcase bookcase : library.getBookcases()) + { + final Set books = bookcase.getPossibleBooks(); + + if (!books.isEmpty()) + { + final Book book = books.iterator().next(); + + // Each bookcase in a complete solved state will contain only one book. If that book is the book + // the customer wants, mark the bookcase which contains it with a hint arrow. + if (book == customerBook) + { + WorldPoint correctLocation = bookcase.getLocation(); + client.setHintArrow(correctLocation); + break; + } + } + } + } + } + static boolean isLibraryCustomer(int npcId) { return npcId == NpcID.VILLIA || npcId == NpcID.PROFESSOR_GRACKLEBONE || npcId == NpcID.SAM_7049; From 29901e5b1318199777d8b970a8f2fb984dfd9226 Mon Sep 17 00:00:00 2001 From: jostn Date: Fri, 3 Apr 2020 15:10:03 +0200 Subject: [PATCH 03/13] HotColdLocation: Center Rimmington mine dig location --- .../plugins/cluescrolls/clues/hotcold/HotColdLocation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/hotcold/HotColdLocation.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/hotcold/HotColdLocation.java index 32cb988b8c..83de07ab43 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/hotcold/HotColdLocation.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/hotcold/HotColdLocation.java @@ -58,7 +58,7 @@ public enum HotColdLocation ASGARNIA_COW(new WorldPoint(3031, 3304, 0), ASGARNIA, "In the cow pen north of Sarah's Farming Shop."), ASGARNIA_PARTY_ROOM(new WorldPoint(3030, 3364, 0), ASGARNIA, "Outside the Falador Party Room."), ASGARNIA_CRAFT_GUILD(new WorldPoint(2917, 3295, 0), ASGARNIA, "Outside the Crafting Guild cow pen."), - ASGARNIA_RIMMINGTON(new WorldPoint(2978, 3241, 0), ASGARNIA, "In the centre of the Rimmington mine."), + ASGARNIA_RIMMINGTON(new WorldPoint(2976, 3239, 0), ASGARNIA, "In the centre of the Rimmington mine."), ASGARNIA_MUDSKIPPER(new WorldPoint(2987, 3110, 0), ASGARNIA, "Mudskipper Point, near the starfish in the south-west corner."), ASGARNIA_TROLL(new WorldPoint(2910, 3616, 0), ASGARNIA, "The Troll arena, where the player fights Dad during the Troll Stronghold quest. Bring climbing boots if travelling from Burthorpe."), DESERT_GENIE(new WorldPoint(3364, 2910, 0), DESERT, "West of Nardah genie cave."), From c703a35f15fa25f99437953b7e76d28e44105863 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 3 Apr 2020 12:48:34 -0400 Subject: [PATCH 04/13] party plugin: play sound effects on client thread --- .../java/net/runelite/client/plugins/party/PartyPlugin.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/party/PartyPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/party/PartyPlugin.java index b70057e97b..1f94f976ee 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/party/PartyPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/party/PartyPlugin.java @@ -52,6 +52,7 @@ import net.runelite.api.events.CommandExecuted; import net.runelite.api.events.FocusChanged; import net.runelite.api.events.GameTick; import net.runelite.api.events.MenuOptionClicked; +import net.runelite.client.callback.ClientThread; import net.runelite.client.chat.ChatColorType; import net.runelite.client.chat.ChatMessageBuilder; import net.runelite.client.chat.ChatMessageManager; @@ -120,6 +121,9 @@ public class PartyPlugin extends Plugin implements KeyListener @Inject private ChatMessageManager chatMessageManager; + @Inject + private ClientThread clientThread; + @Inject @Named("developerMode") boolean developerMode; @@ -260,7 +264,7 @@ public class PartyPlugin extends Plugin implements KeyListener return; } - client.playSoundEffect(SoundEffectID.SMITH_ANVIL_TINK); + clientThread.invoke(() -> client.playSoundEffect(SoundEffectID.SMITH_ANVIL_TINK)); } } From 4a1dbf4e2d59e6a82f29d73c97f42410aa6c74f2 Mon Sep 17 00:00:00 2001 From: Sean Dewar <6256228+seandewar@users.noreply.github.com> Date: Tue, 24 Mar 2020 16:07:27 +0000 Subject: [PATCH 05/13] music: slider volume percentage tooltips --- .../client/plugins/music/MusicPlugin.java | 61 ++++++++++++++----- 1 file changed, 47 insertions(+), 14 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicPlugin.java index 1bc8d0fa2d..f62f3e9f61 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicPlugin.java @@ -1,6 +1,7 @@ /* * Copyright (c) 2019, Anthony Chen * Copyright (c) 2019, Adam + * Copyright (c) 2020, Sean Dewar * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -50,10 +51,10 @@ import net.runelite.api.SpriteID; import net.runelite.api.VarClientInt; import net.runelite.api.VarPlayer; import net.runelite.api.events.AreaSoundEffectPlayed; -import net.runelite.api.events.SoundEffectPlayed; -import net.runelite.client.events.ConfigChanged; +import net.runelite.api.events.BeforeRender; import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.ScriptCallbackEvent; +import net.runelite.api.events.SoundEffectPlayed; import net.runelite.api.events.VarClientIntChanged; import net.runelite.api.events.VolumeChanged; import net.runelite.api.events.WidgetLoaded; @@ -67,10 +68,13 @@ import net.runelite.api.widgets.WidgetType; import net.runelite.client.callback.ClientThread; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.events.ConfigChanged; import net.runelite.client.game.chatbox.ChatboxPanelManager; import net.runelite.client.game.chatbox.ChatboxTextInput; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.ui.overlay.tooltip.Tooltip; +import net.runelite.client.ui.overlay.tooltip.TooltipManager; @PluginDescriptor( name = "Music", @@ -125,6 +129,9 @@ public class MusicPlugin extends Plugin @Inject private ChatboxPanelManager chatboxPanelManager; + @Inject + private TooltipManager tooltipManager; + private ChatboxTextInput searchInput; private Widget musicSearchButton; @@ -134,6 +141,8 @@ public class MusicPlugin extends Plugin private MusicState currentMusicFilter = MusicState.ALL; + private MusicSlider hoveredSlider; + @Override protected void startUp() { @@ -155,7 +164,7 @@ public class MusicPlugin extends Plugin } tracks = null; - + hoveredSlider = null; clientThread.invoke(this::teardownMusicOptions); } @@ -407,10 +416,11 @@ public class MusicPlugin extends Plugin @Getter private enum MusicSlider { - MUSIC(WidgetInfo.OPTIONS_MUSIC_SLIDER, VarPlayer.MUSIC_VOLUME, MusicConfig::getMusicVolume, MusicConfig::setMusicVolume, 255), - AREA(WidgetInfo.OPTIONS_AREA_SOUND_SLIDER, VarPlayer.AREA_EFFECT_VOLUME, MusicConfig::getAreaSoundEffectVolume, MusicConfig::setAreaSoundEffectVolume, 127), - EFFECT(WidgetInfo.OPTIONS_SOUND_EFFECT_SLIDER, VarPlayer.SOUND_EFFECT_VOLUME, MusicConfig::getSoundEffectVolume, MusicConfig::setSoundEffectVolume, 127); + MUSIC("Music", WidgetInfo.OPTIONS_MUSIC_SLIDER, VarPlayer.MUSIC_VOLUME, MusicConfig::getMusicVolume, MusicConfig::setMusicVolume, 255), + AREA("Area Sounds", WidgetInfo.OPTIONS_AREA_SOUND_SLIDER, VarPlayer.AREA_EFFECT_VOLUME, MusicConfig::getAreaSoundEffectVolume, MusicConfig::setAreaSoundEffectVolume, 127), + EFFECT("Sound Effects", WidgetInfo.OPTIONS_SOUND_EFFECT_SLIDER, VarPlayer.SOUND_EFFECT_VOLUME, MusicConfig::getSoundEffectVolume, MusicConfig::setSoundEffectVolume, 127); + private final String name; private final WidgetInfo widgetID; private final VarPlayer var; private final ToIntFunction getter; @@ -434,6 +444,18 @@ public class MusicPlugin extends Plugin { return getTrack().getWidth() - (PADDING * 2) - handle.getWidth(); } + + private int getValue(final MusicConfig config, final Client client) + { + int value = getter.applyAsInt(config) - 1; + if (value <= -1) + { + // Use the vanilla value + value = ((4 - client.getVar(var)) * max) / 4; + } + + return value; + } } private void teardownMusicOptions() @@ -542,6 +564,9 @@ public class MusicPlugin extends Plugin handle.setOriginalHeight(16); handle.setClickMask(WidgetConfig.DRAG); + handle.setOnMouseRepeatListener((JavaScriptCallback) ev -> hoveredSlider = slider); + handle.setHasListener(true); + JavaScriptCallback move = ev -> { int newVal = ((ev.getMouseX() - MusicSlider.PADDING - (slider.getHandle().getWidth() / 2)) * slider.getMax()) @@ -568,20 +593,28 @@ public class MusicPlugin extends Plugin client.runScript(ScriptID.OPTIONS_ALLSOUNDS, -1, init[2], init[3], init[4], init[5], init[6]); } - int value = slider.getGetter().applyAsInt(musicConfig) - 1; - if (value <= -1) - { - // Use the vanilla value - value = ((4 - client.getVar(slider.getVar())) * slider.getMax()) / 4; - } - - int newX = ((value * slider.getWidth()) / slider.getMax()) + slider.getX(); + final int value = slider.getValue(musicConfig, client); + final int newX = ((value * slider.getWidth()) / slider.getMax()) + slider.getX(); slider.getHandle().setOriginalX(newX); slider.getHandle().setOriginalY(slider.getTrack().getOriginalY()); slider.getHandle().revalidate(); } } + @Subscribe + public void onBeforeRender(final BeforeRender event) + { + // Tooltips are auto-cleared before each render frame; create a new updated one for this frame + if (hoveredSlider != null) + { + final int value = hoveredSlider.getValue(musicConfig, client); + final int percent = (int) Math.round((value * 100.0 / hoveredSlider.getMax())); + + tooltipManager.add(new Tooltip(hoveredSlider.getName() + ": " + percent + "%")); + hoveredSlider = null; + } + } + @Subscribe public void onScriptCallbackEvent(ScriptCallbackEvent ev) { From 07d414d41d9acf98a1d1f6dba12ec894a93312bc Mon Sep 17 00:00:00 2001 From: Sean Dewar <6256228+seandewar@users.noreply.github.com> Date: Tue, 24 Mar 2020 19:03:53 +0000 Subject: [PATCH 06/13] camera: zoom slider tooltip & zoom constants This commit also adds constants for: VarClientInt.CAMERA_ZOOM_FIXED_VIEWPORT = 73 VarClientInt.CAMERA_ZOOM_RESIZABLE_VIEWPORT = 74 WidgetID.Options.CAMERA_ZOOM_SLIDER_HANDLE = 15 WidgetInfo.OPTIONS_CAMERA_ZOOM_SLIDER_HANDLE --- .../main/java/net/runelite/api/ScriptID.java | 4 +- .../java/net/runelite/api/VarClientInt.java | 6 ++ .../net/runelite/api/widgets/WidgetID.java | 1 + .../net/runelite/api/widgets/WidgetInfo.java | 1 + .../client/plugins/camera/CameraOverlay.java | 74 +++++++++++++++++++ .../client/plugins/camera/CameraPlugin.java | 14 +++- 6 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/camera/CameraOverlay.java diff --git a/runelite-api/src/main/java/net/runelite/api/ScriptID.java b/runelite-api/src/main/java/net/runelite/api/ScriptID.java index 1b6e93e33c..73f6fabb29 100644 --- a/runelite-api/src/main/java/net/runelite/api/ScriptID.java +++ b/runelite-api/src/main/java/net/runelite/api/ScriptID.java @@ -162,8 +162,8 @@ public final class ScriptID * * Updates the VarClientInts (73, 74) to this same value *
    - *
  • int Reset zoom position
  • - *
  • int Reset zoom position
  • + *
  • int Reset zoom position for fixed viewport mode
  • + *
  • int Reset zoom position for resizable viewport mode
  • *
*/ @ScriptArguments(integer = 2) diff --git a/runelite-api/src/main/java/net/runelite/api/VarClientInt.java b/runelite-api/src/main/java/net/runelite/api/VarClientInt.java index db67c62966..6efd010c6e 100644 --- a/runelite-api/src/main/java/net/runelite/api/VarClientInt.java +++ b/runelite-api/src/main/java/net/runelite/api/VarClientInt.java @@ -52,6 +52,12 @@ public enum VarClientInt */ INPUT_TYPE(5), + /** + * The game sets this to the same value as {@link #CAMERA_ZOOM_RESIZABLE_VIEWPORT} + */ + CAMERA_ZOOM_FIXED_VIEWPORT(73), + CAMERA_ZOOM_RESIZABLE_VIEWPORT(74), + MEMBERSHIP_STATUS(103), INVENTORY_TAB(171), 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 19a5945f67..5287e418a0 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 @@ -870,6 +870,7 @@ public class WidgetID static class Options { + static final int CAMERA_ZOOM_SLIDER_HANDLE = 15; static final int MUSIC_SLIDER = 37; static final int SOUND_EFFECT_SLIDER = 43; static final int AREA_SOUND_SLIDER = 49; 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 81eb08dd49..a7c3bbc94e 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 @@ -525,6 +525,7 @@ public enum WidgetInfo 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), + OPTIONS_CAMERA_ZOOM_SLIDER_HANDLE(WidgetID.OPTIONS_GROUP_ID, WidgetID.Options.CAMERA_ZOOM_SLIDER_HANDLE), OPTIONS_MUSIC_SLIDER(WidgetID.OPTIONS_GROUP_ID, WidgetID.Options.MUSIC_SLIDER), OPTIONS_SOUND_EFFECT_SLIDER(WidgetID.OPTIONS_GROUP_ID, WidgetID.Options.SOUND_EFFECT_SLIDER), OPTIONS_AREA_SOUND_SLIDER(WidgetID.OPTIONS_GROUP_ID, WidgetID.Options.AREA_SOUND_SLIDER), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/camera/CameraOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/camera/CameraOverlay.java new file mode 100644 index 0000000000..f379d60cb2 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/camera/CameraOverlay.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2020, Sean Dewar + * 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.plugins.camera; + +import java.awt.Dimension; +import java.awt.Graphics2D; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.Point; +import net.runelite.api.VarClientInt; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.tooltip.Tooltip; +import net.runelite.client.ui.overlay.tooltip.TooltipManager; + +class CameraOverlay extends Overlay +{ + private final CameraConfig config; + private final Client client; + private final TooltipManager tooltipManager; + + @Inject + private CameraOverlay(final CameraConfig config, final Client client, final TooltipManager tooltipManager) + { + this.config = config; + this.client = client; + this.tooltipManager = tooltipManager; + setPosition(OverlayPosition.DYNAMIC); + setLayer(OverlayLayer.ABOVE_WIDGETS); + } + + @Override + public Dimension render(final Graphics2D graphics) + { + final Widget slider = client.getWidget(WidgetInfo.OPTIONS_CAMERA_ZOOM_SLIDER_HANDLE); + final Point mousePos = client.getMouseCanvasPosition(); + + if (slider == null || slider.isHidden() || !slider.getBounds().contains(mousePos.getX(), mousePos.getY())) + { + return null; + } + + final int value = client.getVar(VarClientInt.CAMERA_ZOOM_RESIZABLE_VIEWPORT); + final int max = config.innerLimit() ? config.INNER_ZOOM_LIMIT : CameraPlugin.DEFAULT_INNER_ZOOM_LIMIT; + + tooltipManager.add(new Tooltip("Camera Zoom: " + value + " / " + max)); + return null; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/camera/CameraPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/camera/CameraPlugin.java index cbdba9f4b4..0b2c0c600f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/camera/CameraPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/camera/CameraPlugin.java @@ -52,6 +52,7 @@ import net.runelite.client.input.MouseListener; import net.runelite.client.input.MouseManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.ui.overlay.OverlayManager; @PluginDescriptor( name = "Camera", @@ -62,6 +63,9 @@ import net.runelite.client.plugins.PluginDescriptor; public class CameraPlugin extends Plugin implements KeyListener, MouseListener { private static final int DEFAULT_ZOOM_INCREMENT = 25; + private static final int DEFAULT_OUTER_ZOOM_LIMIT = 128; + static final int DEFAULT_INNER_ZOOM_LIMIT = 896; + private static final String LOOK_NORTH = "Look North"; private static final String LOOK_SOUTH = "Look South"; private static final String LOOK_EAST = "Look East"; @@ -91,6 +95,12 @@ public class CameraPlugin extends Plugin implements KeyListener, MouseListener @Inject private MouseManager mouseManager; + @Inject + private OverlayManager overlayManager; + + @Inject + private CameraOverlay cameraOverlay; + @Provides CameraConfig getConfig(ConfigManager configManager) { @@ -106,11 +116,13 @@ public class CameraPlugin extends Plugin implements KeyListener, MouseListener client.setCameraPitchRelaxerEnabled(config.relaxCameraPitch()); keyManager.registerKeyListener(this); mouseManager.registerMouseListener(this); + overlayManager.add(cameraOverlay); } @Override protected void shutDown() { + overlayManager.remove(cameraOverlay); client.setCameraPitchRelaxerEnabled(false); keyManager.unregisterKeyListener(this); mouseManager.unregisterMouseListener(this); @@ -177,7 +189,7 @@ public class CameraPlugin extends Plugin implements KeyListener, MouseListener if ("outerZoomLimit".equals(event.getEventName())) { int outerLimit = Ints.constrainToRange(config.outerLimit(), CameraConfig.OUTER_LIMIT_MIN, CameraConfig.OUTER_LIMIT_MAX); - int outerZoomLimit = 128 - outerLimit; + int outerZoomLimit = DEFAULT_OUTER_ZOOM_LIMIT - outerLimit; intStack[intStackSize - 1] = outerZoomLimit; return; } From f2d7515ff3a93f17d1543a93a52182420a69e1f6 Mon Sep 17 00:00:00 2001 From: Unknown <4everpluto@gmail.com> Date: Thu, 2 Apr 2020 14:46:39 -0400 Subject: [PATCH 07/13] Update Plugin Hub risk label As discussed in issue #10997 - using dekvall's label suggestion --- .../net/runelite/client/plugins/config/PluginHubPanel.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginHubPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginHubPanel.java index 269cfe574f..934288342a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginHubPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginHubPanel.java @@ -386,7 +386,9 @@ class PluginHubPanel extends PluginPanel } }); - JLabel externalPluginWarning = new JLabel("External plugins are not supported by the RuneLite Developers. " + + JLabel externalPluginWarning = new JLabel("External plugins are verified to not be " + + "malicious or rule-breaking, but are not " + + "maintained by the RuneLite developers. " + "They may cause bugs or instability."); externalPluginWarning.setBackground(new Color(0xFFBB33)); externalPluginWarning.setForeground(Color.BLACK); From 417b42b0bf89644bd6a099c0b174bcad173d20ca Mon Sep 17 00:00:00 2001 From: Sean Dewar <6256228+seandewar@users.noreply.github.com> Date: Mon, 6 Apr 2020 16:00:22 +0100 Subject: [PATCH 08/13] music: revalidate slider handle on creation --- .../main/java/net/runelite/client/plugins/music/MusicPlugin.java | 1 + 1 file changed, 1 insertion(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicPlugin.java index f62f3e9f61..8205c3f3a3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/music/MusicPlugin.java @@ -563,6 +563,7 @@ public class MusicPlugin extends Plugin handle.setOriginalWidth(16); handle.setOriginalHeight(16); handle.setClickMask(WidgetConfig.DRAG); + handle.revalidate(); handle.setOnMouseRepeatListener((JavaScriptCallback) ev -> hoveredSlider = slider); handle.setHasListener(true); From 6abc433141003c16cf6be9d41a6f57b6e603008b Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 6 Apr 2020 12:32:52 -0400 Subject: [PATCH 09/13] hooks: use monotonic clock for main loop tasks --- .../src/main/java/net/runelite/client/callback/Hooks.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java b/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java index 9954f322dc..f4a963035a 100644 --- a/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java +++ b/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java @@ -42,7 +42,6 @@ import javax.inject.Singleton; import lombok.extern.slf4j.Slf4j; import net.runelite.api.BufferProvider; import net.runelite.api.Client; -import net.runelite.api.Constants; import net.runelite.api.MainBufferProvider; import net.runelite.api.NullItemID; import net.runelite.api.RenderOverview; @@ -75,6 +74,7 @@ import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.ui.overlay.OverlayRenderer; import net.runelite.client.ui.overlay.infobox.InfoBoxManager; import net.runelite.client.util.DeferredEventBus; +import net.runelite.client.util.RSTimeUnit; /** * This class contains field required for mixins and runelite hooks to work. @@ -85,7 +85,7 @@ import net.runelite.client.util.DeferredEventBus; @Slf4j public class Hooks implements Callbacks { - private static final long CHECK = Constants.GAME_TICK_LENGTH; // ms - how often to run checks + private static final long CHECK = RSTimeUnit.GAME_TICKS.getDuration().toNanos(); // ns - how often to run checks private static final Injector injector = RuneLite.getInjector(); private static final Client client = injector.getInstance(Client.class); @@ -192,7 +192,7 @@ public class Hooks implements Callbacks clientThread.invoke(); - long now = System.currentTimeMillis(); + long now = System.nanoTime(); if (now - lastCheck < CHECK) { From 81914b7c9528b82d00fdfd683864512fc25f6dbc Mon Sep 17 00:00:00 2001 From: Max Weber Date: Tue, 7 Apr 2020 13:27:21 -0600 Subject: [PATCH 10/13] kourendlibrary: don't throw npe when starting on the login screen books was null until you login, making the plugin throw every time the client starts --- .../plugins/kourendlibrary/KourendLibraryPlugin.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryPlugin.java index 6b81bd9f18..b08a7f2d9a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/kourendlibrary/KourendLibraryPlugin.java @@ -351,11 +351,10 @@ public class KourendLibraryPlugin extends Plugin private void updatePlayerBooks() { ItemContainer itemContainer = client.getItemContainer(InventoryID.INVENTORY); + EnumSet books = EnumSet.noneOf(Book.class); if (itemContainer != null) { - EnumSet books = EnumSet.noneOf(Book.class); - for (Item item : itemContainer.getItems()) { Book book = Book.byId(item.getId()); @@ -365,9 +364,9 @@ public class KourendLibraryPlugin extends Plugin books.add(book); } } - - playerBooks = books; } + + playerBooks = books; } private void updateBooksPanel() From 670e62b6b9fd877d473b296d5d68a93930c0a222 Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 6 Apr 2020 23:25:45 -0400 Subject: [PATCH 11/13] item service: remove old item searching and item lookup methods We haven't used this code in awhile. Additionally modify the price crawler to re-fetch known items in the event the name or examine changes. --- .../java/net/runelite/http/api/item/Item.java | 36 ---- .../runelite/http/api/item/ItemClient.java | 131 ------------ .../runelite/http/api/item/SearchResult.java | 42 ---- .../http/service/item/ItemController.java | 90 +-------- .../runelite/http/service/item/ItemEntry.java | 13 -- .../http/service/item/ItemService.java | 189 ++---------------- .../http/service/item/PendingLookup.java | 55 ----- .../runelite/http/service/item/RSItem.java | 16 +- .../http/service/item/RSItemResponse.java | 2 +- .../runelite/http/service/item/RSSearch.java | 34 ---- 10 files changed, 19 insertions(+), 589 deletions(-) delete mode 100644 http-api/src/main/java/net/runelite/http/api/item/Item.java delete mode 100644 http-api/src/main/java/net/runelite/http/api/item/SearchResult.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/item/PendingLookup.java delete mode 100644 http-service/src/main/java/net/runelite/http/service/item/RSSearch.java diff --git a/http-api/src/main/java/net/runelite/http/api/item/Item.java b/http-api/src/main/java/net/runelite/http/api/item/Item.java deleted file mode 100644 index 3a6f0346c4..0000000000 --- a/http-api/src/main/java/net/runelite/http/api/item/Item.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2017, Adam - * 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.http.api.item; - -import lombok.Data; - -@Data -public class Item -{ - private int id; - private String name; - private String description; - private ItemType type; -} diff --git a/http-api/src/main/java/net/runelite/http/api/item/ItemClient.java b/http-api/src/main/java/net/runelite/http/api/item/ItemClient.java index d1262e32c6..0dea2d1eed 100644 --- a/http-api/src/main/java/net/runelite/http/api/item/ItemClient.java +++ b/http-api/src/main/java/net/runelite/http/api/item/ItemClient.java @@ -26,14 +26,11 @@ package net.runelite.http.api.item; import com.google.gson.JsonParseException; import com.google.gson.reflect.TypeToken; -import java.awt.image.BufferedImage; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.lang.reflect.Type; -import java.util.Arrays; import java.util.Map; -import javax.imageio.ImageIO; import javax.inject.Inject; import net.runelite.http.api.RuneLiteAPI; import okhttp3.HttpUrl; @@ -55,134 +52,6 @@ public class ItemClient this.client = client; } - public ItemPrice lookupItemPrice(int itemId) throws IOException - { - HttpUrl url = RuneLiteAPI.getApiBase().newBuilder() - .addPathSegment("item") - .addPathSegment("" + itemId) - .addPathSegment("price") - .build(); - - logger.debug("Built URI: {}", url); - - Request request = new Request.Builder() - .url(url) - .build(); - - try (Response response = client.newCall(request).execute()) - { - if (!response.isSuccessful()) - { - logger.debug("Error looking up item {}: {}", itemId, response); - return null; - } - - InputStream in = response.body().byteStream(); - return RuneLiteAPI.GSON.fromJson(new InputStreamReader(in), ItemPrice.class); - } - catch (JsonParseException ex) - { - throw new IOException(ex); - } - } - - public ItemPrice[] lookupItemPrice(Integer[] itemIds) throws IOException - { - HttpUrl.Builder urlBuilder = RuneLiteAPI.getApiBase().newBuilder() - .addPathSegment("item") - .addPathSegment("price"); - - for (int itemId : itemIds) - { - urlBuilder.addQueryParameter("id", String.valueOf(itemId)); - } - - HttpUrl url = urlBuilder.build(); - - logger.debug("Built URI: {}", url); - - Request request = new Request.Builder() - .url(url) - .build(); - - try (Response response = client.newCall(request).execute()) - { - if (!response.isSuccessful()) - { - logger.debug("Error looking up items {}: {}", Arrays.toString(itemIds), response); - return null; - } - - InputStream in = response.body().byteStream(); - return RuneLiteAPI.GSON.fromJson(new InputStreamReader(in), ItemPrice[].class); - } - catch (JsonParseException ex) - { - throw new IOException(ex); - } - } - - public BufferedImage getIcon(int itemId) throws IOException - { - HttpUrl url = RuneLiteAPI.getApiBase().newBuilder() - .addPathSegment("item") - .addPathSegment("" + itemId) - .addPathSegment("icon") - .build(); - - logger.debug("Built URI: {}", url); - - Request request = new Request.Builder() - .url(url) - .build(); - - try (Response response = client.newCall(request).execute()) - { - if (!response.isSuccessful()) - { - logger.debug("Error grabbing icon {}: {}", itemId, response); - return null; - } - - InputStream in = response.body().byteStream(); - synchronized (ImageIO.class) - { - return ImageIO.read(in); - } - } - } - - public SearchResult search(String itemName) throws IOException - { - HttpUrl url = RuneLiteAPI.getApiBase().newBuilder() - .addPathSegment("item") - .addPathSegment("search") - .addQueryParameter("query", itemName) - .build(); - - logger.debug("Built URI: {}", url); - - Request request = new Request.Builder() - .url(url) - .build(); - - try (Response response = client.newCall(request).execute()) - { - if (!response.isSuccessful()) - { - logger.debug("Error looking up item {}: {}", itemName, response); - return null; - } - - InputStream in = response.body().byteStream(); - return RuneLiteAPI.GSON.fromJson(new InputStreamReader(in), SearchResult.class); - } - catch (JsonParseException ex) - { - throw new IOException(ex); - } - } - public ItemPrice[] getPrices() throws IOException { HttpUrl.Builder urlBuilder = RuneLiteAPI.getApiBase().newBuilder() diff --git a/http-api/src/main/java/net/runelite/http/api/item/SearchResult.java b/http-api/src/main/java/net/runelite/http/api/item/SearchResult.java deleted file mode 100644 index 90ae1ec783..0000000000 --- a/http-api/src/main/java/net/runelite/http/api/item/SearchResult.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2017, Adam - * 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.http.api.item; - -import java.util.List; - -public class SearchResult -{ - private List items; - - public List getItems() - { - return items; - } - - public void setItems(List items) - { - this.items = items; - } -} diff --git a/http-service/src/main/java/net/runelite/http/service/item/ItemController.java b/http-service/src/main/java/net/runelite/http/service/item/ItemController.java index 8db56ef2ff..331f01db69 100644 --- a/http-service/src/main/java/net/runelite/http/service/item/ItemController.java +++ b/http-service/src/main/java/net/runelite/http/service/item/ItemController.java @@ -26,8 +26,6 @@ package net.runelite.http.service.item; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; import com.google.common.hash.HashCode; import com.google.common.hash.Hasher; import com.google.common.hash.Hashing; @@ -35,11 +33,7 @@ import java.time.Instant; import java.util.Arrays; import java.util.List; import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; -import javax.servlet.http.HttpServletResponse; -import net.runelite.http.api.item.Item; import net.runelite.http.api.item.ItemPrice; -import net.runelite.http.api.item.SearchResult; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.CacheControl; import org.springframework.http.ResponseEntity; @@ -53,7 +47,6 @@ import org.springframework.web.bind.annotation.RestController; @RequestMapping("/item") public class ItemController { - private static final String RUNELITE_CACHE = "RuneLite-Cache"; private static final int MAX_BATCH_LOOKUP = 1024; private static class MemoizedPrices @@ -75,10 +68,6 @@ public class ItemController } } - private final Cache cachedEmpty = CacheBuilder.newBuilder() - .maximumSize(1024L) - .build(); - private final ItemService itemService; private final Supplier memoizedPrices; @@ -101,58 +90,12 @@ public class ItemController .toArray(ItemPrice[]::new)), 30, TimeUnit.MINUTES); } - @GetMapping("/{itemId}") - public Item getItem(HttpServletResponse response, @PathVariable int itemId) - { - ItemEntry item = itemService.getItem(itemId); - if (item != null) - { - return item.toItem(); - } - - itemService.queueItem(itemId); - return null; - } - - @GetMapping(path = "/{itemId}/icon", produces = "image/gif") - public ResponseEntity getIcon(@PathVariable int itemId) - { - ItemEntry item = itemService.getItem(itemId); - if (item != null && item.getIcon() != null) - { - return ResponseEntity.ok(item.getIcon()); - } - - itemService.queueItem(itemId); - return ResponseEntity.notFound().build(); - } - - @GetMapping(path = "/{itemId}/icon/large", produces = "image/gif") - public ResponseEntity getIconLarge(HttpServletResponse response, @PathVariable int itemId) - { - ItemEntry item = itemService.getItem(itemId); - if (item != null && item.getIcon_large() != null) - { - return ResponseEntity.ok(item.getIcon_large()); - } - - itemService.queueItem(itemId); - return ResponseEntity.notFound().build(); - } - @GetMapping("/{itemId}/price") public ResponseEntity itemPrice( @PathVariable int itemId, @RequestParam(required = false) Instant time ) { - if (cachedEmpty.getIfPresent(itemId) != null) - { - return ResponseEntity.notFound() - .header(RUNELITE_CACHE, "HIT") - .build(); - } - Instant now = Instant.now(); if (time != null && time.isAfter(now)) @@ -160,16 +103,6 @@ public class ItemController time = now; } - ItemEntry item = itemService.getItem(itemId); - if (item == null) - { - itemService.queueItem(itemId); // queue lookup - cachedEmpty.put(itemId, itemId); // cache empty - return ResponseEntity.notFound() - .header(RUNELITE_CACHE, "MISS") - .build(); - } - PriceEntry priceEntry = itemService.getPrice(itemId, time); if (time != null) @@ -178,22 +111,21 @@ public class ItemController { // we maybe can't backfill this return ResponseEntity.notFound() - .header(RUNELITE_CACHE, "MISS") + .cacheControl(CacheControl.maxAge(30, TimeUnit.MINUTES).cachePublic()) .build(); } } else if (priceEntry == null) { // Price is unknown - cachedEmpty.put(itemId, itemId); return ResponseEntity.notFound() - .header(RUNELITE_CACHE, "MISS") + .cacheControl(CacheControl.maxAge(30, TimeUnit.MINUTES).cachePublic()) .build(); } ItemPrice itemPrice = new ItemPrice(); - itemPrice.setId(item.getId()); - itemPrice.setName(item.getName()); + itemPrice.setId(itemId); + itemPrice.setName(priceEntry.getName()); itemPrice.setPrice(priceEntry.getPrice()); itemPrice.setTime(priceEntry.getTime()); @@ -202,20 +134,6 @@ public class ItemController .body(itemPrice); } - @GetMapping("/search") - public SearchResult search(@RequestParam String query) - { - List result = itemService.search(query); - - itemService.queueSearch(query); - - SearchResult searchResult = new SearchResult(); - searchResult.setItems(result.stream() - .map(ItemEntry::toItem) - .collect(Collectors.toList())); - return searchResult; - } - @GetMapping("/price") public ItemPrice[] prices(@RequestParam("id") int[] itemIds) { diff --git a/http-service/src/main/java/net/runelite/http/service/item/ItemEntry.java b/http-service/src/main/java/net/runelite/http/service/item/ItemEntry.java index b92f171cc7..41186b1608 100644 --- a/http-service/src/main/java/net/runelite/http/service/item/ItemEntry.java +++ b/http-service/src/main/java/net/runelite/http/service/item/ItemEntry.java @@ -26,7 +26,6 @@ package net.runelite.http.service.item; import java.time.Instant; import lombok.Data; -import net.runelite.http.api.item.Item; import net.runelite.http.api.item.ItemType; @Data @@ -36,17 +35,5 @@ public class ItemEntry private String name; private String description; private ItemType type; - private byte[] icon; - private byte[] icon_large; private Instant timestamp; - - public Item toItem() - { - Item item = new Item(); - item.setId(id); - item.setName(name); - item.setDescription(description); - item.setType(type); - return item; - } } diff --git a/http-service/src/main/java/net/runelite/http/service/item/ItemService.java b/http-service/src/main/java/net/runelite/http/service/item/ItemService.java index 72a0fe85aa..35aaabe94a 100644 --- a/http-service/src/main/java/net/runelite/http/service/item/ItemService.java +++ b/http-service/src/main/java/net/runelite/http/service/item/ItemService.java @@ -35,7 +35,6 @@ import java.util.List; import java.util.Map; import java.util.Random; import java.util.Set; -import java.util.concurrent.ConcurrentLinkedQueue; import lombok.extern.slf4j.Slf4j; import net.runelite.cache.definitions.ItemDefinition; import net.runelite.http.api.RuneLiteAPI; @@ -59,18 +58,14 @@ public class ItemService private static final String BASE = "https://services.runescape.com/m=itemdb_oldschool"; private static final HttpUrl RS_ITEM_URL = HttpUrl.parse(BASE + "/api/catalogue/detail.json"); private static final HttpUrl RS_PRICE_URL = HttpUrl.parse(BASE + "/api/graph"); - private static final HttpUrl RS_SEARCH_URL = HttpUrl.parse(BASE + "/api/catalogue/items.json?category=1"); private static final String CREATE_ITEMS = "CREATE TABLE IF NOT EXISTS `items` (\n" + " `id` int(11) NOT NULL,\n" + " `name` tinytext NOT NULL,\n" + " `description` tinytext NOT NULL,\n" + " `type` enum('DEFAULT') NOT NULL,\n" - + " `icon` blob,\n" - + " `icon_large` blob,\n" + " `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n" - + " PRIMARY KEY (`id`),\n" - + " FULLTEXT idx_name (name)\n" + + " PRIMARY KEY (`id`)\n" + ") ENGINE=InnoDB"; private static final String CREATE_PRICES = "CREATE TABLE IF NOT EXISTS `prices` (\n" @@ -82,12 +77,9 @@ public class ItemService + " KEY `item_fetched_time` (`item`,`fetched_time`)\n" + ") ENGINE=InnoDB"; - private static final int MAX_PENDING = 512; - private final Sql2o sql2o; private final CacheService cacheService; - private final ConcurrentLinkedQueue pendingLookups = new ConcurrentLinkedQueue(); private int[] tradeableItems; private final Random random = new Random(); @@ -112,11 +104,9 @@ public class ItemService { try (Connection con = sql2o.open()) { - ItemEntry item = con.createQuery("select id, name, description, type, icon, icon_large from items where id = :id") + return con.createQuery("select id, name, description, type from items where id = :id") .addParameter("id", itemId) .executeAndFetchFirst(ItemEntry.class); - - return item; } } @@ -174,54 +164,21 @@ public class ItemService } } - public List search(String search) - { - try (Connection con = sql2o.open()) - { - return con.createQuery("select id, name, description, type, match (name) against (:search) as score from items " - + "where match (name) against (:search) order by score desc limit 10") - .throwOnMappingFailure(false) // otherwise it tries to map 'score' - .addParameter("search", search) - .executeAndFetch(ItemEntry.class); - } - } - public ItemEntry fetchItem(int itemId) { try { RSItem rsItem = fetchRSItem(itemId); - byte[] icon = null, iconLarge = null; - - try - { - icon = fetchImage(rsItem.getIcon()); - } - catch (IOException ex) - { - log.warn("error fetching image", ex); - } - - try - { - iconLarge = fetchImage(rsItem.getIcon_large()); - } - catch (IOException ex) - { - log.warn("error fetching image", ex); - } try (Connection con = sql2o.open()) { - con.createQuery("insert into items (id, name, description, type, icon, icon_large) values (:id," - + " :name, :description, :type, :icon, :icon_large) ON DUPLICATE KEY UPDATE name = :name," - + " description = :description, type = :type, icon = :icon, icon_large = :icon_large") + con.createQuery("insert into items (id, name, description, type) values (:id," + + " :name, :description, :type) ON DUPLICATE KEY UPDATE name = :name," + + " description = :description, type = :type") .addParameter("id", rsItem.getId()) .addParameter("name", rsItem.getName()) .addParameter("description", rsItem.getDescription()) .addParameter("type", rsItem.getType()) - .addParameter("icon", icon) - .addParameter("icon_large", iconLarge) .executeUpdate(); } @@ -230,8 +187,6 @@ public class ItemService item.setName(rsItem.getName()); item.setDescription(rsItem.getDescription()); item.setType(ItemType.of(rsItem.getType())); - item.setIcon(icon); - item.setIcon_large(iconLarge); return item; } catch (IOException ex) @@ -241,7 +196,7 @@ public class ItemService } } - public List fetchPrice(int itemId) + private List fetchPrice(int itemId) { RSPrices rsprice; try @@ -296,8 +251,8 @@ public class ItemService try (Connection con = sql2o.beginTransaction()) { Query query = con.createQuery("select t2.item, t3.name, t2.time, prices.price, prices.fetched_time from (select t1.item as item, max(t1.time) as time from prices t1 group by item) t2 " + - " join prices on t2.item=prices.item and t2.time=prices.time" + - " join items t3 on t2.item=t3.id"); + " join prices on t2.item=prices.item and t2.time=prices.time" + + " join items t3 on t2.item=t3.id"); return query.executeAndFetch(PriceEntry.class); } } @@ -332,46 +287,7 @@ public class ItemService return fetchJson(request, RSPrices.class); } - public RSSearch fetchRSSearch(String query) throws IOException - { - // rs api seems to require lowercase - query = query.toLowerCase(); - - HttpUrl searchUrl = RS_SEARCH_URL - .newBuilder() - .addQueryParameter("alpha", query) - .build(); - - Request request = new Request.Builder() - .url(searchUrl) - .build(); - - return fetchJson(request, RSSearch.class); - } - - private void batchInsertItems(RSSearch search) - { - try (Connection con = sql2o.beginTransaction()) - { - Query q = con.createQuery("insert into items (id, name, description, type) values (:id," - + " :name, :description, :type) ON DUPLICATE KEY UPDATE name = :name," - + " description = :description, type = :type"); - - for (RSItem rsItem : search.getItems()) - { - q.addParameter("id", rsItem.getId()) - .addParameter("name", rsItem.getName()) - .addParameter("description", rsItem.getDescription()) - .addParameter("type", rsItem.getType()) - .addToBatch(); - } - - q.executeBatch(); - con.commit(false); - } - } - - private T fetchJson(Request request, Class clazz) throws IOException + private static T fetchJson(Request request, Class clazz) throws IOException { try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute()) { @@ -389,78 +305,6 @@ public class ItemService } } - private byte[] fetchImage(String url) throws IOException - { - HttpUrl httpUrl = HttpUrl.parse(url); - - Request request = new Request.Builder() - .url(httpUrl) - .build(); - - try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute()) - { - if (!response.isSuccessful()) - { - throw new IOException("Unsuccessful http response: " + response); - } - - return response.body().bytes(); - } - } - - public void queueSearch(String search) - { - if (pendingLookups.size() < MAX_PENDING) - { - pendingLookups.add(new PendingLookup(search, PendingLookup.Type.SEARCH)); - } - else - { - log.debug("Dropping pending search for {}", search); - } - } - - public void queueItem(int itemId) - { - if (pendingLookups.size() < MAX_PENDING) - { - pendingLookups.add(new PendingLookup(itemId, PendingLookup.Type.ITEM)); - } - else - { - log.debug("Dropping pending item lookup for {}", itemId); - } - } - - @Scheduled(fixedDelay = 5000) - public void check() - { - PendingLookup pendingLookup = pendingLookups.poll(); - if (pendingLookup == null) - { - return; - } - - switch (pendingLookup.getType()) - { - case SEARCH: - try - { - RSSearch reSearch = fetchRSSearch(pendingLookup.getSearch()); - - batchInsertItems(reSearch); - } - catch (IOException ex) - { - log.warn("error while searching items", ex); - } - break; - case ITEM: - fetchItem(pendingLookup.getItemId()); - break; - } - } - @Scheduled(fixedDelay = 20_000) public void crawlPrices() { @@ -472,16 +316,10 @@ public class ItemService int idx = random.nextInt(tradeableItems.length); int id = tradeableItems[idx]; - if (getItem(id) == null) - { - // This is a new item.. - log.debug("Fetching new item {}", id); - queueItem(id); - return; - } - log.debug("Fetching price for {}", id); + // check if the item name or description has changed + fetchItem(id); fetchPrice(id); } @@ -495,11 +333,10 @@ public class ItemService } tradeableItems = items.stream() - .filter(item -> item.isTradeable) - .mapToInt(item -> item.id) + .filter(ItemDefinition::isTradeable) + .mapToInt(ItemDefinition::getId) .toArray(); log.debug("Loaded {} tradeable items", tradeableItems.length); } - } diff --git a/http-service/src/main/java/net/runelite/http/service/item/PendingLookup.java b/http-service/src/main/java/net/runelite/http/service/item/PendingLookup.java deleted file mode 100644 index d23ff5c1d9..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/item/PendingLookup.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2018, Adam - * 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.http.service.item; - -import lombok.Value; - -@Value -class PendingLookup -{ - enum Type - { - SEARCH, - ITEM; - } - - private final int itemId; - private final String search; - private final Type type; - - public PendingLookup(int itemId, Type type) - { - this.itemId = itemId; - this.search = null; - this.type = type; - } - - public PendingLookup(String search, Type type) - { - this.itemId = -1; - this.search = search; - this.type = type; - } -} diff --git a/http-service/src/main/java/net/runelite/http/service/item/RSItem.java b/http-service/src/main/java/net/runelite/http/service/item/RSItem.java index b7c09260c6..17e3352f6d 100644 --- a/http-service/src/main/java/net/runelite/http/service/item/RSItem.java +++ b/http-service/src/main/java/net/runelite/http/service/item/RSItem.java @@ -25,26 +25,12 @@ package net.runelite.http.service.item; import lombok.Data; -import net.runelite.http.api.item.Item; -import net.runelite.http.api.item.ItemType; @Data -public class RSItem +class RSItem { private int id; private String name; private String description; private String type; - private String icon; - private String icon_large; - - public Item toItem() - { - Item item = new Item(); - item.setId(id); - item.setName(name); - item.setType(ItemType.of(type)); - item.setDescription(description); - return item; - } } diff --git a/http-service/src/main/java/net/runelite/http/service/item/RSItemResponse.java b/http-service/src/main/java/net/runelite/http/service/item/RSItemResponse.java index 3fd7b3cef3..c0305cd552 100644 --- a/http-service/src/main/java/net/runelite/http/service/item/RSItemResponse.java +++ b/http-service/src/main/java/net/runelite/http/service/item/RSItemResponse.java @@ -27,7 +27,7 @@ package net.runelite.http.service.item; import lombok.Data; @Data -public class RSItemResponse +class RSItemResponse { private RSItem item; } diff --git a/http-service/src/main/java/net/runelite/http/service/item/RSSearch.java b/http-service/src/main/java/net/runelite/http/service/item/RSSearch.java deleted file mode 100644 index b0edfdf798..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/item/RSSearch.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2017, Adam - * 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.http.service.item; - -import java.util.List; -import lombok.Data; - -@Data -public class RSSearch -{ - private List items; -} From 6e06b1c929e73ad390ad051e9deec5dd1294a650 Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 6 Apr 2020 12:17:21 -0400 Subject: [PATCH 12/13] antidrag: add option to disable in pvp This lifts the shift requirement by instead just disabling the feature in pvp Co-authored-by: jcwhisman --- .../main/java/net/runelite/api/Varbits.java | 12 +- .../plugins/antidrag/AntiDragConfig.java | 13 ++- .../plugins/antidrag/AntiDragPlugin.java | 109 ++++++++++++++++-- 3 files changed, 120 insertions(+), 14 deletions(-) diff --git a/runelite-api/src/main/java/net/runelite/api/Varbits.java b/runelite-api/src/main/java/net/runelite/api/Varbits.java index b9b8a7a4ed..9caeeb0840 100644 --- a/runelite-api/src/main/java/net/runelite/api/Varbits.java +++ b/runelite-api/src/main/java/net/runelite/api/Varbits.java @@ -563,7 +563,17 @@ public enum Varbits TWISTED_LEAGUE_RELIC_2(10050), TWISTED_LEAGUE_RELIC_3(10051), TWISTED_LEAGUE_RELIC_4(10052), - TWISTED_LEAGUE_RELIC_5(10053); + TWISTED_LEAGUE_RELIC_5(10053), + + /** + * Whether the Special Attack orb is disabled due to being in a PvP area + * + * 0 = Enabled (player is not in PvP) + * 1 = Disabled (player in in PvP) + * + * @see The OSRS Wiki's Minimap page + */ + PVP_SPEC_ORB(8121); /** * The raw varbit ID. diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragConfig.java index 01767c5b4e..3e645547f1 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragConfig.java @@ -29,7 +29,7 @@ import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; -@ConfigGroup("antiDrag") +@ConfigGroup(AntiDragPlugin.CONFIG_GROUP) public interface AntiDragConfig extends Config { @ConfigItem( @@ -42,4 +42,15 @@ public interface AntiDragConfig extends Config { return Constants.GAME_TICK_LENGTH / Constants.CLIENT_TICK_LENGTH; // one game tick } + + @ConfigItem( + keyName = "onShiftOnly", + name = "On Shift Only", + description = "Configures whether to only adjust the delay while holding shift. Required for anti drag in PvP scenarios.", + position = 2 + ) + default boolean onShiftOnly() + { + return true; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragPlugin.java index 41b025e2aa..e6c7c7f0b0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragPlugin.java @@ -28,34 +28,49 @@ import com.google.inject.Provides; import java.awt.event.KeyEvent; import javax.inject.Inject; import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.Varbits; import net.runelite.api.events.FocusChanged; +import net.runelite.api.events.VarbitChanged; +import net.runelite.api.events.WidgetLoaded; import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetID; import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.callback.ClientThread; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.events.ConfigChanged; import net.runelite.client.input.KeyListener; import net.runelite.client.input.KeyManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; @PluginDescriptor( - name = "Shift Anti Drag", + name = "Anti Drag", description = "Prevent dragging an item for a specified delay", - tags = {"antidrag", "delay", "inventory", "items"} + tags = {"antidrag", "delay", "inventory", "items"}, + enabledByDefault = false ) public class AntiDragPlugin extends Plugin implements KeyListener { + static final String CONFIG_GROUP = "antiDrag"; + private static final int DEFAULT_DELAY = 5; @Inject private Client client; + @Inject + private ClientThread clientThread; + @Inject private AntiDragConfig config; @Inject private KeyManager keyManager; + private boolean inPvp; + @Provides AntiDragConfig getConfig(ConfigManager configManager) { @@ -65,13 +80,25 @@ public class AntiDragPlugin extends Plugin implements KeyListener @Override protected void startUp() throws Exception { + if (client.getGameState() == GameState.LOGGED_IN) + { + clientThread.invokeLater(() -> + { + inPvp = client.getVar(Varbits.PVP_SPEC_ORB) == 1; + if (!config.onShiftOnly() && !inPvp) + { + setDragDelay(); + } + }); + } + keyManager.registerKeyListener(this); } @Override protected void shutDown() throws Exception { - client.setInventoryDragDelay(DEFAULT_DELAY); + clientThread.invoke(this::resetDragDelay); keyManager.unregisterKeyListener(this); } @@ -84,31 +111,77 @@ public class AntiDragPlugin extends Plugin implements KeyListener @Override public void keyPressed(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_SHIFT) + if (e.getKeyCode() == KeyEvent.VK_SHIFT && config.onShiftOnly()) { - final int delay = config.dragDelay(); - client.setInventoryDragDelay(delay); - setBankDragDelay(delay); + setDragDelay(); } } @Override public void keyReleased(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_SHIFT) + if (e.getKeyCode() == KeyEvent.VK_SHIFT && config.onShiftOnly()) { - client.setInventoryDragDelay(DEFAULT_DELAY); - setBankDragDelay(DEFAULT_DELAY); + resetDragDelay(); } } + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + if (event.getGroup().equals(CONFIG_GROUP)) + { + if (config.onShiftOnly() || inPvp) + { + clientThread.invoke(this::resetDragDelay); + } + else + { + clientThread.invoke(this::setDragDelay); + } + } + } + + @Subscribe + public void onVarbitChanged(VarbitChanged varbitChanged) + { + boolean currentStatus = client.getVar(Varbits.PVP_SPEC_ORB) == 1; + + if (currentStatus != inPvp) + { + inPvp = currentStatus; + + if (!inPvp && !config.onShiftOnly()) + { + setDragDelay(); + } + else + { + resetDragDelay(); + } + } + + } + @Subscribe public void onFocusChanged(FocusChanged focusChanged) { if (!focusChanged.isFocused()) { - client.setInventoryDragDelay(DEFAULT_DELAY); - setBankDragDelay(DEFAULT_DELAY); + clientThread.invoke(this::resetDragDelay); + } + else if (!inPvp && !config.onShiftOnly()) + { + clientThread.invoke(this::setDragDelay); + } + } + + @Subscribe + public void onWidgetLoaded(WidgetLoaded widgetLoaded) + { + if (widgetLoaded.getGroupId() == WidgetID.BANK_GROUP_ID) + { + setBankDragDelay(config.dragDelay()); } } @@ -125,4 +198,16 @@ public class AntiDragPlugin extends Plugin implements KeyListener } } + private void setDragDelay() + { + client.setInventoryDragDelay(config.dragDelay()); + setBankDragDelay(config.dragDelay()); + } + + private void resetDragDelay() + { + client.setInventoryDragDelay(DEFAULT_DELAY); + setBankDragDelay(DEFAULT_DELAY); + } + } From 15b5dd02902b5f86440441009aa82e656458643f Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 7 Apr 2020 16:30:03 -0400 Subject: [PATCH 13/13] worldhopper: skip over almost full worlds Co-authored-by: Hugh --- .../client/plugins/worldhopper/WorldHopperPlugin.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java index 238338f63b..d8f29c54d0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java @@ -31,7 +31,6 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ObjectArrays; import com.google.inject.Provides; import java.awt.image.BufferedImage; -import java.time.Duration; import java.time.Instant; import java.util.EnumSet; import java.util.HashMap; @@ -101,7 +100,7 @@ import org.apache.commons.lang3.ArrayUtils; public class WorldHopperPlugin extends Plugin { private static final int REFRESH_THROTTLE = 60_000; // ms - private static final int TICK_THROTTLE = (int) Duration.ofMinutes(10).toMillis(); + private static final int MAX_PLAYER_COUNT = 1950; private static final int DISPLAY_SWITCHER_MAX_ATTEMPTS = 3; @@ -584,6 +583,12 @@ public class WorldHopperPlugin extends Plugin } } + // Avoid switching to near-max population worlds, as it will refuse to allow the hop if the world is full + if (world.getPlayers() >= MAX_PLAYER_COUNT) + { + continue; + } + // Break out if we've found a good world to hop to if (currentWorldTypes.equals(types)) {