From bb6c2d6381d49583d3b7ec7587c7cdeff868aacb Mon Sep 17 00:00:00 2001 From: RobertCurll Date: Wed, 13 May 2020 21:14:50 -0700 Subject: [PATCH 01/31] skillcalculator: Add comma separators to experience fields --- .../client/plugins/skillcalculator/SkillCalculator.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/SkillCalculator.java b/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/SkillCalculator.java index 8b0c10c654..c93b6917ec 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/SkillCalculator.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/SkillCalculator.java @@ -367,10 +367,12 @@ class SkillCalculator extends JPanel targetXP = Experience.getXpForLevel(targetLevel); } + final String cXP = String.format("%,d", currentXP); + final String tXP = String.format("%,d", targetXP); uiInput.setCurrentLevelInput(currentLevel); - uiInput.setCurrentXPInput(currentXP); + uiInput.setCurrentXPInput(cXP); uiInput.setTargetLevelInput(targetLevel); - uiInput.setTargetXPInput(targetXP); + uiInput.setTargetXPInput(tXP); calculate(); } From 81427bfd9479fb6f64ec51b1ab6f2c54448cf6e7 Mon Sep 17 00:00:00 2001 From: RobertCurll Date: Wed, 13 May 2020 21:15:27 -0700 Subject: [PATCH 02/31] skillcalculator: Add needed experience tooltip This adds a tooltip to the "Target Experience" field indicating the amount of experience needed to reach that target. --- .../client/plugins/skillcalculator/SkillCalculator.java | 2 ++ .../plugins/skillcalculator/UICalculatorInputArea.java | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/SkillCalculator.java b/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/SkillCalculator.java index c93b6917ec..30d6979a54 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/SkillCalculator.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/SkillCalculator.java @@ -369,10 +369,12 @@ class SkillCalculator extends JPanel final String cXP = String.format("%,d", currentXP); final String tXP = String.format("%,d", targetXP); + final String nXP = String.format("%,d", targetXP - currentXP); uiInput.setCurrentLevelInput(currentLevel); uiInput.setCurrentXPInput(cXP); uiInput.setTargetLevelInput(targetLevel); uiInput.setTargetXPInput(tXP); + uiInput.setNeededXP(nXP + " XP required to reach target XP"); calculate(); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/UICalculatorInputArea.java b/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/UICalculatorInputArea.java index a15565bd34..06fc201a0e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/UICalculatorInputArea.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/UICalculatorInputArea.java @@ -94,6 +94,11 @@ class UICalculatorInputArea extends JPanel setInput(uiFieldTargetXP, value); } + void setNeededXP(Object value) + { + uiFieldTargetXP.setToolTipText((String) value); + } + private int getInput(JTextField field) { try From aae994cbf1172cbb59a171b7ccf06b01d9f34cc1 Mon Sep 17 00:00:00 2001 From: geheur <41499327+geheur@users.noreply.github.com> Date: Thu, 21 May 2020 11:03:28 -0700 Subject: [PATCH 03/31] menu swapper: add swaps for buy and sell --- .../plugins/menuentryswapper/BuyMode.java | 41 +++++++++++++++++++ .../MenuEntrySwapperConfig.java | 20 +++++++++ .../MenuEntrySwapperPlugin.java | 12 ++++++ .../plugins/menuentryswapper/SellMode.java | 41 +++++++++++++++++++ 4 files changed, 114 insertions(+) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/BuyMode.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/SellMode.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/BuyMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/BuyMode.java new file mode 100644 index 0000000000..2c1ab2a818 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/BuyMode.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2020, Sam + * 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.menuentryswapper; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum BuyMode +{ + OFF(null), + BUY_1("buy 1"), + BUY_5("buy 5"), + BUY_10("buy 10"), + BUY_50("buy 50"); + + private final String option; +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperConfig.java index f54b99fd6b..88e5ff0bfe 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperConfig.java @@ -412,6 +412,26 @@ public interface MenuEntrySwapperConfig extends Config return ShiftDepositMode.OFF; } + @ConfigItem( + keyName = "shopBuy", + name = "Shop Buy Shift-Click", + description = "Swaps the Buy options with Value on items in shops when shift is held." + ) + default BuyMode shopBuy() + { + return BuyMode.OFF; + } + + @ConfigItem( + keyName = "shopSell", + name = "Shop Sell Shift-Click", + description = "Swaps the Sell options with Value on items in your inventory when selling to shops when shift is held." + ) + default SellMode shopSell() + { + return SellMode.OFF; + } + @ConfigItem( keyName = "swapEssenceMineTeleport", name = "Essence Mine Teleport", diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java index 2b1b6b4289..f148ec9a90 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java @@ -733,6 +733,18 @@ public class MenuEntrySwapperPlugin extends Plugin swap("barbarian guard", option, target, index); swap("random", option, target, index); } + else if (shiftModifier && option.equals("value")) + { + if (config.shopBuy() != null && config.shopBuy() != BuyMode.OFF) + { + swap(config.shopBuy().getOption(), option, target, index); + } + + if (config.shopSell() != null && config.shopSell() != SellMode.OFF) + { + swap(config.shopSell().getOption(), option, target, index); + } + } else if (config.shiftClickCustomization() && shiftModifier && !option.equals("use")) { Integer customOption = getSwapConfig(eventId); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/SellMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/SellMode.java new file mode 100644 index 0000000000..814628eded --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/SellMode.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2020, Sam + * 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.menuentryswapper; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum SellMode +{ + OFF(null), + SELL_1("sell 1"), + SELL_5("sell 5"), + SELL_10("sell 10"), + SELL_50("sell 50"); + + private final String option; +} From aea258fb5cac5a5539fe7294bab57cea61f4dfa6 Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 11 May 2020 16:19:29 -0400 Subject: [PATCH 04/31] ge plugin: add buy limit reset timer Co-authored-by: renfc --- .../grandexchange/GrandExchangeConfig.java | 22 +++++-- .../grandexchange/GrandExchangePlugin.java | 64 +++++++++++++++++-- 2 files changed, 76 insertions(+), 10 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeConfig.java index 3268aa6716..9cb66911af 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeConfig.java @@ -28,9 +28,11 @@ import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; -@ConfigGroup("grandexchange") +@ConfigGroup(GrandExchangeConfig.CONFIG_GROUP) public interface GrandExchangeConfig extends Config { + String CONFIG_GROUP = "grandexchange"; + @ConfigItem( position = 1, keyName = "quickLookup", @@ -77,6 +79,18 @@ public interface GrandExchangeConfig extends Config @ConfigItem( position = 5, + keyName = "enableGELimitReset", + name = "Enable GE Limit Reset Timer", + description = "Shows when GE Trade limits reset (H:MM)" + ) + + default boolean enableGELimitReset() + { + return true; + } + + @ConfigItem( + position = 6, keyName = "showTotal", name = "Show grand exchange total", description = "Show grand exchange total" @@ -87,7 +101,7 @@ public interface GrandExchangeConfig extends Config } @ConfigItem( - position = 6, + position = 7, keyName = "showExact", name = "Show exact total value", description = "Show exact total value" @@ -98,7 +112,7 @@ public interface GrandExchangeConfig extends Config } @ConfigItem( - position = 7, + position = 8, keyName = "highlightSearchMatch", name = "Highlight Search Match", description = "Highlights the search match with an underline" @@ -109,7 +123,7 @@ public interface GrandExchangeConfig extends Config } @ConfigItem( - position = 8, + position = 9, keyName = "geSearchMode", name = "Search Mode", description = "The search mode to use for the GE
" 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 76f51245ee..8215e16675 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 @@ -30,18 +30,18 @@ package net.runelite.client.plugins.grandexchange; import com.google.common.annotations.VisibleForTesting; import com.google.common.primitives.Shorts; -import com.google.common.reflect.TypeToken; import com.google.gson.Gson; import com.google.inject.Provides; import java.awt.Color; import java.awt.image.BufferedImage; import java.io.IOException; +import java.time.Duration; +import java.time.Instant; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Locale; -import java.util.Map; import java.util.concurrent.ScheduledExecutorService; import java.util.function.ToIntFunction; import java.util.stream.Collectors; @@ -98,6 +98,7 @@ import net.runelite.http.api.ge.GrandExchangeTrade; import net.runelite.http.api.item.ItemStats; import net.runelite.http.api.osbuddy.OSBGrandExchangeClient; import net.runelite.http.api.osbuddy.OSBGrandExchangeResult; +import org.apache.commons.lang3.time.DurationFormatUtils; import org.apache.commons.text.similarity.FuzzyScore; @PluginDescriptor( @@ -114,10 +115,9 @@ public class GrandExchangePlugin extends Plugin private static final String OSB_GE_TEXT = "
OSBuddy Actively traded price: "; private static final String BUY_LIMIT_GE_TEXT = "
Buy limit: "; + private static final String BUY_LIMIT_KEY = "buylimit_"; private static final Gson GSON = new Gson(); - private static final TypeToken> BUY_LIMIT_TOKEN = new TypeToken>() - { - }; + private static final Duration BUY_LIMIT_RESET = Duration.ofHours(4); static final String SEARCH_GRAND_EXCHANGE = "Search Grand Exchange"; @@ -315,7 +315,7 @@ public class GrandExchangePlugin extends Plugin @Subscribe public void onConfigChanged(ConfigChanged event) { - if (event.getGroup().equals("grandexchange")) + if (event.getGroup().equals(GrandExchangeConfig.CONFIG_GROUP)) { if (event.getKey().equals("quickLookup")) { @@ -403,6 +403,8 @@ public class GrandExchangePlugin extends Plugin savedOffer.setSpent(offer.getSpent()); savedOffer.setState(offer.getState()); setOffer(slot, savedOffer); + + updateLimitTimer(offer); } } @@ -679,6 +681,46 @@ public class GrandExchangePlugin extends Plugin stringStack[stringStackSize - 1] += titleBuilder.toString(); } + private void setLimitResetTime(int itemId) + { + Instant lastDateTime = configManager.getConfiguration(GrandExchangeConfig.CONFIG_GROUP, + BUY_LIMIT_KEY + client.getUsername().toLowerCase() + "." + itemId, Instant.class); + if (lastDateTime == null || lastDateTime.isBefore(Instant.now())) + { + configManager.setConfiguration(GrandExchangeConfig.CONFIG_GROUP, + BUY_LIMIT_KEY + client.getUsername().toLowerCase() + "." + itemId, + Instant.now().plus(BUY_LIMIT_RESET)); + } + } + + private Instant getLimitResetTime(int itemId) + { + Instant lastDateTime = configManager.getConfiguration(GrandExchangeConfig.CONFIG_GROUP, + BUY_LIMIT_KEY + client.getUsername().toLowerCase() + "." + itemId, Instant.class); + if (lastDateTime == null) + { + return null; + } + + if (lastDateTime.isBefore(Instant.now())) + { + configManager.unsetConfiguration(GrandExchangeConfig.CONFIG_GROUP, BUY_LIMIT_KEY + client.getUsername().toLowerCase() + "." + itemId); + return null; + } + + return lastDateTime; + } + + private void updateLimitTimer(GrandExchangeOffer offer) + { + if (offer.getState() == GrandExchangeOfferState.BOUGHT || + (offer.getQuantitySold() > 0 && + offer.getState() == GrandExchangeOfferState.BUYING)) + { + setLimitResetTime(offer.getItemId()); + } + } + private void rebuildGeText() { if (grandExchangeText == null || grandExchangeItem == null || grandExchangeItem.isHidden()) @@ -709,6 +751,16 @@ public class GrandExchangePlugin extends Plugin } } + if (config.enableGELimitReset()) + { + Instant resetTime = getLimitResetTime(itemId); + if (resetTime != null) + { + Duration remaining = Duration.between(Instant.now(), resetTime); + text += " (" + DurationFormatUtils.formatDuration(remaining.toMillis(), "H:mm") + ")"; + } + } + geText.setText(text); if (!config.enableOsbPrices()) From a01a2483f7ddeec46af591f878ea5a9f4d8dc2d2 Mon Sep 17 00:00:00 2001 From: Matthew Kramer Date: Thu, 21 May 2020 15:44:21 -0400 Subject: [PATCH 05/31] metronome: add independent volume configuration --- .../plugins/metronome/MetronomePlugin.java | 18 +++++++--- .../MetronomePluginConfiguration.java | 36 ++++++++++++++----- 2 files changed, 40 insertions(+), 14 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/metronome/MetronomePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/metronome/MetronomePlugin.java index 7d7416c7f0..0c63dd2033 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/metronome/MetronomePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/metronome/MetronomePlugin.java @@ -27,7 +27,6 @@ package net.runelite.client.plugins.metronome; import com.google.inject.Provides; import javax.inject.Inject; -import net.runelite.api.SoundEffectVolume; import net.runelite.api.Client; import net.runelite.api.SoundEffectID; import net.runelite.api.events.GameTick; @@ -69,14 +68,23 @@ public class MetronomePlugin extends Plugin if (++tickCounter % config.tickCount() == 0) { - if (config.enableTock() && shouldTock) + // As playSoundEffect only uses the volume argument when the in-game volume isn't muted, sound effect volume + // needs to be set to the value desired for ticks or tocks and afterwards reset to the previous value. + int previousVolume = client.getSoundEffectVolume(); + + if (shouldTock && config.tockVolume() > 0) { - client.playSoundEffect(SoundEffectID.GE_DECREMENT_PLOP, SoundEffectVolume.MEDIUM_HIGH); + client.setSoundEffectVolume(config.tockVolume()); + client.playSoundEffect(SoundEffectID.GE_DECREMENT_PLOP, config.tockVolume()); } - else + else if (config.tickVolume() > 0) { - client.playSoundEffect(SoundEffectID.GE_INCREMENT_PLOP, SoundEffectVolume.MEDIUM_HIGH); + client.setSoundEffectVolume(config.tickVolume()); + client.playSoundEffect(SoundEffectID.GE_INCREMENT_PLOP, config.tickVolume()); } + + client.setSoundEffectVolume(previousVolume); + shouldTock = !shouldTock; } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/metronome/MetronomePluginConfiguration.java b/runelite-client/src/main/java/net/runelite/client/plugins/metronome/MetronomePluginConfiguration.java index cb2ff60889..161af611ae 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/metronome/MetronomePluginConfiguration.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/metronome/MetronomePluginConfiguration.java @@ -28,29 +28,47 @@ package net.runelite.client.plugins.metronome; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.Range; +import net.runelite.api.SoundEffectVolume; @ConfigGroup("metronome") public interface MetronomePluginConfiguration extends Config { + int VOLUME_MAX = SoundEffectVolume.HIGH; + @ConfigItem( keyName = "tickCount", name = "Tick count", - description = "Configures the tick on which a sound will be played", - position = 2 + description = "Configures the tick on which a sound will be played." ) default int tickCount() { return 1; } - @ConfigItem( - keyName = "enableTock", - name = "Enable tock (alternating) sound", - description = "Toggles whether to play two alternating sounds", - position = 3 + @Range( + max = VOLUME_MAX ) - default boolean enableTock() + @ConfigItem( + keyName = "tickVolume", + name = "Tick volume", + description = "Configures the volume of the tick sound. A value of 0 will disable tick sounds." + ) + default int tickVolume() { - return false; + return SoundEffectVolume.MEDIUM_HIGH; + } + + @Range( + max = VOLUME_MAX + ) + @ConfigItem( + keyName = "tockVolume", + name = "Tock volume", + description = "Configures the volume of the tock sound. A value of 0 will disable tock sounds." + ) + default int tockVolume() + { + return SoundEffectVolume.MUTED; } } From e658928277a192bae97e75293b06d7ae2b8fae71 Mon Sep 17 00:00:00 2001 From: Jordan Atwood Date: Thu, 21 May 2020 21:49:29 -0700 Subject: [PATCH 06/31] HotColdLocation: Center some location spots Center some hot-cold locations as reported and verified from the mega issue. Ref: runelite/runelite#9601 --- .../cluescrolls/clues/hotcold/HotColdLocation.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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 6ef9854d19..c889ab4b9f 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 @@ -67,8 +67,8 @@ public enum HotColdLocation DESERT_ALKHARID_MINE(new WorldPoint(3282, 3270, 0), DESERT, "West of Al Kharid mine.", BRASSICAN_MAGE), DESERT_MENAPHOS_GATE(new WorldPoint(3223, 2820, 0), DESERT, "North of Menaphos gate.", BRASSICAN_MAGE), DESERT_BEDABIN_CAMP(new WorldPoint(3164, 3050, 0), DESERT, "Bedabin Camp, dig around the north tent.", BRASSICAN_MAGE), - DESERT_UZER(new WorldPoint(3431, 3106, 0), DESERT, "West of Uzer.", BRASSICAN_MAGE), - DESERT_POLLNIVNEACH(new WorldPoint(3287, 2975, 0), DESERT, "West of Pollnivneach.", BRASSICAN_MAGE), + DESERT_UZER(new WorldPoint(3432, 3105, 0), DESERT, "West of Uzer.", BRASSICAN_MAGE), + DESERT_POLLNIVNEACH(new WorldPoint(3288, 2976, 0), DESERT, "West of Pollnivneach.", BRASSICAN_MAGE), DESERT_MTA(new WorldPoint(3347, 3295, 0), DESERT, "Next to Mage Training Arena.", BRASSICAN_MAGE), DESERT_SHANTY(new WorldPoint(3292, 3107, 0), DESERT, "South-west of Shantay Pass.", BRASSICAN_MAGE), DRAYNOR_MANOR_MUSHROOMS(new WorldPoint(3096, 3379, 0), MISTHALIN, "Patch of mushrooms just northwest of Draynor Manor"), @@ -84,7 +84,7 @@ public enum HotColdLocation FREMENNIK_PROVINCE_MTN_CAMP(new WorldPoint(2800, 3669, 0), FREMENNIK_PROVINCE, "At the Mountain Camp.", BRASSICAN_MAGE), FREMENNIK_PROVINCE_RELLEKKA_HUNTER(new WorldPoint(2720, 3784, 0), FREMENNIK_PROVINCE, "At the Rellekka Hunter area, near the Hunter icon.", BRASSICAN_MAGE), FREMENNIK_PROVINCE_KELGADRIM_ENTRANCE(new WorldPoint(2715, 3689, 0), FREMENNIK_PROVINCE, "West of the Keldagrim entrance mine.", BRASSICAN_MAGE), - FREMENNIK_PROVINCE_SW(new WorldPoint(2605, 3648, 0), FREMENNIK_PROVINCE, "Outside the fence in the south-western corner of Rellekka.", BRASSICAN_MAGE), + FREMENNIK_PROVINCE_SW(new WorldPoint(2604, 3648, 0), FREMENNIK_PROVINCE, "Outside the fence in the south-western corner of Rellekka.", BRASSICAN_MAGE), FREMENNIK_PROVINCE_LIGHTHOUSE(new WorldPoint(2585, 3601, 0), FREMENNIK_PROVINCE, "South-east of the Lighthouse.", BRASSICAN_MAGE), FREMENNIK_PROVINCE_ETCETERIA_CASTLE(new WorldPoint(2617, 3862, 0), FREMENNIK_PROVINCE, "South-east of Etceteria's castle.", BRASSICAN_MAGE), FREMENNIK_PROVINCE_MISC_COURTYARD(new WorldPoint(2527, 3868, 0), FREMENNIK_PROVINCE, "Outside Miscellania's courtyard.", BRASSICAN_MAGE), @@ -115,7 +115,7 @@ public enum HotColdLocation KANDARIN_BA_AGILITY_COURSE(new WorldPoint(2540, 3548, 0), KANDARIN, "Inside the Barbarian Agility Course. Completion of Alfred Grimhand's Barcrawl is required.", BRASSICAN_MAGE), KARAMJA_MUSA_POINT(new WorldPoint(2913, 3169, 0), KARAMJA, "Musa Point, banana plantation.", BRASSICAN_MAGE), KARAMJA_BRIMHAVEN_FRUIT_TREE(new WorldPoint(2782, 3215, 0), KARAMJA, "Brimhaven, east of the fruit tree patch.", BRASSICAN_MAGE), - KARAMJA_WEST_BRIMHAVEN(new WorldPoint(2721, 3169, 0), KARAMJA, "West of Brimhaven.", BRASSICAN_MAGE), + KARAMJA_WEST_BRIMHAVEN(new WorldPoint(2718, 3167, 0), KARAMJA, "West of Brimhaven.", BRASSICAN_MAGE), KARAMJA_GLIDER(new WorldPoint(2966, 2975, 0), KARAMJA, "West of the gnome glider.", BRASSICAN_MAGE), KARAMJA_KHARAZI_NE(new WorldPoint(2904, 2925, 0), KARAMJA, "North-eastern part of Kharazi Jungle.", BRASSICAN_MAGE), KARAMJA_KHARAZI_SW(new WorldPoint(2783, 2898, 0), KARAMJA, "South-western part of Kharazi Jungle.", BRASSICAN_MAGE), @@ -126,7 +126,7 @@ public enum HotColdLocation MISTHALIN_LUMBRIDGE_2(new WorldPoint(3169, 3279, 0), MISTHALIN, "North of the pond between Lumbridge and Draynor Village.", BRASSICAN_MAGE), MISTHALIN_GERTUDES(new WorldPoint(3154, 3421, 0), MISTHALIN, "North-east of Gertrude's house west of Varrock.", BRASSICAN_MAGE), MISTHALIN_DRAYNOR_BANK(new WorldPoint(3098, 3234, 0), MISTHALIN, "South of Draynor Village bank.", BRASSICAN_MAGE), - MISTHALIN_LUMBER_YARD(new WorldPoint(3303, 3483, 0), MISTHALIN, "South of Lumber Yard, east of Assistant Serf.", BRASSICAN_MAGE), + MISTHALIN_LUMBER_YARD(new WorldPoint(3301, 3484, 0), MISTHALIN, "South of Lumber Yard, east of Assistant Serf.", BRASSICAN_MAGE), MORYTANIA_BURGH_DE_ROTT(new WorldPoint(3545, 3253, 0), MORYTANIA, "In the north-east area of Burgh de Rott, by the reverse-L-shaped ruins.", BRASSICAN_MAGE), MORYTANIA_PORT_PHASMATYS(new WorldPoint(3611, 3485, 0), MORYTANIA, "West of Port Phasmatys, south-east of fairy ring.", BRASSICAN_MAGE), MORYTANIA_HOLLOWS(new WorldPoint(3499, 3421, 0), MORYTANIA, "Inside The Hollows, south of the bridge which was repaired in a quest.", BRASSICAN_MAGE), From ab6b8c70ae903669334fbf5243c63eaf4670f4aa Mon Sep 17 00:00:00 2001 From: Melky <5113962+melkypie@users.noreply.github.com> Date: Fri, 22 May 2020 11:28:01 +0300 Subject: [PATCH 07/31] screenmarker: add ability to put screen markers around widgets (#11552) Gives you the ability to put a screen marker around a widget that has a menu option attached to it Co-authored-by: Jasper Ketelaar Co-authored-by: Tomas Slusny --- .../ScreenMarkerMouseListener.java | 12 +- .../screenmarkers/ScreenMarkerPlugin.java | 34 ++++- .../ScreenMarkerWidgetHighlightOverlay.java | 120 ++++++++++++++++++ .../ui/ScreenMarkerPluginPanel.java | 1 + 4 files changed, 163 insertions(+), 4 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerWidgetHighlightOverlay.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerMouseListener.java b/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerMouseListener.java index e00114041d..ace5980b42 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerMouseListener.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerMouseListener.java @@ -24,6 +24,7 @@ */ package net.runelite.client.plugins.screenmarkers; +import java.awt.Rectangle; import java.awt.event.MouseEvent; import javax.swing.SwingUtilities; import net.runelite.client.input.MouseAdapter; @@ -59,7 +60,16 @@ public class ScreenMarkerMouseListener extends MouseAdapter if (SwingUtilities.isLeftMouseButton(event)) { - plugin.startCreation(event.getPoint()); + final Rectangle bounds = plugin.getSelectedWidgetBounds(); + + if (bounds != null) + { + plugin.startCreation(bounds.getLocation(), bounds.getSize()); + } + else + { + plugin.startCreation(event.getPoint()); + } } else if (plugin.isCreatingScreenMarker()) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerPlugin.java index 9ca3c9c46d..6dc7558df2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerPlugin.java @@ -42,6 +42,7 @@ import java.util.stream.Stream; import javax.inject.Inject; import lombok.AccessLevel; import lombok.Getter; +import lombok.Setter; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.events.ConfigChanged; @@ -91,6 +92,9 @@ public class ScreenMarkerPlugin extends Plugin @Inject private ColorPickerManager colorPickerManager; + @Inject + private ScreenMarkerWidgetHighlightOverlay widgetHighlight; + private ScreenMarkerMouseListener mouseListener; private ScreenMarkerPluginPanel pluginPanel; private NavigationButton navigationButton; @@ -99,13 +103,22 @@ public class ScreenMarkerPlugin extends Plugin private ScreenMarker currentMarker; @Getter + @Setter private boolean creatingScreenMarker = false; + + @Getter + private boolean drawingScreenMarker = false; + + @Getter + @Setter + private Rectangle selectedWidgetBounds = null; private Point startLocation = null; @Override protected void startUp() throws Exception { overlayManager.add(overlay); + overlayManager.add(widgetHighlight); loadConfig(configManager.getConfiguration(CONFIG_GROUP, CONFIG_KEY)).forEach(screenMarkers::add); screenMarkers.forEach(overlayManager::add); @@ -130,16 +143,19 @@ public class ScreenMarkerPlugin extends Plugin protected void shutDown() throws Exception { overlayManager.remove(overlay); + overlayManager.remove(widgetHighlight); overlayManager.removeIf(ScreenMarkerOverlay.class::isInstance); screenMarkers.clear(); clientToolbar.removeNavigation(navigationButton); setMouseListenerEnabled(false); creatingScreenMarker = false; + drawingScreenMarker = false; pluginPanel = null; currentMarker = null; mouseListener = null; navigationButton = null; + selectedWidgetBounds = null; } @Subscribe @@ -166,6 +182,17 @@ public class ScreenMarkerPlugin extends Plugin } public void startCreation(Point location) + { + startCreation(location, DEFAULT_SIZE); + + // Stop the highlighting so we don't get rectangles around widgets while trying to make normal screen markers + if (selectedWidgetBounds == null) + { + drawingScreenMarker = true; + } + } + + public void startCreation(Point location, Dimension size) { currentMarker = new ScreenMarker( Instant.now().toEpochMilli(), @@ -179,8 +206,7 @@ public class ScreenMarkerPlugin extends Plugin // Set overlay creator bounds to current position and default size startLocation = location; overlay.setPreferredLocation(location); - overlay.setPreferredSize(DEFAULT_SIZE); - creatingScreenMarker = true; + overlay.setPreferredSize(size); } public void finishCreation(boolean aborted) @@ -200,6 +226,8 @@ public class ScreenMarkerPlugin extends Plugin } creatingScreenMarker = false; + drawingScreenMarker = false; + selectedWidgetBounds = null; startLocation = null; currentMarker = null; setMouseListenerEnabled(false); @@ -207,7 +235,6 @@ public class ScreenMarkerPlugin extends Plugin pluginPanel.setCreation(false); } - /* The marker area has been drawn, inform the user and unlock the confirm button */ public void completeSelection() { pluginPanel.getCreationPanel().unlockConfirm(); @@ -224,6 +251,7 @@ public class ScreenMarkerPlugin extends Plugin void resizeMarker(Point point) { + drawingScreenMarker = true; Rectangle bounds = new Rectangle(startLocation); bounds.add(point); overlay.setPreferredLocation(bounds.getLocation()); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerWidgetHighlightOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerWidgetHighlightOverlay.java new file mode 100644 index 0000000000..4dc590aefd --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerWidgetHighlightOverlay.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2018, Jasper + * Copyright (c) 2020, melky + * 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.screenmarkers; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.MenuEntry; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.api.widgets.WidgetItem; +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.OverlayPriority; + +class ScreenMarkerWidgetHighlightOverlay extends Overlay +{ + private final ScreenMarkerPlugin plugin; + private final Client client; + + @Inject + private ScreenMarkerWidgetHighlightOverlay(final ScreenMarkerPlugin plugin, final Client client) + { + this.plugin = plugin; + this.client = client; + setPosition(OverlayPosition.DETACHED); + setLayer(OverlayLayer.ABOVE_WIDGETS); + setPriority(OverlayPriority.HIGH); + } + + @Override + public Dimension render(Graphics2D graphics) + { + if (!plugin.isCreatingScreenMarker() || plugin.isDrawingScreenMarker()) + { + return null; + } + + if (client.isMenuOpen()) + { + plugin.setSelectedWidgetBounds(null); + return null; + } + + final MenuEntry[] menuEntries = client.getMenuEntries(); + + final int last = menuEntries.length - 1; + if (last < 0) + { + plugin.setSelectedWidgetBounds(null); + return null; + } + + final MenuEntry menuEntry = menuEntries[last]; + final int widgetId = menuEntry.getParam1(); + final int groupId = WidgetInfo.TO_GROUP(widgetId); + final int childId = WidgetInfo.TO_CHILD(widgetId); + + final Widget widget = client.getWidget(groupId, childId); + if (widget == null) + { + plugin.setSelectedWidgetBounds(null); + return null; + } + + final int param0 = menuEntry.getParam0(); + if (param0 > -1) + { + final WidgetItem widgetItem = widget.getWidgetItem(param0); + if (widgetItem != null) + { + drawHighlight(widgetItem.getCanvasBounds(), graphics); + } + else + { + drawHighlight(widget.getChild(param0).getBounds(), graphics); + } + } + else + { + drawHighlight(widget.getBounds(), graphics); + } + + return null; + } + + private void drawHighlight(Rectangle bounds, Graphics2D graphics) + { + graphics.setColor(Color.GREEN); + graphics.draw(bounds); + plugin.setSelectedWidgetBounds(bounds); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ui/ScreenMarkerPluginPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ui/ScreenMarkerPluginPanel.java index b0813cc8ef..d63a2af4d4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ui/ScreenMarkerPluginPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ui/ScreenMarkerPluginPanel.java @@ -204,6 +204,7 @@ public class ScreenMarkerPluginPanel extends PluginPanel { creationPanel.lockConfirm(); plugin.setMouseListenerEnabled(true); + plugin.setCreatingScreenMarker(true); } } } From f7532b2e9c0569cb7657ae8341becff3c7253e1e Mon Sep 17 00:00:00 2001 From: trimbe <19672127+trimbe@users.noreply.github.com> Date: Wed, 20 May 2020 13:17:48 -0400 Subject: [PATCH 08/31] bank tags: clear remembered search when the active tag tab is clicked This fixes an issue where the tab would reactivate if you clicked the active tab while the withdraw-x dialog was open. This was caused by the handling for withdraw-x, which activates the tab again a tick after the withdraw-x dialog is closed. --- .../net/runelite/client/plugins/banktags/tabs/TabInterface.java | 1 + 1 file changed, 1 insertion(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabInterface.java b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabInterface.java index 8e819250e0..329a539d93 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabInterface.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabInterface.java @@ -406,6 +406,7 @@ public class TabInterface if (tab.equals(activeTab)) { bankSearch.reset(true); + rememberedSearch = ""; clientThread.invokeLater(() -> client.runScript(ScriptID.MESSAGE_LAYER_CLOSE, 0, 0)); } From d434e48d772781270b3b196936b59b26b5c97683 Mon Sep 17 00:00:00 2001 From: Anthony Alves Date: Fri, 22 May 2020 15:48:12 -0400 Subject: [PATCH 09/31] chat-history: add option to clear history for all chatbox tabs (#11543) Signed-off-by: Tomas Slusny Co-authored-by: Tomas Slusny --- .../java/net/runelite/api/ChatLineBuffer.java | 6 +- .../net/runelite/api/widgets/WidgetID.java | 6 + .../net/runelite/api/widgets/WidgetInfo.java | 6 + .../chathistory/ChatHistoryConfig.java | 11 ++ .../chathistory/ChatHistoryPlugin.java | 106 +++++++++++++++--- .../plugins/chathistory/ChatboxTab.java | 94 ++++++++++++++++ 6 files changed, 214 insertions(+), 15 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatboxTab.java diff --git a/runelite-api/src/main/java/net/runelite/api/ChatLineBuffer.java b/runelite-api/src/main/java/net/runelite/api/ChatLineBuffer.java index a1f8a7e056..94e26d6812 100644 --- a/runelite-api/src/main/java/net/runelite/api/ChatLineBuffer.java +++ b/runelite-api/src/main/java/net/runelite/api/ChatLineBuffer.java @@ -46,7 +46,11 @@ public interface ChatLineBuffer int getLength(); /** - * Removes a message node + * Removes a message node. + * + * This method modifies the underlying MessageNode array. If removing multiple MessageNodes at a time, + * clone the original {@link #getLines()} array; as items in the array will get modified and be left in an + * inconsistent state. * * @param node the {@link MessageNode} to remove */ 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 04f22f9312..a88b2e37c0 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 @@ -466,6 +466,12 @@ public class WidgetID { static final int PARENT = 0; static final int BUTTONS = 1; + static final int TAB_ALL = 4; + static final int TAB_GAME = 8; + static final int TAB_PUBLIC = 13; + static final int TAB_PRIVATE = 18; + static final int TAB_CLAN = 23; + static final int TAB_TRADE = 28; static final int REPORT_TEXT = 36; static final int FRAME = 37; static final int TRANSPARENT_BACKGROUND = 38; 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 eea24201ba..aeef3d01bf 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 @@ -365,6 +365,12 @@ public enum WidgetInfo CHATBOX_TRANSPARENT_LINES(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.TRANSPARENT_BACKGROUND_LINES), CHATBOX_MESSAGE_LINES(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.MESSAGE_LINES), CHATBOX_FIRST_MESSAGE(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.FIRST_MESSAGE), + CHATBOX_TAB_ALL(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.TAB_ALL), + CHATBOX_TAB_GAME(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.TAB_GAME), + CHATBOX_TAB_PUBLIC(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.TAB_PUBLIC), + CHATBOX_TAB_PRIVATE(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.TAB_PRIVATE), + CHATBOX_TAB_CLAN(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.TAB_CLAN), + CHATBOX_TAB_TRADE(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.TAB_TRADE), BA_HEAL_WAVE_TEXT(WidgetID.BA_HEALER_GROUP_ID, WidgetID.BarbarianAssault.CURRENT_WAVE), BA_HEAL_CALL_TEXT(WidgetID.BA_HEALER_GROUP_ID, WidgetID.BarbarianAssault.TO_CALL), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatHistoryConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatHistoryConfig.java index cf558c3759..a552d39951 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatHistoryConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatHistoryConfig.java @@ -63,4 +63,15 @@ public interface ChatHistoryConfig extends Config { return true; } + + @ConfigItem( + keyName = "clearHistory", + name = "Clear history option for all tabs", + description = "Add 'Clear history' option chatbox tab buttons", + position = 3 + ) + default boolean clearHistory() + { + return true; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatHistoryPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatHistoryPlugin.java index 7f4db12375..4ed0f21646 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatHistoryPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatHistoryPlugin.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2018, Tomas Slusny + * Copyright (c) 2020, Anthony * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,6 +28,7 @@ package net.runelite.client.plugins.chathistory; import com.google.common.base.Strings; import com.google.common.collect.EvictingQueue; import com.google.inject.Provides; +import java.awt.Color; import java.awt.Toolkit; import java.awt.datatransfer.StringSelection; import java.awt.event.KeyEvent; @@ -35,14 +37,17 @@ import java.util.Deque; import java.util.Iterator; import java.util.Queue; import javax.inject.Inject; +import net.runelite.api.ChatLineBuffer; import net.runelite.api.ChatMessageType; import net.runelite.api.Client; import net.runelite.api.MenuAction; import net.runelite.api.MenuEntry; +import net.runelite.api.MessageNode; import net.runelite.api.ScriptID; import net.runelite.api.VarClientInt; import net.runelite.api.VarClientStr; import net.runelite.api.events.ChatMessage; +import net.runelite.api.events.MenuEntryAdded; import net.runelite.api.events.MenuOpened; import net.runelite.api.events.MenuOptionClicked; import net.runelite.api.vars.InputType; @@ -59,6 +64,7 @@ import net.runelite.client.input.KeyListener; import net.runelite.client.input.KeyManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.util.ColorUtil; import net.runelite.client.util.Text; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; @@ -72,7 +78,6 @@ public class ChatHistoryPlugin extends Plugin implements KeyListener { private static final String WELCOME_MESSAGE = "Welcome to Old School RuneScape"; private static final String CLEAR_HISTORY = "Clear history"; - private static final String CLEAR_PRIVATE = "Private:"; private static final String COPY_TO_CLIPBOARD = "Copy to clipboard"; private static final int CYCLE_HOTKEY = KeyEvent.VK_TAB; private static final int FRIENDS_MAX_SIZE = 5; @@ -102,7 +107,7 @@ public class ChatHistoryPlugin extends Plugin implements KeyListener { return configManager.getConfig(ChatHistoryConfig.class); } - + @Override protected void startUp() { @@ -247,20 +252,11 @@ public class ChatHistoryPlugin extends Plugin implements KeyListener @Subscribe public void onMenuOptionClicked(MenuOptionClicked event) { - String menuOption = event.getMenuOption(); + final String menuOption = event.getMenuOption(); - if (menuOption.contains(CLEAR_HISTORY)) + if (CLEAR_HISTORY.equals(menuOption)) { - if (menuOption.startsWith(CLEAR_PRIVATE)) - { - messageQueue.removeIf(e -> e.getType() == ChatMessageType.PRIVATECHAT || - e.getType() == ChatMessageType.PRIVATECHATOUT || e.getType() == ChatMessageType.MODPRIVATECHAT); - friends.clear(); - } - else - { - messageQueue.removeIf(e -> e.getType() == ChatMessageType.PUBLICCHAT || e.getType() == ChatMessageType.MODCHAT); - } + clearChatboxHistory(ChatboxTab.of(event.getWidgetId())); } else if (COPY_TO_CLIPBOARD.equals(menuOption) && !Strings.isNullOrEmpty(currentMessage)) { @@ -269,6 +265,88 @@ public class ChatHistoryPlugin extends Plugin implements KeyListener } } + @Subscribe + public void onMenuEntryAdded(MenuEntryAdded entry) + { + final String option = Text.removeTags(entry.getOption()); + final ChatboxTab tab = ChatboxTab.of(entry.getActionParam1()); + + if (!config.clearHistory() || tab == null || !option.equals(tab.getAfter())) + { + return; + } + + final MenuEntry clearEntry = new MenuEntry(); + clearEntry.setTarget(""); + clearEntry.setType(MenuAction.RUNELITE.getId()); + clearEntry.setParam0(entry.getActionParam0()); + clearEntry.setParam1(entry.getActionParam1()); + + if (tab == ChatboxTab.GAME) + { + // keep type as the original CC_OP to correctly group "Game: Clear history" with + // other tab "Game: *" options. + clearEntry.setType(entry.getType()); + } + + final StringBuilder messageBuilder = new StringBuilder(); + + if (tab != ChatboxTab.ALL) + { + messageBuilder.append(ColorUtil.wrapWithColorTag(tab.getName() + ": ", Color.YELLOW)); + } + + messageBuilder.append(CLEAR_HISTORY); + clearEntry.setOption(messageBuilder.toString()); + + final MenuEntry[] menuEntries = client.getMenuEntries(); + client.setMenuEntries(ArrayUtils.insert(menuEntries.length - 1, menuEntries, clearEntry)); + } + + private void clearMessageQueue(ChatboxTab tab) + { + if (tab == ChatboxTab.ALL || tab == ChatboxTab.PRIVATE) + { + friends.clear(); + } + + messageQueue.removeIf(e -> tab.getMessageTypes().contains(e.getType())); + } + + private void clearChatboxHistory(ChatboxTab tab) + { + if (tab == null) + { + return; + } + + boolean removed = false; + for (ChatMessageType msgType : tab.getMessageTypes()) + { + final ChatLineBuffer lineBuffer = client.getChatLineMap().get(msgType.getType()); + if (lineBuffer == null) + { + continue; + } + + final MessageNode[] lines = lineBuffer.getLines().clone(); + for (final MessageNode line : lines) + { + if (line != null) + { + lineBuffer.removeMessageNode(line); + removed = true; + } + } + } + + if (removed) + { + clientThread.invoke(() -> client.runScript(ScriptID.BUILD_CHATBOX)); + clearMessageQueue(tab); + } + } + /** * Small hack to prevent plugins checking for specific messages to match * @param message message diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatboxTab.java b/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatboxTab.java new file mode 100644 index 0000000000..9411f08c82 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatboxTab.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2020, Anthony + * 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.chathistory; + +import com.google.common.collect.ImmutableList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.annotation.Nullable; +import lombok.Getter; +import net.runelite.api.ChatMessageType; +import net.runelite.api.widgets.WidgetInfo; + +@Getter +enum ChatboxTab +{ + + ALL("All", "Switch tab", WidgetInfo.CHATBOX_TAB_ALL, + ChatMessageType.values()), + + // null 'after' var since we're not adding to menu + PRIVATE("Private", null, WidgetInfo.CHATBOX_TAB_PRIVATE, + ChatMessageType.PRIVATECHAT, ChatMessageType.PRIVATECHATOUT, ChatMessageType.MODPRIVATECHAT, + ChatMessageType.LOGINLOGOUTNOTIFICATION), + + // null 'after' var since we're not adding to menu + PUBLIC("Public", null, WidgetInfo.CHATBOX_TAB_PUBLIC, + ChatMessageType.PUBLICCHAT, ChatMessageType.AUTOTYPER, ChatMessageType.MODCHAT, ChatMessageType.MODAUTOTYPER), + + GAME("Game", "Game: Filter", WidgetInfo.CHATBOX_TAB_GAME, + ChatMessageType.GAMEMESSAGE, ChatMessageType.ENGINE, ChatMessageType.BROADCAST, + ChatMessageType.SNAPSHOTFEEDBACK, ChatMessageType.ITEM_EXAMINE, ChatMessageType.NPC_EXAMINE, + ChatMessageType.OBJECT_EXAMINE, ChatMessageType.FRIENDNOTIFICATION, ChatMessageType.IGNORENOTIFICATION, + ChatMessageType.CONSOLE, ChatMessageType.SPAM, ChatMessageType.PLAYERRELATED, ChatMessageType.TENSECTIMEOUT, + ChatMessageType.WELCOME, ChatMessageType.UNKNOWN), + + CLAN("Clan", "Clan: Off", WidgetInfo.CHATBOX_TAB_CLAN, + ChatMessageType.FRIENDSCHATNOTIFICATION, ChatMessageType.FRIENDSCHAT, ChatMessageType.CHALREQ_FRIENDSCHAT), + + TRADE("Trade", "Trade: Off", WidgetInfo.CHATBOX_TAB_TRADE, + ChatMessageType.TRADE_SENT, ChatMessageType.TRADEREQ, ChatMessageType.TRADE, ChatMessageType.CHALREQ_TRADE), + ; + + private static final Map TAB_MESSAGE_TYPES = new HashMap<>(); + + @Nullable + private final String after; + private final String name; + private final int widgetId; + private final List messageTypes; + + ChatboxTab(String name, String after, WidgetInfo widgetId, ChatMessageType... messageTypes) + { + this.name = name; + this.after = after; + this.widgetId = widgetId.getId(); + this.messageTypes = ImmutableList.copyOf(messageTypes); + } + + static + { + for (ChatboxTab t : values()) + { + TAB_MESSAGE_TYPES.put(t.widgetId, t); + } + } + + static ChatboxTab of(int widgetId) + { + return TAB_MESSAGE_TYPES.get(widgetId); + } +} From ab22082e387cf2c6853316ab8782cd9db91b2ef7 Mon Sep 17 00:00:00 2001 From: Tim van Rossum Date: Fri, 22 May 2020 21:58:22 +0200 Subject: [PATCH 10/31] boosts: Add option to disable boost threshold notifications (#11668) Co-authored-by: Tomas Slusny --- .../client/plugins/boosts/BoostsConfig.java | 15 +++++++++++++-- .../client/plugins/boosts/BoostsPlugin.java | 2 +- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsConfig.java index a853ea41c3..5c9111bc06 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsConfig.java @@ -103,12 +103,23 @@ public interface BoostsConfig extends Config @ConfigItem( keyName = "boostThreshold", - name = "Boost Amount Threshold", - description = "The amount of levels boosted to send a notification at. A value of 0 will disable notification.", + name = "Boost amount threshold", + description = "The amount of levels boosted to display then in different color. A value of 0 will disable the feature.", position = 6 ) default int boostThreshold() { return 0; } + + @ConfigItem( + keyName = "notifyOnBoost", + name = "Notify on boost threshold", + description = "Configures whether or not a notification will be sent for boosted stats.", + position = 7 + ) + default boolean notifyOnBoost() + { + return true; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsPlugin.java index 891006db43..c9fd49c97b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsPlugin.java @@ -209,7 +209,7 @@ public class BoostsPlugin extends Plugin int boostThreshold = config.boostThreshold(); - if (boostThreshold != 0) + if (boostThreshold != 0 && config.notifyOnBoost()) { int real = client.getRealSkillLevel(skill); int lastBoost = last - real; From 0715e3c9fc380972f1acb3319de453b2fa658d55 Mon Sep 17 00:00:00 2001 From: Corey Forsyth Date: Mon, 11 May 2020 21:26:35 -0400 Subject: [PATCH 11/31] chatfilter: add collapse duplicate chat option Co-authored-by: Adam --- .../plugins/chatfilter/ChatFilterConfig.java | 22 ++++ .../plugins/chatfilter/ChatFilterPlugin.java | 116 +++++++++++++++--- .../chatfilter/ChatFilterPluginTest.java | 46 +++++++ 3 files changed, 164 insertions(+), 20 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatfilter/ChatFilterConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatfilter/ChatFilterConfig.java index 253afd7e18..d5592318b6 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chatfilter/ChatFilterConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatfilter/ChatFilterConfig.java @@ -108,4 +108,26 @@ public interface ChatFilterConfig extends Config { return false; } + + @ConfigItem( + keyName = "collapseGameChat", + name = "Collapse Game Chat", + description = "Collapse duplicate game chat messages into a single line", + position = 9 + ) + default boolean collapseGameChat() + { + return false; + } + + @ConfigItem( + keyName = "collapsePlayerChat", + name = "Collapse Player Chat", + description = "Collapse duplicate player chat messages into a single line", + position = 10 + ) + default boolean collapsePlayerChat() + { + return false; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatfilter/ChatFilterPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatfilter/ChatFilterPlugin.java index 67561b0833..ee74245a59 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chatfilter/ChatFilterPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatfilter/ChatFilterPlugin.java @@ -28,23 +28,36 @@ package net.runelite.client.plugins.chatfilter; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.CharMatcher; import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableSet; import com.google.inject.Provides; import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import javax.inject.Inject; import net.runelite.api.ChatMessageType; +import static net.runelite.api.ChatMessageType.ENGINE; +import static net.runelite.api.ChatMessageType.GAMEMESSAGE; +import static net.runelite.api.ChatMessageType.ITEM_EXAMINE; +import static net.runelite.api.ChatMessageType.MODCHAT; +import static net.runelite.api.ChatMessageType.NPC_EXAMINE; +import static net.runelite.api.ChatMessageType.OBJECT_EXAMINE; +import static net.runelite.api.ChatMessageType.PUBLICCHAT; +import static net.runelite.api.ChatMessageType.SPAM; import net.runelite.api.Client; import net.runelite.api.MessageNode; import net.runelite.api.Player; -import net.runelite.client.events.ConfigChanged; +import net.runelite.api.events.ChatMessage; import net.runelite.api.events.OverheadTextChanged; import net.runelite.api.events.ScriptCallbackEvent; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.events.ConfigChanged; import net.runelite.client.game.ClanManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; @@ -66,10 +79,38 @@ public class ChatFilterPlugin extends Plugin @VisibleForTesting static final String CENSOR_MESSAGE = "Hey, everyone, I just tried to say something very silly!"; + private static final Set COLLAPSIBLE_MESSAGETYPES = ImmutableSet.of( + ENGINE, + GAMEMESSAGE, + ITEM_EXAMINE, + NPC_EXAMINE, + OBJECT_EXAMINE, + SPAM, + PUBLICCHAT, + MODCHAT + ); + private final CharMatcher jagexPrintableCharMatcher = Text.JAGEX_PRINTABLE_CHAR_MATCHER; private final List filteredPatterns = new ArrayList<>(); private final List filteredNamePatterns = new ArrayList<>(); + private static class Duplicate + { + int messageId; + int count; + } + + private final LinkedHashMap duplicateChatCache = new LinkedHashMap() + { + private static final int MAX_ENTRIES = 100; + + @Override + protected boolean removeEldestEntry(Map.Entry eldest) + { + return size() > MAX_ENTRIES; + } + }; + @Inject private Client client; @@ -96,6 +137,7 @@ public class ChatFilterPlugin extends Plugin protected void shutDown() throws Exception { filteredPatterns.clear(); + duplicateChatCache.clear(); client.refreshChat(); } @@ -109,10 +151,18 @@ public class ChatFilterPlugin extends Plugin int[] intStack = client.getIntStack(); int intStackSize = client.getIntStackSize(); - int messageType = intStack[intStackSize - 2]; - int messageId = intStack[intStackSize - 1]; + String[] stringStack = client.getStringStack(); + int stringStackSize = client.getStringStackSize(); + + final int messageType = intStack[intStackSize - 2]; + final int messageId = intStack[intStackSize - 1]; + String message = stringStack[stringStackSize - 1]; ChatMessageType chatMessageType = ChatMessageType.of(messageType); + final MessageNode messageNode = client.getMessages().get(messageId); + final String name = messageNode.getName(); + int duplicateCount = 0; + boolean blockMessage = false; // Only filter public chat and private messages switch (chatMessageType) @@ -123,32 +173,34 @@ public class ChatFilterPlugin extends Plugin case PRIVATECHAT: case MODPRIVATECHAT: case FRIENDSCHAT: + if (shouldFilterPlayerMessage(name)) + { + message = censorMessage(name, message); + blockMessage = message == null; + } break; case LOGINLOGOUTNOTIFICATION: if (config.filterLogin()) { - // Block the message - intStack[intStackSize - 3] = 0; + blockMessage = true; } - return; - default: - return; + break; } - MessageNode messageNode = client.getMessages().get(messageId); - String name = messageNode.getName(); - if (!shouldFilterPlayerMessage(name)) + boolean shouldCollapse = chatMessageType == PUBLICCHAT || chatMessageType == MODCHAT + ? config.collapsePlayerChat() + : COLLAPSIBLE_MESSAGETYPES.contains(chatMessageType) && config.collapseGameChat(); + if (!blockMessage && shouldCollapse) { - return; + Duplicate duplicateCacheEntry = duplicateChatCache.get(name + ":" + message); + if (duplicateCacheEntry != null) + { + blockMessage = duplicateCacheEntry.messageId != messageId; + duplicateCount = duplicateCacheEntry.count; + } } - String[] stringStack = client.getStringStack(); - int stringStackSize = client.getStringStackSize(); - - String message = stringStack[stringStackSize - 1]; - String censoredMessage = censorMessage(name, message); - - if (censoredMessage == null) + if (blockMessage) { // Block the message intStack[intStackSize - 3] = 0; @@ -156,7 +208,12 @@ public class ChatFilterPlugin extends Plugin else { // Replace the message - stringStack[stringStackSize - 1] = censoredMessage; + if (duplicateCount > 1) + { + message += " (" + duplicateCount + ")"; + } + + stringStack[stringStackSize - 1] = message; } } @@ -178,6 +235,25 @@ public class ChatFilterPlugin extends Plugin event.getActor().setOverheadText(message); } + @Subscribe + public void onChatMessage(ChatMessage chatMessage) + { + if (COLLAPSIBLE_MESSAGETYPES.contains(chatMessage.getType())) + { + // remove and re-insert into map to move to end of list + final String key = chatMessage.getName() + ":" + chatMessage.getMessage(); + Duplicate duplicate = duplicateChatCache.remove(key); + if (duplicate == null) + { + duplicate = new Duplicate(); + } + + duplicate.count++; + duplicate.messageId = chatMessage.getMessageNode().getId(); + duplicateChatCache.put(key, duplicate); + } + } + boolean shouldFilterPlayerMessage(String playerName) { boolean isMessageFromSelf = playerName.equals(client.getLocalPlayer().getName()); diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/chatfilter/ChatFilterPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/chatfilter/ChatFilterPluginTest.java index dfa8a08712..3964273a92 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/chatfilter/ChatFilterPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/chatfilter/ChatFilterPluginTest.java @@ -34,6 +34,7 @@ import net.runelite.api.Client; import net.runelite.api.IterableHashTable; import net.runelite.api.MessageNode; import net.runelite.api.Player; +import net.runelite.api.events.ChatMessage; import net.runelite.api.events.ScriptCallbackEvent; import net.runelite.client.game.ClanManager; import static net.runelite.client.plugins.chatfilter.ChatFilterPlugin.CENSOR_MESSAGE; @@ -108,6 +109,13 @@ public class ChatFilterPluginTest return node; } + private MessageNode mockMessageNode(int id) + { + MessageNode node = mock(MessageNode.class); + when(node.getId()).thenReturn(id); + return node; + } + @Test public void testCensorWords() { @@ -322,4 +330,42 @@ public class ChatFilterPluginTest chatFilterPlugin.onScriptCallbackEvent(event); assertEquals(CENSOR_MESSAGE, client.getStringStack()[client.getStringStackSize() - 1]); } + + @Test + public void testDuplicateChatFiltered() + { + when(chatFilterConfig.collapseGameChat()).thenReturn(true); + chatFilterPlugin.onChatMessage(new ChatMessage(mockMessageNode(0), ChatMessageType.GAMEMESSAGE, null, "testMessage", null, 0)); + ScriptCallbackEvent event = createCallbackEvent(null, "testMessage", ChatMessageType.GAMEMESSAGE); + chatFilterPlugin.onScriptCallbackEvent(event); + + assertEquals(0, client.getIntStack()[client.getIntStackSize() - 3]); + } + + @Test + public void testNoDuplicate() + { + when(chatFilterConfig.collapseGameChat()).thenReturn(true); + chatFilterPlugin.onChatMessage(new ChatMessage(mockMessageNode(1), ChatMessageType.GAMEMESSAGE, null, "testMessage", null, 0)); + ScriptCallbackEvent event = createCallbackEvent(null, "testMessage", ChatMessageType.GAMEMESSAGE); + chatFilterPlugin.onScriptCallbackEvent(event); + + assertEquals(1, client.getIntStack()[client.getIntStackSize() - 3]); + assertEquals("testMessage", client.getStringStack()[client.getStringStackSize() - 1]); + } + + @Test + public void testDuplicateChatCount() + { + when(chatFilterConfig.collapseGameChat()).thenReturn(true); + chatFilterPlugin.onChatMessage(new ChatMessage(mockMessageNode(4), ChatMessageType.GAMEMESSAGE, null, "testMessage", null, 0)); + chatFilterPlugin.onChatMessage(new ChatMessage(mockMessageNode(3), ChatMessageType.GAMEMESSAGE, null, "testMessage", null, 0)); + chatFilterPlugin.onChatMessage(new ChatMessage(mockMessageNode(2), ChatMessageType.GAMEMESSAGE, null, "testMessage", null, 0)); + chatFilterPlugin.onChatMessage(new ChatMessage(mockMessageNode(1), ChatMessageType.GAMEMESSAGE, null, "testMessage", null, 0)); + ScriptCallbackEvent event = createCallbackEvent(null, "testMessage", ChatMessageType.GAMEMESSAGE); + chatFilterPlugin.onScriptCallbackEvent(event); + + assertEquals(1, client.getIntStack()[client.getIntStackSize() - 3]); + assertEquals("testMessage (4)", client.getStringStack()[client.getStringStackSize() - 1]); + } } \ No newline at end of file From f85f6be5cf6d97b0bc053ad50915496d7a78eef2 Mon Sep 17 00:00:00 2001 From: Corey Forsyth Date: Fri, 22 May 2020 14:44:36 -0400 Subject: [PATCH 12/31] chatfilter: add option to block repeated public messages Co-authored-by: Adam --- .../plugins/chatfilter/ChatFilterConfig.java | 11 +++++++++++ .../plugins/chatfilter/ChatFilterPlugin.java | 4 +++- .../plugins/chatfilter/ChatFilterPluginTest.java | 14 ++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatfilter/ChatFilterConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatfilter/ChatFilterConfig.java index d5592318b6..86eff01756 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chatfilter/ChatFilterConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatfilter/ChatFilterConfig.java @@ -130,4 +130,15 @@ public interface ChatFilterConfig extends Config { return false; } + + @ConfigItem( + keyName = "maxRepeatedPublicChats", + name = "Max repeated public chats", + description = "Block player chat message if repeated this many times. 0 is off", + position = 11 + ) + default int maxRepeatedPublicChats() + { + return 0; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatfilter/ChatFilterPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatfilter/ChatFilterPlugin.java index ee74245a59..607d50d3f9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chatfilter/ChatFilterPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatfilter/ChatFilterPlugin.java @@ -195,7 +195,9 @@ public class ChatFilterPlugin extends Plugin Duplicate duplicateCacheEntry = duplicateChatCache.get(name + ":" + message); if (duplicateCacheEntry != null) { - blockMessage = duplicateCacheEntry.messageId != messageId; + blockMessage = duplicateCacheEntry.messageId != messageId || + ((chatMessageType == PUBLICCHAT || chatMessageType == MODCHAT) && + config.maxRepeatedPublicChats() > 0 && duplicateCacheEntry.count > config.maxRepeatedPublicChats()); duplicateCount = duplicateCacheEntry.count; } } diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/chatfilter/ChatFilterPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/chatfilter/ChatFilterPluginTest.java index 3964273a92..de4c104e3d 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/chatfilter/ChatFilterPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/chatfilter/ChatFilterPluginTest.java @@ -368,4 +368,18 @@ public class ChatFilterPluginTest assertEquals(1, client.getIntStack()[client.getIntStackSize() - 3]); assertEquals("testMessage (4)", client.getStringStack()[client.getStringStackSize() - 1]); } + + @Test + public void publicChatFilteredOnDuplicate() + { + when(chatFilterConfig.collapsePlayerChat()).thenReturn(true); + when(chatFilterConfig.maxRepeatedPublicChats()).thenReturn(2); + chatFilterPlugin.onChatMessage(new ChatMessage(mockMessageNode(1), ChatMessageType.PUBLICCHAT, "testName", "testMessage", null, 0)); + chatFilterPlugin.onChatMessage(new ChatMessage(mockMessageNode(1), ChatMessageType.PUBLICCHAT, "testName", "testMessage", null, 0)); + chatFilterPlugin.onChatMessage(new ChatMessage(mockMessageNode(1), ChatMessageType.PUBLICCHAT, "testName", "testMessage", null, 0)); + ScriptCallbackEvent event = createCallbackEvent("testName", "testMessage", ChatMessageType.PUBLICCHAT); + chatFilterPlugin.onScriptCallbackEvent(event); + + assertEquals(0, client.getIntStack()[client.getIntStackSize() - 3]); + } } \ No newline at end of file From eae4e0b6a06618aec9f9df5d4be8bdadddd26f53 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 23 May 2020 13:23:37 -0400 Subject: [PATCH 13/31] wintertodt plugin: add option to disable overlay Co-authored-by: Jonathan Taylor Co-authored-by: Pharros --- .../client/plugins/wintertodt/WintertodtConfig.java | 11 +++++++++++ .../client/plugins/wintertodt/WintertodtOverlay.java | 6 ++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/wintertodt/WintertodtConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/wintertodt/WintertodtConfig.java index 907d1c6d95..407d9018aa 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/wintertodt/WintertodtConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/wintertodt/WintertodtConfig.java @@ -37,6 +37,17 @@ import net.runelite.client.plugins.wintertodt.config.WintertodtNotifyDamage; @ConfigGroup("wintertodt") public interface WintertodtConfig extends Config { + @ConfigItem( + position = 0, + keyName = "showOverlay", + name = "Show Overlay", + description = "Toggles the status overlay" + ) + default boolean showOverlay() + { + return true; + } + @ConfigItem( position = 1, keyName = "damageNotificationColor", diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/wintertodt/WintertodtOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/wintertodt/WintertodtOverlay.java index 4388f4fa1a..48a8c0d93a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/wintertodt/WintertodtOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/wintertodt/WintertodtOverlay.java @@ -40,12 +40,14 @@ import net.runelite.client.ui.overlay.components.TitleComponent; class WintertodtOverlay extends OverlayPanel { private final WintertodtPlugin plugin; + private final WintertodtConfig wintertodtConfig; @Inject - private WintertodtOverlay(WintertodtPlugin plugin) + private WintertodtOverlay(WintertodtPlugin plugin, WintertodtConfig wintertodtConfig) { super(plugin); this.plugin = plugin; + this.wintertodtConfig = wintertodtConfig; setPosition(OverlayPosition.BOTTOM_LEFT); getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Wintertodt overlay")); } @@ -53,7 +55,7 @@ class WintertodtOverlay extends OverlayPanel @Override public Dimension render(Graphics2D graphics) { - if (!plugin.isInWintertodt()) + if (!plugin.isInWintertodt() || !wintertodtConfig.showOverlay()) { return null; } From 116e1a0090ec5478ee2746f56e10d672e6e8e158 Mon Sep 17 00:00:00 2001 From: Jordan Atwood Date: Thu, 7 May 2020 18:56:46 -0700 Subject: [PATCH 14/31] loot tracker: Use "an" prefix for monster names starting with vowels --- .../client/plugins/loottracker/LootTrackerPlugin.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java index b5b8070b0c..b05dd21a40 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java @@ -167,6 +167,8 @@ public class LootTrackerPlugin extends Plugin "H.A.M. Member", "Woman" ); + private static final Set VOWELS = ImmutableSet.of('a', 'e', 'i', 'o', 'u'); + @Inject private ClientToolbar clientToolbar; @@ -403,7 +405,11 @@ public class LootTrackerPlugin extends Plugin if (config.npcKillChatMessage()) { - lootReceivedChatMessage(items, "a " + name); + final String prefix = VOWELS.contains(Character.toLowerCase(name.charAt(0))) + ? "an" + : "a"; + + lootReceivedChatMessage(items, prefix + ' ' + name); } } From 73d928ea8928d9384656d99714b7761239fed505 Mon Sep 17 00:00:00 2001 From: Hydrox6 Date: Fri, 8 May 2020 22:07:03 +0100 Subject: [PATCH 15/31] gpu: add warning message to compute shaders option --- .../java/net/runelite/client/plugins/gpu/GpuPluginConfig.java | 1 + 1 file changed, 1 insertion(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPluginConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPluginConfig.java index 29396dfb11..d804624976 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPluginConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPluginConfig.java @@ -101,6 +101,7 @@ public interface GpuPluginConfig extends Config keyName = "useComputeShaders", name = "Compute Shaders", description = "Offloads face sorting to GPU, enabling extended draw distance. Requires plugin restart.", + warning = "This feature requires OpenGL 4.3 to use. Please check that your GPU supports this.\nRestart the plugin for changes to take effect.", position = 6 ) default boolean useComputeShaders() From 39a2407b71f3ad1b888e923e17babfcfae831641 Mon Sep 17 00:00:00 2001 From: Jordan Atwood Date: Sat, 9 May 2020 21:16:32 -0700 Subject: [PATCH 16/31] examine: Move price lookups off executor Historically price lookup was done by sending a web request on price lookups, which required calls to be done on an executor. As of a1ae397e11, client prices are loaded periodically and cached, thus no longer imposing any thread requirement on price lookup. --- .../net/runelite/client/plugins/examine/ExaminePlugin.java | 6 +----- .../runelite/client/plugins/examine/ExaminePluginTest.java | 5 ----- 2 files changed, 1 insertion(+), 10 deletions(-) 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 d414d6fba0..aafba1f4c1 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 @@ -29,7 +29,6 @@ import com.google.common.cache.CacheBuilder; import java.time.Instant; import java.util.ArrayDeque; import java.util.Deque; -import java.util.concurrent.ScheduledExecutorService; import java.util.regex.Pattern; import javax.inject.Inject; import lombok.extern.slf4j.Slf4j; @@ -92,9 +91,6 @@ public class ExaminePlugin extends Plugin @Inject private ChatMessageManager chatMessageManager; - @Inject - private ScheduledExecutorService executor; - @Subscribe public void onGameStateChanged(GameStateChanged event) { @@ -219,7 +215,7 @@ public class ExaminePlugin extends Plugin if (itemComposition != null) { final int id = itemManager.canonicalize(itemComposition.getId()); - executor.submit(() -> getItemPrice(id, itemComposition, itemQuantity)); + getItemPrice(id, itemComposition, itemQuantity); } } else diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/examine/ExaminePluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/examine/ExaminePluginTest.java index dccf97258a..312543cf94 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/examine/ExaminePluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/examine/ExaminePluginTest.java @@ -27,7 +27,6 @@ package net.runelite.client.plugins.examine; import com.google.inject.Guice; import com.google.inject.testing.fieldbinder.Bind; import com.google.inject.testing.fieldbinder.BoundFieldModule; -import java.util.concurrent.ScheduledExecutorService; import javax.inject.Inject; import net.runelite.api.ChatMessageType; import net.runelite.api.Client; @@ -73,10 +72,6 @@ public class ExaminePluginTest @Bind ItemManager itemManager; - @Mock - @Bind - ScheduledExecutorService scheduledExecutorService; - @Before public void before() { From f9d3647db1a6c8b715d50d39a5141b006f5f3840 Mon Sep 17 00:00:00 2001 From: Jordan Atwood Date: Sat, 9 May 2020 22:47:29 -0700 Subject: [PATCH 17/31] itemmanager: Canonicalize price lookup item IDs --- .../java/net/runelite/client/game/ItemManager.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/game/ItemManager.java b/runelite-client/src/main/java/net/runelite/client/game/ItemManager.java index 58415a17c2..cb9cf32afd 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/ItemManager.java +++ b/runelite-client/src/main/java/net/runelite/client/game/ItemManager.java @@ -290,18 +290,20 @@ public class ItemManager */ public int getItemPrice(int itemID, boolean ignoreUntradeableMap) { - if (itemID == ItemID.COINS_995) + final int realId = canonicalize(itemID); + + if (realId == ItemID.COINS_995) { return 1; } - if (itemID == ItemID.PLATINUM_TOKEN) + if (realId == ItemID.PLATINUM_TOKEN) { return 1000; } if (!ignoreUntradeableMap) { - UntradeableItemMapping p = UntradeableItemMapping.map(ItemVariationMapping.map(itemID)); + UntradeableItemMapping p = UntradeableItemMapping.map(ItemVariationMapping.map(realId)); if (p != null) { return getItemPrice(p.getPriceID()) * p.getQuantity(); @@ -309,7 +311,7 @@ public class ItemManager } int price = 0; - for (int mappedID : ItemMapping.map(itemID)) + for (int mappedID : ItemMapping.map(realId)) { ItemPrice ip = itemPrices.get(mappedID); if (ip != null) From c2a9ac443b66f67fa0d1b9f9231888e2ea6b4732 Mon Sep 17 00:00:00 2001 From: Jordan Atwood Date: Sat, 9 May 2020 22:53:28 -0700 Subject: [PATCH 18/31] client: Simplify ItemContainer usage Because itemManager#getItemPrice() canonicalizes the passed item ID, it is no longer necessary to get noted items' base IDs or otherwise canonicalize item IDs before interacting with the method. --- .../net/runelite/client/plugins/examine/ExaminePlugin.java | 7 +------ .../client/plugins/itemprices/ItemPricesOverlay.java | 7 +------ .../client/plugins/loottracker/LootTrackerPlugin.java | 3 +-- .../runelite/client/plugins/examine/ExaminePluginTest.java | 3 +++ 4 files changed, 6 insertions(+), 14 deletions(-) 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 aafba1f4c1..5611ea656e 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 @@ -211,12 +211,7 @@ public class ExaminePlugin extends Plugin } itemComposition = itemManager.getItemComposition(itemId); - - if (itemComposition != null) - { - final int id = itemManager.canonicalize(itemComposition.getId()); - getItemPrice(id, itemComposition, itemQuantity); - } + getItemPrice(itemComposition.getId(), itemComposition, itemQuantity); } else { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemprices/ItemPricesOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemprices/ItemPricesOverlay.java index a972ae1f6e..0203578378 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemprices/ItemPricesOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemprices/ItemPricesOverlay.java @@ -188,7 +188,7 @@ class ItemPricesOverlay extends Overlay private String getItemStackValueText(Item item) { - int id = item.getId(); + int id = itemManager.canonicalize(item.getId()); int qty = item.getQuantity(); // Special case for coins and platinum tokens @@ -202,11 +202,6 @@ class ItemPricesOverlay extends Overlay } ItemComposition itemDef = itemManager.getItemComposition(id); - if (itemDef.getNote() != -1) - { - id = itemDef.getLinkedNoteId(); - itemDef = itemManager.getItemComposition(id); - } // Only check prices for things with store prices if (itemDef.getPrice() <= 0) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java index b05dd21a40..dd776e32a3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java @@ -801,8 +801,7 @@ public class LootTrackerPlugin extends Plugin private LootTrackerItem buildLootTrackerItem(int itemId, int quantity) { final ItemComposition itemComposition = itemManager.getItemComposition(itemId); - final int realItemId = itemComposition.getNote() != -1 ? itemComposition.getLinkedNoteId() : itemId; - final int gePrice = itemManager.getItemPrice(realItemId); + final int gePrice = itemManager.getItemPrice(itemId); final int haPrice = Math.round(itemComposition.getPrice() * Constants.HIGH_ALCHEMY_MULTIPLIER); final boolean ignored = ignoredItems.contains(itemComposition.getName()); diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/examine/ExaminePluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/examine/ExaminePluginTest.java index 312543cf94..093beec4f9 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/examine/ExaminePluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/examine/ExaminePluginTest.java @@ -30,6 +30,7 @@ import com.google.inject.testing.fieldbinder.BoundFieldModule; import javax.inject.Inject; import net.runelite.api.ChatMessageType; import net.runelite.api.Client; +import net.runelite.api.ItemComposition; import net.runelite.api.ItemID; import net.runelite.api.MenuAction; import net.runelite.api.events.ChatMessage; @@ -82,6 +83,7 @@ public class ExaminePluginTest public void testItem() { when(client.getWidget(anyInt(), anyInt())).thenReturn(mock(Widget.class)); + when(itemManager.getItemComposition(anyInt())).thenReturn(mock(ItemComposition.class)); MenuOptionClicked menuOptionClicked = new MenuOptionClicked(); menuOptionClicked.setMenuOption("Examine"); @@ -100,6 +102,7 @@ public class ExaminePluginTest public void testLargeStacks() { when(client.getWidget(anyInt(), anyInt())).thenReturn(mock(Widget.class)); + when(itemManager.getItemComposition(anyInt())).thenReturn(mock(ItemComposition.class)); MenuOptionClicked menuOptionClicked = new MenuOptionClicked(); menuOptionClicked.setMenuOption("Examine"); From e9aac02a43f2e21f1736bce491062f0d264790ed Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 23 May 2020 20:10:57 -0400 Subject: [PATCH 19/31] keyremapping: use modified key map for mapping key release This cleans up the code some and is more-correct since it will eg. no longer remap fkeys on keyrelease even when it was not remapped on keypress. --- .../keyremapping/KeyRemappingListener.java | 110 ++---------------- .../KeyRemappingListenerTest.java | 2 +- 2 files changed, 8 insertions(+), 104 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/keyremapping/KeyRemappingListener.java b/runelite-client/src/main/java/net/runelite/client/plugins/keyremapping/KeyRemappingListener.java index 3c7ce4be79..472e009e1b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/keyremapping/KeyRemappingListener.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/keyremapping/KeyRemappingListener.java @@ -156,7 +156,7 @@ class KeyRemappingListener implements KeyListener } } - if (mappedKeyCode != KeyEvent.VK_UNDEFINED) + if (mappedKeyCode != KeyEvent.VK_UNDEFINED && mappedKeyCode != e.getKeyCode()) { final char keyChar = e.getKeyChar(); modified.put(e.getKeyCode(), mappedKeyCode); @@ -217,115 +217,19 @@ class KeyRemappingListener implements KeyListener @Override public void keyReleased(KeyEvent e) { + final int keyCode = e.getKeyCode(); final char keyChar = e.getKeyChar(); + if (keyChar != KeyEvent.CHAR_UNDEFINED) { blockedChars.remove(keyChar); } - if (client.getGameState() == GameState.LOGIN_SCREEN) + final Integer mappedKeyCode = modified.remove(keyCode); + if (mappedKeyCode != null) { - return; - } - - if (plugin.chatboxFocused() && !plugin.isTyping()) - { - modified.remove(e.getKeyCode()); - - int mappedKeyCode = KeyEvent.VK_UNDEFINED; - - if (config.cameraRemap()) - { - if (config.up().matches(e)) - { - mappedKeyCode = KeyEvent.VK_UP; - } - else if (config.down().matches(e)) - { - mappedKeyCode = KeyEvent.VK_DOWN; - } - else if (config.left().matches(e)) - { - mappedKeyCode = KeyEvent.VK_LEFT; - } - else if (config.right().matches(e)) - { - mappedKeyCode = KeyEvent.VK_RIGHT; - } - } - - if (config.fkeyRemap()) - { - if (config.f1().matches(e)) - { - mappedKeyCode = KeyEvent.VK_F1; - } - else if (config.f2().matches(e)) - { - mappedKeyCode = KeyEvent.VK_F2; - } - else if (config.f3().matches(e)) - { - mappedKeyCode = KeyEvent.VK_F3; - } - else if (config.f4().matches(e)) - { - mappedKeyCode = KeyEvent.VK_F4; - } - else if (config.f5().matches(e)) - { - mappedKeyCode = KeyEvent.VK_F5; - } - else if (config.f6().matches(e)) - { - mappedKeyCode = KeyEvent.VK_F6; - } - else if (config.f7().matches(e)) - { - mappedKeyCode = KeyEvent.VK_F7; - } - else if (config.f8().matches(e)) - { - mappedKeyCode = KeyEvent.VK_F8; - } - else if (config.f9().matches(e)) - { - mappedKeyCode = KeyEvent.VK_F9; - } - else if (config.f10().matches(e)) - { - mappedKeyCode = KeyEvent.VK_F10; - } - else if (config.f11().matches(e)) - { - mappedKeyCode = KeyEvent.VK_F11; - } - else if (config.f12().matches(e)) - { - mappedKeyCode = KeyEvent.VK_F12; - } - else if (config.esc().matches(e)) - { - mappedKeyCode = KeyEvent.VK_ESCAPE; - } - } - - if (mappedKeyCode != KeyEvent.VK_UNDEFINED) - { - e.setKeyCode(mappedKeyCode); - e.setKeyChar(KeyEvent.CHAR_UNDEFINED); - } - } - else - { - // press d + enter + release d - causes the right arrow to never be released - Integer m = modified.get(e.getKeyCode()); - if (m != null) - { - modified.remove(e.getKeyCode()); - e.setKeyCode(m); - e.setKeyChar(KeyEvent.CHAR_UNDEFINED); - } + e.setKeyCode(mappedKeyCode); + e.setKeyChar(KeyEvent.CHAR_UNDEFINED); } } } diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/keyremapping/KeyRemappingListenerTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/keyremapping/KeyRemappingListenerTest.java index 036f53e303..cbaefc875f 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/keyremapping/KeyRemappingListenerTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/keyremapping/KeyRemappingListenerTest.java @@ -99,9 +99,9 @@ public class KeyRemappingListenerTest verify(event).consume(); + lenient().when(keyRemappingPlugin.isTyping()).thenReturn(true); // release handler no longer checks this // with the plugin now in typing mode, previously pressed and remapped keys should still be mapped // on key release regardless - when(keyRemappingPlugin.isTyping()).thenReturn(true); event = mock(KeyEvent.class); when(event.getKeyCode()).thenReturn(KeyEvent.VK_D); keyRemappingListener.keyReleased(event); From 0168bf042257960785d1731f6d32f4c43cdf43be Mon Sep 17 00:00:00 2001 From: Vidyogamasta Date: Sun, 24 May 2020 10:41:26 -0500 Subject: [PATCH 20/31] loot tracker: float group to top of list when obtaining drop --- .../client/plugins/loottracker/LootTrackerPanel.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPanel.java index 015749793e..596ca1ff2c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPanel.java @@ -502,6 +502,14 @@ class LootTrackerPanel extends PluginPanel { if (box.matches(record)) { + // float the matched box to the top of the UI list if it's not already first + int idx = logsContainer.getComponentZOrder(box); + if (idx > 0) + { + logsContainer.remove(idx); + logsContainer.add(box, 0); + } + box.addKill(record); return box; } From cb1fc598ba784543fece8f05ebab47f71b69b27f Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 24 May 2020 14:07:03 -0400 Subject: [PATCH 21/31] plugins: add Plugin::getName This avoids the infobox manager from having to access plugin descriptor annotations, making it easier to write tests for --- .../src/main/java/net/runelite/client/plugins/Plugin.java | 5 +++++ .../net/runelite/client/plugins/config/ConfigPlugin.java | 3 +-- .../runelite/client/ui/overlay/infobox/InfoBoxManager.java | 5 ++--- 3 files changed, 8 insertions(+), 5 deletions(-) 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 2dbdf009d2..a36a1f40e6 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 @@ -53,4 +53,9 @@ public abstract class Plugin implements Module { return injector; } + + public String getName() + { + return getClass().getAnnotation(PluginDescriptor.class).name(); + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPlugin.java index 4e4b1fce9b..ac93dcf96b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPlugin.java @@ -115,14 +115,13 @@ public class ConfigPlugin extends Plugin } // Expand config panel for plugin - PluginDescriptor descriptor = plugin.getClass().getAnnotation(PluginDescriptor.class); SwingUtilities.invokeLater(() -> { if (!navButton.isSelected()) { navButton.getOnSelect().run(); } - pluginListPanel.openConfigurationPanel(descriptor.name()); + pluginListPanel.openConfigurationPanel(plugin.getName()); }); } } diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxManager.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxManager.java index 8d75ec5bc9..4d51e6af93 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxManager.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxManager.java @@ -36,11 +36,10 @@ import java.util.function.Predicate; import javax.inject.Inject; import javax.inject.Singleton; import lombok.extern.slf4j.Slf4j; -import net.runelite.client.events.ConfigChanged; import net.runelite.client.config.RuneLiteConfig; import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.events.ConfigChanged; import net.runelite.client.util.AsyncBufferedImage; -import net.runelite.client.plugins.PluginDescriptor; @Singleton @Slf4j @@ -168,7 +167,7 @@ public class InfoBoxManager infoBoxes.sort((b1, b2) -> ComparisonChain .start() .compare(b1.getPriority(), b2.getPriority()) - .compare(b1.getPlugin().getClass().getAnnotation(PluginDescriptor.class).name(), b2.getPlugin().getClass().getAnnotation(PluginDescriptor.class).name()) + .compare(b1.getPlugin().getName(), b2.getPlugin().getName()) .result()); } } From ba9ffb1d600d314100a128db503d10b97a6cbef5 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 24 May 2020 15:22:25 -0400 Subject: [PATCH 22/31] infobox manager: make threadsafe Currently this gets called from multiple threads, mostly client and EDT, causing unsafe acces to infoBoxes. --- .../client/ui/overlay/infobox/InfoBox.java | 4 +- .../ui/overlay/infobox/InfoBoxManager.java | 55 ++++------- .../overlay/infobox/InfoBoxManagerTest.java | 92 +++++++++++++++++++ 3 files changed, 114 insertions(+), 37 deletions(-) create mode 100644 runelite-client/src/test/java/net/runelite/client/ui/overlay/infobox/InfoBoxManagerTest.java diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBox.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBox.java index fab945c11b..777bb9d634 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBox.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBox.java @@ -26,6 +26,7 @@ package net.runelite.client.ui.overlay.infobox; import java.awt.Color; import java.awt.image.BufferedImage; +import javax.annotation.Nonnull; import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; @@ -33,6 +34,7 @@ import net.runelite.client.plugins.Plugin; public abstract class InfoBox { + @Nonnull @Getter(AccessLevel.PACKAGE) private final Plugin plugin; @@ -52,7 +54,7 @@ public abstract class InfoBox @Setter private String tooltip; - public InfoBox(BufferedImage image, Plugin plugin) + public InfoBox(BufferedImage image, @Nonnull Plugin plugin) { this.plugin = plugin; setImage(image); diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxManager.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxManager.java index 4d51e6af93..b634800ea4 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxManager.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxManager.java @@ -28,10 +28,9 @@ import com.google.common.base.Preconditions; import com.google.common.collect.ComparisonChain; import java.awt.Graphics; import java.awt.image.BufferedImage; -import java.util.ArrayList; import java.util.Collections; -import java.util.Iterator; import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.function.Predicate; import javax.inject.Inject; import javax.inject.Singleton; @@ -45,7 +44,7 @@ import net.runelite.client.util.AsyncBufferedImage; @Slf4j public class InfoBoxManager { - private final List infoBoxes = new ArrayList<>(); + private final List infoBoxes = new CopyOnWriteArrayList<>(); private final RuneLiteConfig runeLiteConfig; @Inject @@ -69,8 +68,19 @@ public class InfoBoxManager log.debug("Adding InfoBox {}", infoBox); updateInfoBoxImage(infoBox); - infoBoxes.add(infoBox); - refreshInfoBoxes(); + + synchronized (this) + { + int idx = Collections.binarySearch(infoBoxes, infoBox, (b1, b2) -> ComparisonChain + .start() + .compare(b1.getPriority(), b2.getPriority()) + .compare(b1.getPlugin().getName(), b2.getPlugin().getName()) + .result()); + if (idx < 0) + { + infoBoxes.add(-idx - 1, infoBox); + } + } BufferedImage image = infoBox.getImage(); @@ -81,21 +91,19 @@ public class InfoBoxManager } } - public void removeInfoBox(InfoBox infoBox) + public synchronized void removeInfoBox(InfoBox infoBox) { if (infoBoxes.remove(infoBox)) { log.debug("Removed InfoBox {}", infoBox); - refreshInfoBoxes(); } } - public void removeIf(Predicate filter) + public synchronized void removeIf(Predicate filter) { if (infoBoxes.removeIf(filter)) { log.debug("Removed InfoBoxes for filter {}", filter); - refreshInfoBoxes(); } } @@ -104,25 +112,9 @@ public class InfoBoxManager return Collections.unmodifiableList(infoBoxes); } - public void cull() + public synchronized void cull() { - boolean culled = false; - for (Iterator it = infoBoxes.iterator(); it.hasNext();) - { - InfoBox box = it.next(); - - if (box.cull()) - { - log.debug("Culling InfoBox {}", box); - it.remove(); - culled = true; - } - } - - if (culled) - { - refreshInfoBoxes(); - } + infoBoxes.removeIf(InfoBox::cull); } public void updateInfoBoxImage(final InfoBox infoBox) @@ -161,13 +153,4 @@ public class InfoBoxManager infoBox.setScaledImage(resultImage); } - - private void refreshInfoBoxes() - { - infoBoxes.sort((b1, b2) -> ComparisonChain - .start() - .compare(b1.getPriority(), b2.getPriority()) - .compare(b1.getPlugin().getName(), b2.getPlugin().getName()) - .result()); - } } diff --git a/runelite-client/src/test/java/net/runelite/client/ui/overlay/infobox/InfoBoxManagerTest.java b/runelite-client/src/test/java/net/runelite/client/ui/overlay/infobox/InfoBoxManagerTest.java new file mode 100644 index 0000000000..ee968280b7 --- /dev/null +++ b/runelite-client/src/test/java/net/runelite/client/ui/overlay/infobox/InfoBoxManagerTest.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2020, 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.client.ui.overlay.infobox; + +import com.google.inject.Guice; +import com.google.inject.testing.fieldbinder.Bind; +import com.google.inject.testing.fieldbinder.BoundFieldModule; +import java.awt.Color; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import javax.inject.Inject; +import net.runelite.client.config.RuneLiteConfig; +import net.runelite.client.plugins.Plugin; +import static org.junit.Assert.assertEquals; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import static org.mockito.Mockito.mock; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class InfoBoxManagerTest +{ + @Inject + private InfoBoxManager infoBoxManager; + + @Mock + @Bind + private RuneLiteConfig runeLiteConfig; + + @Before + public void before() + { + Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); + } + + private static class TestInfobox extends InfoBox + { + public TestInfobox(InfoBoxPriority infoBoxPriority) + { + super(null, mock(Plugin.class)); + setPriority(infoBoxPriority); + } + + @Override + public String getText() + { + return null; + } + + @Override + public Color getTextColor() + { + return null; + } + } + + @Test + public void testSorting() + { + infoBoxManager.addInfoBox(new TestInfobox(InfoBoxPriority.LOW)); + infoBoxManager.addInfoBox(new TestInfobox(InfoBoxPriority.HIGH)); + infoBoxManager.addInfoBox(new TestInfobox(InfoBoxPriority.MED)); + + List order = infoBoxManager.getInfoBoxes().stream().map(InfoBox::getPriority).collect(Collectors.toList()); + assertEquals(Arrays.asList(InfoBoxPriority.HIGH, InfoBoxPriority.MED, InfoBoxPriority.LOW), order); + } +} \ No newline at end of file From a54374e93122945a3a779dde1a4c0dab8c8dd127 Mon Sep 17 00:00:00 2001 From: Max Weber Date: Sun, 24 May 2020 09:50:59 -0600 Subject: [PATCH 23/31] HotkeyButton: allow binding the space key --- .../runelite/client/plugins/config/HotkeyButton.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/config/HotkeyButton.java b/runelite-client/src/main/java/net/runelite/client/plugins/config/HotkeyButton.java index 17b23a5785..55b9160c5b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/config/HotkeyButton.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/config/HotkeyButton.java @@ -26,6 +26,8 @@ package net.runelite.client.plugins.config; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; import javax.swing.JButton; import lombok.Getter; import net.runelite.client.config.Keybind; @@ -39,10 +41,16 @@ class HotkeyButton extends JButton public HotkeyButton(Keybind value, boolean modifierless) { setValue(value); - addActionListener(e -> + addMouseListener(new MouseAdapter() { - setValue(Keybind.NOT_SET); + @Override + public void mouseReleased(MouseEvent e) + { + // We have to use a mouse adapter instead of an action listener so the press action key (space) can be bound + setValue(Keybind.NOT_SET); + } }); + addKeyListener(new KeyAdapter() { @Override From 8d62ba9416397b6094e4a893290aa41819e19ac2 Mon Sep 17 00:00:00 2001 From: Tinus Flagstad Date: Sun, 24 May 2020 22:44:33 +0200 Subject: [PATCH 24/31] keyremapping: add option to remap space in dialog --- .../plugins/keyremapping/KeyRemappingConfig.java | 11 +++++++++++ .../plugins/keyremapping/KeyRemappingListener.java | 5 +++++ 2 files changed, 16 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/keyremapping/KeyRemappingConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/keyremapping/KeyRemappingConfig.java index 0ee4c58e22..ca549e5967 100755 --- a/runelite-client/src/main/java/net/runelite/client/plugins/keyremapping/KeyRemappingConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/keyremapping/KeyRemappingConfig.java @@ -241,4 +241,15 @@ public interface KeyRemappingConfig extends Config { return new ModifierlessKeybind(KeyEvent.VK_ESCAPE, 0); } + + @ConfigItem( + position = 20, + keyName = "space", + name = "Space", + description = "The key which will replace {Space} when dialogs are open." + ) + default ModifierlessKeybind space() + { + return new ModifierlessKeybind(KeyEvent.VK_SPACE, 0); + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/keyremapping/KeyRemappingListener.java b/runelite-client/src/main/java/net/runelite/client/plugins/keyremapping/KeyRemappingListener.java index 472e009e1b..726881379a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/keyremapping/KeyRemappingListener.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/keyremapping/KeyRemappingListener.java @@ -156,6 +156,11 @@ class KeyRemappingListener implements KeyListener } } + if (plugin.isDialogOpen() && config.space().matches(e)) + { + mappedKeyCode = KeyEvent.VK_SPACE; + } + if (mappedKeyCode != KeyEvent.VK_UNDEFINED && mappedKeyCode != e.getKeyCode()) { final char keyChar = e.getKeyChar(); From 8e06e398ee32100ff76cea116cafd9427f884145 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 24 May 2020 17:12:23 -0400 Subject: [PATCH 25/31] chathistory: small cleanups of clear history --- .../plugins/chathistory/ChatHistoryPlugin.java | 8 ++++---- .../client/plugins/chathistory/ChatboxTab.java | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatHistoryPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatHistoryPlugin.java index 4ed0f21646..bf454cf9bb 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatHistoryPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatHistoryPlugin.java @@ -268,10 +268,9 @@ public class ChatHistoryPlugin extends Plugin implements KeyListener @Subscribe public void onMenuEntryAdded(MenuEntryAdded entry) { - final String option = Text.removeTags(entry.getOption()); final ChatboxTab tab = ChatboxTab.of(entry.getActionParam1()); - if (!config.clearHistory() || tab == null || !option.equals(tab.getAfter())) + if (tab == null || !config.clearHistory() || !Text.removeTags(entry.getOption()).equals(tab.getAfter())) { return; } @@ -310,7 +309,7 @@ public class ChatHistoryPlugin extends Plugin implements KeyListener friends.clear(); } - messageQueue.removeIf(e -> tab.getMessageTypes().contains(e.getType())); + messageQueue.removeIf(e -> ArrayUtils.contains(tab.getMessageTypes(), e.getType())); } private void clearChatboxHistory(ChatboxTab tab) @@ -343,8 +342,9 @@ public class ChatHistoryPlugin extends Plugin implements KeyListener if (removed) { clientThread.invoke(() -> client.runScript(ScriptID.BUILD_CHATBOX)); - clearMessageQueue(tab); } + + clearMessageQueue(tab); } /** diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatboxTab.java b/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatboxTab.java index 9411f08c82..f37adb0ea1 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatboxTab.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chathistory/ChatboxTab.java @@ -24,9 +24,7 @@ */ package net.runelite.client.plugins.chathistory; -import com.google.common.collect.ImmutableList; -import java.util.HashMap; -import java.util.List; +import com.google.common.collect.ImmutableMap; import java.util.Map; import javax.annotation.Nullable; import lombok.Getter; @@ -63,28 +61,30 @@ enum ChatboxTab ChatMessageType.TRADE_SENT, ChatMessageType.TRADEREQ, ChatMessageType.TRADE, ChatMessageType.CHALREQ_TRADE), ; - private static final Map TAB_MESSAGE_TYPES = new HashMap<>(); + private static final Map TAB_MESSAGE_TYPES; + private final String name; @Nullable private final String after; - private final String name; private final int widgetId; - private final List messageTypes; + private final ChatMessageType[] messageTypes; ChatboxTab(String name, String after, WidgetInfo widgetId, ChatMessageType... messageTypes) { this.name = name; this.after = after; this.widgetId = widgetId.getId(); - this.messageTypes = ImmutableList.copyOf(messageTypes); + this.messageTypes = messageTypes; } static { + ImmutableMap.Builder builder = ImmutableMap.builder(); for (ChatboxTab t : values()) { - TAB_MESSAGE_TYPES.put(t.widgetId, t); + builder.put(t.widgetId, t); } + TAB_MESSAGE_TYPES = builder.build(); } static ChatboxTab of(int widgetId) From db592bcad072239e750889189869c4f70a59ea04 Mon Sep 17 00:00:00 2001 From: Trey Date: Wed, 1 Apr 2020 01:32:14 -0500 Subject: [PATCH 26/31] cluescrolls: Add jungle traversing info to dragon's eye clue This commit adds information on traversing the Kharazi jungle prior to reaching the Viyeldi caves. --- .../runelite/client/plugins/cluescrolls/clues/CrypticClue.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CrypticClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CrypticClue.java index 7ee9b762fa..421b09145d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CrypticClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CrypticClue.java @@ -230,7 +230,7 @@ public class CrypticClue extends ClueScroll implements TextClueScroll, NpcClueSc new CrypticClue("Dig under Razorlor's toad batta.", new WorldPoint(3139, 4554, 0), "Dig on the toad batta spawn in Tarn's Lair."), new CrypticClue("Talk to Cassie in Falador.", "Cassie", new WorldPoint(2975, 3383, 0), "Cassie is found just south-east of the northern Falador gate."), new CrypticClue("Faint sounds of 'Arr', fire giants found deep, the eastern tip of a lake, are the rewards you could reap.", new WorldPoint(3055, 10338, 0), "Dig south of the pillar in the Deep Wilderness Dungeon in the room with the fire giants."), - new CrypticClue("If you're feeling brave, dig beneath the dragon's eye.", new WorldPoint(2410, 4714, 0), "Dig below the mossy rock under the Viyeldi caves (Legend's Quest). Items needed: Pickaxe, unpowered orb, lockpick, spade, and any charge orb spell."), + new CrypticClue("If you're feeling brave, dig beneath the dragon's eye.", new WorldPoint(2410, 4714, 0), "Dig below the mossy rock under the Viyeldi caves (Legend's Quest). Items needed: Pickaxe, unpowered orb, lockpick, spade, any charge orb spell, and either 79 agility or an axe and machete."), new CrypticClue("Search the tents in the Imperial Guard camp in Burthorpe for some boxes.", BOXES_3686, new WorldPoint(2885, 3540, 0), "Search in the tents in northwest corner of the camp."), new CrypticClue("A dwarf, approaching death, but very much in the light.", "Thorgel", new WorldPoint(1863, 4639, 0), "Thorgel at the entrance to the Death altar"), new CrypticClue("You must be 100 to play with me.", "Squire (Veteran)", new WorldPoint(2638, 2656, 0), "Speak to the Veteran boat squire at Pest Control"), From 0b62acbcaf99cb129c5fa8734a3a974e7722a579 Mon Sep 17 00:00:00 2001 From: Trey Date: Sun, 24 May 2020 17:59:15 -0700 Subject: [PATCH 27/31] cluescrolls: Add Dragontooth Island travel info to clue This commit adds information on reaching Dragontooth Island for the clue step located there. --- .../client/plugins/cluescrolls/clues/CoordinateClue.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java index 16d524b91c..72da07ede4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java @@ -184,7 +184,7 @@ public class CoordinateClue extends ClueScroll implements TextClueScroll, Locati .put(new WorldPoint(3828, 2848, 0), new CoordinateClueInfo("East of Harmony Island.", ARMADYLIAN_OR_BANDOSIAN_GUARD)) .put(new WorldPoint(3225, 2838, 0), new CoordinateClueInfo("South of Desert Treasure pyramid.", ARMADYLIAN_OR_BANDOSIAN_GUARD)) .put(new WorldPoint(1773, 3510, 0), new CoordinateClueInfo("Ruins north of the Hosidius mine.", ARMADYLIAN_OR_BANDOSIAN_GUARD)) - .put(new WorldPoint(3822, 3562, 0), new CoordinateClueInfo("North-east of Dragontooth Island.", ARMADYLIAN_OR_BANDOSIAN_GUARD)) + .put(new WorldPoint(3822, 3562, 0), new CoordinateClueInfo("North-east of Dragontooth Island. Bring a Ghostspeak Amulet and 25 Ecto-tokens to reach the island.", ARMADYLIAN_OR_BANDOSIAN_GUARD)) .put(new WorldPoint(3603, 3564, 0), new CoordinateClueInfo("North of the wrecked ship, outside of Port Phasmatys.", ARMADYLIAN_OR_BANDOSIAN_GUARD)) .put(new WorldPoint(2936, 2721, 0), new CoordinateClueInfo("Eastern shore of Crash Island.", ARMADYLIAN_OR_BANDOSIAN_GUARD)) .put(new WorldPoint(2697, 2705, 0), new CoordinateClueInfo("South-west of Ape Atoll.", ARMADYLIAN_OR_BANDOSIAN_GUARD)) From 4faf36edc22390819c7fa2cb016f6db0ad90ab50 Mon Sep 17 00:00:00 2001 From: Broooklyn <54762282+Broooklyn@users.noreply.github.com> Date: Mon, 25 May 2020 00:45:45 -0400 Subject: [PATCH 28/31] loottracker: Improve ignored events config name and description (#11545) --- .../runelite/client/plugins/loottracker/LootTrackerBox.java | 2 +- .../client/plugins/loottracker/LootTrackerConfig.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerBox.java b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerBox.java index 2d1398b486..927b222dc7 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerBox.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerBox.java @@ -143,7 +143,7 @@ class LootTrackerBox extends JPanel popupMenu.setBorder(new EmptyBorder(5, 5, 5, 5)); this.setComponentPopupMenu(popupMenu); - final JMenuItem toggle = new JMenuItem(eventIgnored ? "Include group" : "Ignore group"); + final JMenuItem toggle = new JMenuItem(eventIgnored ? "Include loot" : "Hide loot"); toggle.addActionListener(e -> onEventToggle.accept(id, !eventIgnored)); popupMenu.add(toggle); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerConfig.java index 00a04f7756..1d9f8b847d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerConfig.java @@ -93,8 +93,8 @@ public interface LootTrackerConfig extends Config @ConfigItem( keyName = "ignoredEvents", - name = "Ignored groups", - description = "Configures which loot groups should be excluded from the panel UI" + name = "Ignored Loot Sources", + description = "Hide specific NPCs or sources of loot in the loot tracker (e.g., Goblin, Barrows Chest, H.A.M. Member)." ) default String getIgnoredEvents() { From fc7e697aa7f562aee6077594ee59c6acbcbda8d1 Mon Sep 17 00:00:00 2001 From: Daniel Date: Mon, 25 May 2020 02:09:53 -0400 Subject: [PATCH 29/31] item prices: always show tooltip when alching if option is enabled --- .../runelite/client/plugins/itemprices/ItemPricesConfig.java | 2 +- .../client/plugins/itemprices/ItemPricesOverlay.java | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemprices/ItemPricesConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemprices/ItemPricesConfig.java index 2880d1b8f0..5c667a2b1a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemprices/ItemPricesConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemprices/ItemPricesConfig.java @@ -89,7 +89,7 @@ public interface ItemPricesConfig extends Config @ConfigItem( keyName = "showWhileAlching", name = "Show prices while alching", - description = "Show the price overlay while using High Alchemy", + description = "Show the price overlay while using High Alchemy. Takes priority over \"Hide tooltips on Inventory Items\"", position = 6 ) default boolean showWhileAlching() diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemprices/ItemPricesOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemprices/ItemPricesOverlay.java index 0203578378..a4102f7996 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemprices/ItemPricesOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemprices/ItemPricesOverlay.java @@ -93,12 +93,13 @@ class ItemPricesOverlay extends Overlay final MenuAction action = MenuAction.of(menuEntry.getType()); final int widgetId = menuEntry.getParam1(); final int groupId = WidgetInfo.TO_GROUP(widgetId); + final boolean isAlching = menuEntry.getOption().equals("Cast") && menuEntry.getTarget().contains("High Level Alchemy"); // Tooltip action type handling switch (action) { case ITEM_USE_ON_WIDGET: - if (!config.showWhileAlching() || !menuEntry.getOption().equals("Cast") || !menuEntry.getTarget().contains("High Level Alchemy")) + if (!config.showWhileAlching() || !isAlching) { break; } @@ -118,7 +119,7 @@ class ItemPricesOverlay extends Overlay return null; } case WidgetID.INVENTORY_GROUP_ID: - if (config.hideInventory()) + if (config.hideInventory() && !(config.showWhileAlching() && isAlching)) { return null; } From 5f84e28a14cf6753bf98a95f11e61557a47a996c Mon Sep 17 00:00:00 2001 From: Jan-Willem de Bruyn Date: Mon, 25 May 2020 08:31:59 +0200 Subject: [PATCH 30/31] skillcalculator: Add clay crafting items (#11518) --- .../skillcalculator/skill_crafting.json | 62 ++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_crafting.json b/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_crafting.json index 655703639f..0f2a5c6922 100644 --- a/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_crafting.json +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_crafting.json @@ -6,6 +6,18 @@ "name": "Ball Of Wool", "xp": 2.5 }, + { + "level": 1, + "icon": 1787, + "name": "Unfired pot", + "xp": 6.3 + }, + { + "level": 1, + "icon": 1931, + "name": "Pot", + "xp": 6.3 + }, { "level": 1, "icon": 1059, @@ -66,12 +78,36 @@ "name": "Leather Boots", "xp": 16.3 }, + { + "level": 7, + "icon": 1789, + "name": "Unfired pie dish", + "xp": 15 + }, + { + "level": 7, + "icon": 2313, + "name": "Pie dish", + "xp": 10 + }, { "level": 7, "icon": 11068, "name": "Gold Bracelet", "xp": 25 }, + { + "level": 8, + "icon": 1791, + "name": "Unfired bowl", + "xp": 18 + }, + { + "level": 8, + "icon": 1923, + "name": "Bowl", + "xp": 15 + }, { "level": 8, "icon": 1673, @@ -169,6 +205,18 @@ "name": "Leather Chaps", "xp": 27 }, + { + "level": 19, + "icon": 5352, + "name": "Unfired plant pot", + "xp": 20 + }, + { + "level": 19, + "icon": 5350, + "name": "Empty plant pot", + "xp": 17.5 + }, { "level": 19, "icon": 6038, @@ -223,6 +271,18 @@ "name": "Sapphire Amulet (U)", "xp": 65 }, + { + "level": 25, + "icon": 4438, + "name": "Unfired pot lid", + "xp": 20 + }, + { + "level": 25, + "icon": 4440, + "name": "Pot lid", + "xp": 20 + }, { "level": 25, "icon": 21093, @@ -740,4 +800,4 @@ "xp": 200 } ] -} \ No newline at end of file +} From 667a0e92976c92a51ea144b317d0fad3b9a5476e Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 25 May 2020 11:10:23 -0400 Subject: [PATCH 31/31] cache: diable some long-running tests These tests just bulk-dump data and don't really test anything, and use up a lot of CI time when tests are run --- cache/src/test/java/net/runelite/cache/FramemapDumper.java | 2 ++ .../src/test/java/net/runelite/cache/InterfaceManagerTest.java | 2 ++ cache/src/test/java/net/runelite/cache/ItemManagerTest.java | 2 ++ cache/src/test/java/net/runelite/cache/ModelDumperTest.java | 2 ++ cache/src/test/java/net/runelite/cache/NpcManagerTest.java | 2 ++ cache/src/test/java/net/runelite/cache/ObjectManagerTest.java | 2 ++ cache/src/test/java/net/runelite/cache/SequenceDumper.java | 2 ++ .../test/java/net/runelite/cache/SoundEffectsDumperTest.java | 2 ++ cache/src/test/java/net/runelite/cache/SpotanimDumperTest.java | 2 ++ cache/src/test/java/net/runelite/cache/SpriteManagerTest.java | 2 ++ cache/src/test/java/net/runelite/cache/TitleDumper.java | 2 +- cache/src/test/java/net/runelite/cache/VarbitDumper.java | 2 ++ 12 files changed, 23 insertions(+), 1 deletion(-) diff --git a/cache/src/test/java/net/runelite/cache/FramemapDumper.java b/cache/src/test/java/net/runelite/cache/FramemapDumper.java index f95e92c9fa..8feef1f814 100644 --- a/cache/src/test/java/net/runelite/cache/FramemapDumper.java +++ b/cache/src/test/java/net/runelite/cache/FramemapDumper.java @@ -36,6 +36,7 @@ import net.runelite.cache.fs.Archive; import net.runelite.cache.fs.Index; import net.runelite.cache.fs.Storage; import net.runelite.cache.fs.Store; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -52,6 +53,7 @@ public class FramemapDumper private final Gson gson = new GsonBuilder().setPrettyPrinting().create(); @Test + @Ignore public void extract() throws IOException { File base = StoreLocation.LOCATION, diff --git a/cache/src/test/java/net/runelite/cache/InterfaceManagerTest.java b/cache/src/test/java/net/runelite/cache/InterfaceManagerTest.java index 060aae5d57..f26ff06b21 100644 --- a/cache/src/test/java/net/runelite/cache/InterfaceManagerTest.java +++ b/cache/src/test/java/net/runelite/cache/InterfaceManagerTest.java @@ -28,6 +28,7 @@ package net.runelite.cache; import java.io.File; import java.io.IOException; import net.runelite.cache.fs.Store; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -42,6 +43,7 @@ public class InterfaceManagerTest public TemporaryFolder folder = StoreLocation.getTemporaryFolder(); @Test + @Ignore public void test() throws IOException { File dumpDir = folder.newFolder(), diff --git a/cache/src/test/java/net/runelite/cache/ItemManagerTest.java b/cache/src/test/java/net/runelite/cache/ItemManagerTest.java index e3ac0b3324..e9f74f0c0d 100644 --- a/cache/src/test/java/net/runelite/cache/ItemManagerTest.java +++ b/cache/src/test/java/net/runelite/cache/ItemManagerTest.java @@ -28,6 +28,7 @@ package net.runelite.cache; import java.io.File; import java.io.IOException; import net.runelite.cache.fs.Store; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -42,6 +43,7 @@ public class ItemManagerTest public TemporaryFolder folder = StoreLocation.getTemporaryFolder(); @Test + @Ignore public void test() throws IOException { File dumpDir = folder.newFolder(), diff --git a/cache/src/test/java/net/runelite/cache/ModelDumperTest.java b/cache/src/test/java/net/runelite/cache/ModelDumperTest.java index 32f5879ac1..362e02ea3b 100644 --- a/cache/src/test/java/net/runelite/cache/ModelDumperTest.java +++ b/cache/src/test/java/net/runelite/cache/ModelDumperTest.java @@ -34,6 +34,7 @@ import net.runelite.cache.fs.Archive; import net.runelite.cache.fs.Index; import net.runelite.cache.fs.Storage; import net.runelite.cache.fs.Store; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -48,6 +49,7 @@ public class ModelDumperTest public TemporaryFolder folder = StoreLocation.getTemporaryFolder(); @Test + @Ignore public void test() throws IOException { File modelDir = folder.newFolder("models"); diff --git a/cache/src/test/java/net/runelite/cache/NpcManagerTest.java b/cache/src/test/java/net/runelite/cache/NpcManagerTest.java index cdccac0cfb..bb80e5d0d2 100644 --- a/cache/src/test/java/net/runelite/cache/NpcManagerTest.java +++ b/cache/src/test/java/net/runelite/cache/NpcManagerTest.java @@ -27,6 +27,7 @@ package net.runelite.cache; import java.io.File; import java.io.IOException; import net.runelite.cache.fs.Store; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -41,6 +42,7 @@ public class NpcManagerTest public TemporaryFolder folder = StoreLocation.getTemporaryFolder(); @Test + @Ignore public void test() throws IOException { File dumpDir = folder.newFolder(), diff --git a/cache/src/test/java/net/runelite/cache/ObjectManagerTest.java b/cache/src/test/java/net/runelite/cache/ObjectManagerTest.java index f50196734e..da6f4de579 100644 --- a/cache/src/test/java/net/runelite/cache/ObjectManagerTest.java +++ b/cache/src/test/java/net/runelite/cache/ObjectManagerTest.java @@ -27,6 +27,7 @@ package net.runelite.cache; import java.io.File; import java.io.IOException; import net.runelite.cache.fs.Store; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -41,6 +42,7 @@ public class ObjectManagerTest public TemporaryFolder folder = StoreLocation.getTemporaryFolder(); @Test + @Ignore public void test() throws IOException { File dumpDir = folder.newFolder(), diff --git a/cache/src/test/java/net/runelite/cache/SequenceDumper.java b/cache/src/test/java/net/runelite/cache/SequenceDumper.java index 485bd3d84f..b03bed7f03 100644 --- a/cache/src/test/java/net/runelite/cache/SequenceDumper.java +++ b/cache/src/test/java/net/runelite/cache/SequenceDumper.java @@ -38,6 +38,7 @@ import net.runelite.cache.fs.FSFile; import net.runelite.cache.fs.Index; import net.runelite.cache.fs.Storage; import net.runelite.cache.fs.Store; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -54,6 +55,7 @@ public class SequenceDumper private final Gson gson = new GsonBuilder().setPrettyPrinting().create(); @Test + @Ignore public void extract() throws IOException { File base = StoreLocation.LOCATION, diff --git a/cache/src/test/java/net/runelite/cache/SoundEffectsDumperTest.java b/cache/src/test/java/net/runelite/cache/SoundEffectsDumperTest.java index 5ac0c9e1c5..7a1cef91b3 100644 --- a/cache/src/test/java/net/runelite/cache/SoundEffectsDumperTest.java +++ b/cache/src/test/java/net/runelite/cache/SoundEffectsDumperTest.java @@ -36,6 +36,7 @@ import net.runelite.cache.fs.Archive; import net.runelite.cache.fs.Index; import net.runelite.cache.fs.Storage; import net.runelite.cache.fs.Store; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -52,6 +53,7 @@ public class SoundEffectsDumperTest public TemporaryFolder folder = StoreLocation.getTemporaryFolder(); @Test + @Ignore public void test() throws IOException { File dumpDir = folder.newFolder(); diff --git a/cache/src/test/java/net/runelite/cache/SpotanimDumperTest.java b/cache/src/test/java/net/runelite/cache/SpotanimDumperTest.java index 93de3d66f4..31c837debd 100644 --- a/cache/src/test/java/net/runelite/cache/SpotanimDumperTest.java +++ b/cache/src/test/java/net/runelite/cache/SpotanimDumperTest.java @@ -39,6 +39,7 @@ import net.runelite.cache.fs.FSFile; import net.runelite.cache.fs.Index; import net.runelite.cache.fs.Storage; import net.runelite.cache.fs.Store; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -52,6 +53,7 @@ public class SpotanimDumperTest public TemporaryFolder folder = StoreLocation.getTemporaryFolder(); @Test + @Ignore public void test() throws IOException { File dumpDir = folder.newFolder("spotanims"); diff --git a/cache/src/test/java/net/runelite/cache/SpriteManagerTest.java b/cache/src/test/java/net/runelite/cache/SpriteManagerTest.java index f8a103ccb8..b9564f4d41 100644 --- a/cache/src/test/java/net/runelite/cache/SpriteManagerTest.java +++ b/cache/src/test/java/net/runelite/cache/SpriteManagerTest.java @@ -27,6 +27,7 @@ package net.runelite.cache; import java.io.File; import java.io.IOException; import net.runelite.cache.fs.Store; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -41,6 +42,7 @@ public class SpriteManagerTest public TemporaryFolder folder = StoreLocation.getTemporaryFolder(); @Test + @Ignore public void test() throws IOException { File dumpDir = folder.newFolder(); diff --git a/cache/src/test/java/net/runelite/cache/TitleDumper.java b/cache/src/test/java/net/runelite/cache/TitleDumper.java index c611ddf04a..5be95c7563 100644 --- a/cache/src/test/java/net/runelite/cache/TitleDumper.java +++ b/cache/src/test/java/net/runelite/cache/TitleDumper.java @@ -48,7 +48,7 @@ public class TitleDumper public void extract() throws IOException { File base = StoreLocation.LOCATION, - outFile = folder.newFolder(); + outFile = folder.newFile(); try (Store store = new Store(base)) { diff --git a/cache/src/test/java/net/runelite/cache/VarbitDumper.java b/cache/src/test/java/net/runelite/cache/VarbitDumper.java index 9bcdcf9237..73bc9d41b1 100644 --- a/cache/src/test/java/net/runelite/cache/VarbitDumper.java +++ b/cache/src/test/java/net/runelite/cache/VarbitDumper.java @@ -38,6 +38,7 @@ import net.runelite.cache.fs.FSFile; import net.runelite.cache.fs.Index; import net.runelite.cache.fs.Storage; import net.runelite.cache.fs.Store; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -54,6 +55,7 @@ public class VarbitDumper private final Gson gson = new GsonBuilder().setPrettyPrinting().create(); @Test + @Ignore public void extract() throws IOException { File base = StoreLocation.LOCATION,