diff --git a/runelite-client/src/main/java/net/runelite/client/game/ItemMapping.java b/runelite-client/src/main/java/net/runelite/client/game/ItemMapping.java index 3894b32e0d..07ec488ff7 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/ItemMapping.java +++ b/runelite-client/src/main/java/net/runelite/client/game/ItemMapping.java @@ -228,7 +228,7 @@ public enum ItemMapping ITEM_CRYSTAL_SHIELD(CRYSTAL_WEAPON_SEED, CRYSTAL_SHIELD, CRYSTAL_SHIELD_24127, CRYSTAL_SHIELD_INACTIVE), // Bird nests - ITEM_BIRD_NEST(BIRD_NEST, BIRD_NEST_5071, BIRD_NEST_5072, BIRD_NEST_5073, BIRD_NEST_5074, BIRD_NEST_5075, BIRD_NEST_7413, BIRD_NEST_13653, BIRD_NEST_22798, BIRD_NEST_22800); + ITEM_BIRD_NEST(BIRD_NEST_5075, BIRD_NEST, BIRD_NEST_5071, BIRD_NEST_5072, BIRD_NEST_5073, BIRD_NEST_5074, BIRD_NEST_7413, BIRD_NEST_13653, BIRD_NEST_22798, BIRD_NEST_22800, CLUE_NEST_EASY, CLUE_NEST_MEDIUM, CLUE_NEST_HARD, CLUE_NEST_ELITE); private static final Multimap MAPPINGS = HashMultimap.create(); private final int tradeableItem; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/bank/BankPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/bank/BankPlugin.java index 549642efbf..e5f3424724 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/bank/BankPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/bank/BankPlugin.java @@ -26,19 +26,28 @@ */ package net.runelite.client.plugins.bank; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.HashMultiset; import com.google.common.collect.ImmutableList; +import com.google.common.collect.Multiset; import com.google.inject.Provides; +import java.text.ParseException; import java.util.Arrays; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.inject.Inject; import javax.inject.Singleton; import lombok.AccessLevel; import lombok.Getter; import net.runelite.api.Client; +import static net.runelite.api.Constants.HIGH_ALCHEMY_MULTIPLIER; import net.runelite.api.InventoryID; import net.runelite.api.Item; import net.runelite.api.FontID; import net.runelite.api.ItemContainer; +import net.runelite.api.ItemDefinition; +import net.runelite.api.ItemID; import net.runelite.api.MenuEntry; import net.runelite.api.events.ConfigChanged; import net.runelite.api.Varbits; @@ -53,6 +62,7 @@ import net.runelite.api.widgets.WidgetInfo; import net.runelite.client.callback.ClientThread; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.EventBus; +import net.runelite.client.game.ItemManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.banktags.tabs.BankSearch; @@ -97,12 +107,20 @@ public class BankPlugin extends Plugin private static final String SEED_VAULT_TITLE = "Seed Vault"; private static final int PIN_FONT_OFFSET = 5; + private static final String NUMBER_REGEX = "[0-9]+(\\.[0-9]+)?[kmb]?"; + private static final Pattern VALUE_SEARCH_PATTERN = Pattern.compile("^(?ge|ha|alch)?" + + " *(((?[<>=]|>=|<=) *(?" + NUMBER_REGEX + "))|" + + "((?" + NUMBER_REGEX + ") *- *(?" + NUMBER_REGEX + ")))$", Pattern.CASE_INSENSITIVE); + @Inject private Client client; @Inject private ClientThread clientThread; + @Inject + private ItemManager itemManager; + @Inject private BankConfig config; @@ -120,6 +138,7 @@ public class BankPlugin extends Plugin private boolean forceRightClickFlag; private boolean largePinNumbers; + private Multiset itemQuantities; // bank item quantities for bank value search @Provides BankConfig getConfig(ConfigManager configManager) @@ -149,6 +168,7 @@ public class BankPlugin extends Plugin eventBus.unregister(this); clientThread.invokeLater(() -> bankSearch.reset(false)); forceRightClickFlag = false; + itemQuantities = null; } private void addSubscriptions() @@ -204,18 +224,36 @@ public class BankPlugin extends Plugin return; } - final ContainerPrices prices = bankCalculation.calculate(getBankTabItems()); - if (prices == null) - { - return; - } - - final String strCurrentTab = createValueText(prices); - + int[] intStack = client.getIntStack(); String[] stringStack = client.getStringStack(); + int intStackSize = client.getIntStackSize(); int stringStackSize = client.getStringStackSize(); - stringStack[stringStackSize - 1] += strCurrentTab; + switch (event.getEventName()) + { + case "setBankTitle": + final ContainerPrices prices = bankCalculation.calculate(getBankTabItems()); + if (prices == null) + { + return; + } + + final String strCurrentTab = createValueText(prices); + + stringStack[stringStackSize - 1] += strCurrentTab; + break; + case "bankSearchFilter": + int itemId = intStack[intStackSize - 1]; + String search = stringStack[stringStackSize - 1]; + + if (valueSearch(itemId, search)) + { + // return true + intStack[intStackSize - 2] = 1; + } + + break; + } } private void onWidgetLoaded(WidgetLoaded event) @@ -230,12 +268,16 @@ public class BankPlugin extends Plugin private void onItemContainerChanged(ItemContainerChanged event) { - if (event.getContainerId() != InventoryID.SEED_VAULT.getId() || !config.seedVaultValue()) - { - return; - } + int containerId = event.getContainerId(); - updateSeedVaultTotal(); + if (containerId == InventoryID.BANK.getId()) + { + itemQuantities = null; + } + else if (containerId == InventoryID.SEED_VAULT.getId() && config.seedVaultValue()) + { + updateSeedVaultTotal(); + } } private String createValueText(final ContainerPrices prices) @@ -403,4 +445,99 @@ public class BankPlugin extends Plugin this.rightClickBankEquip = config.rightClickBankEquip(); this.rightClickBankLoot = config.rightClickBankLoot(); } + + @VisibleForTesting + boolean valueSearch(final int itemId, final String str) + { + final Matcher matcher = VALUE_SEARCH_PATTERN.matcher(str); + if (!matcher.matches()) + { + return false; + } + + // Count bank items and remember it for determining item quantity + if (itemQuantities == null) + { + itemQuantities = getBankItemSet(); + } + + final ItemDefinition itemComposition = itemManager.getItemDefinition(itemId); + long gePrice = (long) itemManager.getItemPrice(itemId) * (long) itemQuantities.count(itemId); + long haPrice = (long) (itemComposition.getPrice() * HIGH_ALCHEMY_MULTIPLIER) * (long) itemQuantities.count(itemId); + + long value = Math.max(gePrice, haPrice); + + final String mode = matcher.group("mode"); + if (mode != null) + { + value = mode.toLowerCase().equals("ge") ? gePrice : haPrice; + } + + final String op = matcher.group("op"); + if (op != null) + { + long compare; + try + { + compare = StackFormatter.stackSizeToQuantity(matcher.group("num")); + } + catch (ParseException e) + { + return false; + } + + switch (op) + { + case ">": + return value > compare; + case "<": + return value < compare; + case "=": + return value == compare; + case ">=": + return value >= compare; + case "<=": + return value <= compare; + } + } + + final String num1 = matcher.group("num1"); + final String num2 = matcher.group("num2"); + if (num1 != null && num2 != null) + { + long compare1, compare2; + try + { + compare1 = StackFormatter.stackSizeToQuantity(num1); + compare2 = StackFormatter.stackSizeToQuantity(num2); + } + catch (ParseException e) + { + return false; + } + + return compare1 <= value && compare2 >= value; + } + + return false; + } + + private Multiset getBankItemSet() + { + ItemContainer itemContainer = client.getItemContainer(InventoryID.BANK); + if (itemContainer == null) + { + return HashMultiset.create(); + } + + Multiset set = HashMultiset.create(); + for (Item item : itemContainer.getItems()) + { + if (item.getId() != ItemID.BANK_FILLER) + { + set.add(item.getId(), item.getQuantity()); + } + } + return set; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTagsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTagsPlugin.java index 3343450b86..ee192041ff 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTagsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/BankTagsPlugin.java @@ -214,10 +214,6 @@ public class BankTagsPlugin extends Plugin implements MouseWheelListener, KeyLis switch (eventName) { - case "bankTagsActive": - // tell the script the bank tag plugin is active - intStack[intStackSize - 1] = 1; - break; case "setSearchBankInputText": stringStack[stringStackSize - 1] = SEARCH_BANK_INPUT_TEXT; break; @@ -229,7 +225,6 @@ public class BankTagsPlugin extends Plugin implements MouseWheelListener, KeyLis } case "bankSearchFilter": int itemId = intStack[intStackSize - 1]; - String itemName = stringStack[stringStackSize - 2]; String search = stringStack[stringStackSize - 1]; boolean tagSearch = search.startsWith(TAG_SEARCH); @@ -254,9 +249,9 @@ public class BankTagsPlugin extends Plugin implements MouseWheelListener, KeyLis } break; } - else if (!tagSearch) + else if (tagSearch) { - intStack[intStackSize - 2] = itemName.contains(search) ? 1 : 0; + intStack[intStackSize - 2] = 0; } break; case "getSearchingTagTab": diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/ClueScrollPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/ClueScrollPlugin.java index ed6522ceba..27d36c1c80 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/ClueScrollPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/ClueScrollPlugin.java @@ -253,14 +253,6 @@ public class ClueScrollPlugin extends Plugin ((SkillChallengeClue) clue).setChallengeCompleted(true); } } - - if (!event.getMessage().equals("The strange device cools as you find your treasure.") - && !event.getMessage().equals("Well done, you've completed the Treasure Trail!")) - { - return; - } - - resetClue(true); } private void onMenuOptionClicked(final MenuOptionClicked event) @@ -420,6 +412,15 @@ public class ClueScrollPlugin extends Plugin } } + // Reset clue when receiving a new beginner or master clue + // These clues use a single item ID, so we cannot detect step changes based on the item ID changing + final Widget chatDialogClueItem = client.getWidget(WidgetInfo.DIALOG_SPRITE_SPRITE); + if (chatDialogClueItem != null + && (chatDialogClueItem.getItemId() == ItemID.CLUE_SCROLL_BEGINNER || chatDialogClueItem.getItemId() == ItemID.CLUE_SCROLL_MASTER)) + { + resetClue(true); + } + // If we have a clue, save that knowledge // so the clue window doesn't have to be open. updateClue(findClueScroll()); 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 268e03f5a0..55735a3767 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 @@ -77,7 +77,7 @@ public class CoordinateClue extends ClueScroll implements TextClueScroll, Locati .put(new WorldPoint(2363, 3531, 0), "North-east of Eagles' Peak.") .put(new WorldPoint(2919, 3535, 0), "East of Burthorpe pub.") .put(new WorldPoint(3548, 3560, 0), "Inside Fenkenstrain's Castle.") - .put(new WorldPoint(1456, 3620, 0), "Graveyard west of Shayzien.") + .put(new WorldPoint(1456, 3620, 0), "Graveyard west of Shayzien (DJR).") .put(new WorldPoint(2735, 3638, 0), "East of Rellekka, north-west of Golden Apple Tree (AJR).") .put(new WorldPoint(2681, 3653, 0), "Rellekka, in the garden of the south-east house.") .put(new WorldPoint(2537, 3881, 0), "Miscellania.") 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 54f843270c..8e63f37ca5 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 @@ -170,7 +170,7 @@ public class CrypticClue extends ClueScroll implements TextClueScroll, NpcClueSc new CrypticClue("Search the bush at the digsite centre.", BUSH_2357, new WorldPoint(3345, 3378, 0), "The bush is on the east side of the first pathway towards the digsite from the Exam Centre."), new CrypticClue("Someone watching the fights in the Duel Arena is your next destination.", "Jeed", new WorldPoint(3360, 3242, 0), "Talk to Jeed, found on the upper floors, at the Duel Arena."), new CrypticClue("It seems to have reached the end of the line, and it's still empty.", MINE_CART_6045, new WorldPoint(3041, 9820, 0), "Search the carts in the northern part of the Dwarven Mine."), - new CrypticClue("You'll have to plug your nose if you use this source of herbs.", null, "Kill an Aberrant spectre."), + new CrypticClue("You'll have to plug your nose if you use this source of herbs.", null, "Kill an Aberrant or Deviant spectre."), new CrypticClue("When you get tired of fighting, go deep, deep down until you need an antidote.", CRATE_357, new WorldPoint(2576, 9583, 0), "Go to Yanille Agility dungeon and fall into the place with the poison spiders. Search the crate by the stairs leading up."), new CrypticClue("Search the bookcase in the monastery.", BOOKCASE_380, new WorldPoint(3054, 3484, 0), "Search the southeastern bookcase at Edgeville Monastery."), new CrypticClue("Surprising? I bet he is...", "Sir Prysin", new WorldPoint(3205, 3474, 0), "Talk to Sir Prysin in Varrock Palace."), @@ -274,7 +274,7 @@ public class CrypticClue extends ClueScroll implements TextClueScroll, NpcClueSc new CrypticClue("Search the crates in Horvik's armoury.", CRATE_5106, new WorldPoint(3228, 3433, 0), "Horvik's in Varrock"), new CrypticClue("Ghommal wishes to be impressed by how strong your equipment is.", "Ghommal", new WorldPoint(2878, 3546, 0), "Speak to Ghommal at the Warriors' Guild with a total Melee Strength bonus of over 100."), new CrypticClue("Shhhh!", "Logosia", new WorldPoint(1633, 3808, 0), "Speak to Logosia in the Arceuus Library's ground floor."), - new CrypticClue("Salty peter.", "Konoo", new WorldPoint(1703, 3524, 0), "Talk to Konoo who is digging saltpetre in Hosidius, south of the bank."), + new CrypticClue("Salty peter.", "Konoo", new WorldPoint(1703, 3524, 0), "Talk to Konoo who is digging saltpetre in Hosidius, north-east of the Woodcutting Guild."), new CrypticClue("Talk to Zeke in Al Kharid.", "Zeke", new WorldPoint(3287, 3190, 0), "Zeke is the owner of the scimitar shop in Al Kharid."), new CrypticClue("Guthix left his mark in a fiery lake, dig at the tip of it.", new WorldPoint(3069, 3935, 0), "Dig at the tip of the lava lake that is shaped like a Guthixian symbol, west of the Mage Arena."), new CrypticClue("Search the drawers in the upstairs of a house in Catherby.", DRAWERS_350, new WorldPoint(2809, 3451, 1), "Perdu's house in Catherby."), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java index f3a6e9acc3..7231020f74 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java @@ -138,7 +138,7 @@ public class EmoteClue extends ClueScroll implements TextClueScroll, LocationClu new EmoteClue("Panic by the big egg where no one dare goes and the ground is burnt. Beware of double agents! Equip a dragon med helm, a TokTz-Ket-Xil, a brine sabre, rune platebody and an uncharged amulet of glory.", "Lava dragon isle", SOUTHEAST_CORNER_OF_LAVA_DRAGON_ISLE, new WorldPoint(3227, 3831, 0), PANIC, item(DRAGON_MED_HELM), item(TOKTZKETXIL), item(BRINE_SABRE), item(RUNE_PLATEBODY), item(AMULET_OF_GLORY)), new EmoteClue("Panic at the area flowers meet snow. Equip Blue D'hide vambs, a dragon spear and a rune plateskirt.", "Trollweiss mountain", HALFWAY_DOWN_TROLLWEISS_MOUNTAIN, new WorldPoint(2776, 3781, 0), PANIC, item(BLUE_DHIDE_VAMB), item(DRAGON_SPEAR), item(RUNE_PLATESKIRT), item(SLED_4084)), new EmoteClue("Do a push up at the bank of the Warrior's guild. Beware of double agents! Equip a dragon battleaxe, a dragon defender and a slayer helm of any kind.", "Warriors' guild", WARRIORS_GUILD_BANK_29047, new WorldPoint(2843, 3543, 0), PUSH_UP, item(DRAGON_BATTLEAXE), item(DRAGON_DEFENDER), any("Any slayer helmet", item(SLAYER_HELMET), item(BLACK_SLAYER_HELMET), item(GREEN_SLAYER_HELMET), item(PURPLE_SLAYER_HELMET), item(RED_SLAYER_HELMET), item(TURQUOISE_SLAYER_HELMET), item(SLAYER_HELMET_I), item(BLACK_SLAYER_HELMET_I), item(GREEN_SLAYER_HELMET_I), item(PURPLE_SLAYER_HELMET_I), item(RED_SLAYER_HELMET_I), item(TURQUOISE_SLAYER_HELMET_I), item(HYDRA_SLAYER_HELMET), item(HYDRA_SLAYER_HELMET_I))), - new EmoteClue("Blow a raspberry at the bank of the Warrior's guild. Beware of double agents! Equip a dragon battleaxe, a dragon defender and a slayer helm of any kind.", "Warriors' guild", WARRIORS_GUILD_BANK_29047, new WorldPoint(2843, 3543, 0), RASPBERRY, item(DRAGON_BATTLEAXE), item(DRAGON_DEFENDER), any("Any slayer helmet", item(SLAYER_HELMET), item(BLACK_SLAYER_HELMET), item(GREEN_SLAYER_HELMET), item(PURPLE_SLAYER_HELMET), item(RED_SLAYER_HELMET), item(TURQUOISE_SLAYER_HELMET), item(SLAYER_HELMET_I), item(BLACK_SLAYER_HELMET_I), item(GREEN_SLAYER_HELMET_I), item(PURPLE_SLAYER_HELMET_I), item(RED_SLAYER_HELMET_I), item(TURQUOISE_SLAYER_HELMET_I), item(HYDRA_SLAYER_HELMET), item(HYDRA_SLAYER_HELMET_I))), + new EmoteClue("Blow a raspberry at the bank of the Warrior's guild. Beware of double agents! Equip a dragon battleaxe, a slayer helm of any kind and a dragon defender or avernic defender.", "Warriors' guild", WARRIORS_GUILD_BANK_29047, new WorldPoint(2843, 3543, 0), RASPBERRY, item(DRAGON_BATTLEAXE), any("Dragon defender or Avernic defender", item(DRAGON_DEFENDER), item(AVERNIC_DEFENDER)), any("Any slayer helmet", item(SLAYER_HELMET), item(BLACK_SLAYER_HELMET), item(GREEN_SLAYER_HELMET), item(PURPLE_SLAYER_HELMET), item(RED_SLAYER_HELMET), item(TURQUOISE_SLAYER_HELMET), item(SLAYER_HELMET_I), item(BLACK_SLAYER_HELMET_I), item(GREEN_SLAYER_HELMET_I), item(PURPLE_SLAYER_HELMET_I), item(RED_SLAYER_HELMET_I), item(TURQUOISE_SLAYER_HELMET_I), item(HYDRA_SLAYER_HELMET), item(HYDRA_SLAYER_HELMET_I))), new EmoteClue("Blow a raspberry at the monkey cage in Ardougne Zoo. Equip a studded leather body, bronze platelegs and a normal staff with no orb.", "Ardougne Zoo", NEAR_THE_PARROTS_IN_ARDOUGNE_ZOO, new WorldPoint(2607, 3282, 0), RASPBERRY, item(STUDDED_BODY), item(BRONZE_PLATELEGS), item(STAFF)), new EmoteClue("Blow raspberries outside the entrance to Keep Le Faye. Equip a coif, an iron platebody and leather gloves.", "Keep Le Faye", OUTSIDE_KEEP_LE_FAYE, new WorldPoint(2757, 3401, 0), RASPBERRY, item(COIF), item(IRON_PLATEBODY), item(LEATHER_GLOVES)), new EmoteClue("Blow a raspberry in the Fishing Guild bank. Beware of double agents! Equip an elemental shield, blue dragonhide chaps and a rune warhammer.", "Fishing Guild", FISHING_GUILD_BANK, new WorldPoint(2588, 3419, 0), RASPBERRY, item(ELEMENTAL_SHIELD), item(BLUE_DHIDE_CHAPS), item(RUNE_WARHAMMER)), @@ -216,12 +216,6 @@ public class EmoteClue extends ClueScroll implements TextClueScroll, LocationClu .leftColor(TITLED_CONTENT_COLOR) .build()); - panelComponent.getChildren().add(LineComponent.builder().left("Location:").build()); - panelComponent.getChildren().add(LineComponent.builder() - .left(getLocationName()) - .leftColor(TITLED_CONTENT_COLOR) - .build()); - if (getSecondEmote() != null) { panelComponent.getChildren().add(LineComponent.builder() @@ -230,6 +224,12 @@ public class EmoteClue extends ClueScroll implements TextClueScroll, LocationClu .build()); } + panelComponent.getChildren().add(LineComponent.builder().left("Location:").build()); + panelComponent.getChildren().add(LineComponent.builder() + .left(getLocationName()) + .leftColor(TITLED_CONTENT_COLOR) + .build()); + if (itemRequirements.length > 0) { Client client = plugin.getClient(); 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 a45b8b3f06..cecfd4525b 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 @@ -29,6 +29,7 @@ import com.google.common.base.Strings; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; +import java.awt.Dimension; import java.awt.GridLayout; import java.awt.image.BufferedImage; import java.text.DateFormat; @@ -38,6 +39,8 @@ import java.util.Date; import java.util.List; import java.util.function.BiConsumer; import javax.annotation.Nullable; +import javax.swing.Box; +import javax.swing.BoxLayout; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JMenuItem; @@ -58,12 +61,13 @@ import net.runelite.api.util.Text; class LootTrackerBox extends JPanel { private static final int ITEMS_PER_ROW = 5; + private static final int TITLE_PADDING = 5; private final JPanel itemContainer = new JPanel(); private final JLabel priceLabel = new JLabel(); private final JLabel subTitleLabel = new JLabel(); private final JLabel dateLabel = new JLabel(); - private final JPanel logTitle = new JPanel(new BorderLayout(5, 0)); + private final JPanel logTitle = new JPanel(); private final JLabel titleLabel = new JLabel(); private final ItemManager itemManager; @Getter(AccessLevel.PACKAGE) @@ -95,18 +99,19 @@ class LootTrackerBox extends JPanel setLayout(new BorderLayout(0, 1)); setBorder(new EmptyBorder(5, 0, 0, 0)); + logTitle.setLayout(new BoxLayout(logTitle, BoxLayout.X_AXIS)); logTitle.setBorder(new EmptyBorder(7, 7, 7, 7)); logTitle.setBackground(ColorScheme.DARKER_GRAY_COLOR.darker()); titleLabel.setText(Text.removeTags(id)); titleLabel.setFont(FontManager.getRunescapeSmallFont()); titleLabel.setForeground(Color.WHITE); - - logTitle.add(titleLabel, BorderLayout.WEST); + // Set a size to make BoxLayout truncate the name + titleLabel.setMinimumSize(new Dimension(1, titleLabel.getPreferredSize().height)); + logTitle.add(titleLabel); subTitleLabel.setFont(FontManager.getRunescapeSmallFont()); subTitleLabel.setForeground(ColorScheme.LIGHT_GRAY_COLOR); - logTitle.add(subTitleLabel, BorderLayout.CENTER); dateLabel.setFont(FontManager.getRunescapeSmallFont().deriveFont(FontManager.getRunescapeSmallFont().getSize() - 2)); dateLabel.setForeground(Color.LIGHT_GRAY); @@ -123,9 +128,14 @@ class LootTrackerBox extends JPanel subTitleLabel.setText(subtitle); } + logTitle.add(Box.createRigidArea(new Dimension(TITLE_PADDING, 0))); + logTitle.add(subTitleLabel); + logTitle.add(Box.createHorizontalGlue()); + logTitle.add(Box.createRigidArea(new Dimension(TITLE_PADDING, 0))); + priceLabel.setFont(FontManager.getRunescapeSmallFont()); priceLabel.setForeground(ColorScheme.LIGHT_GRAY_COLOR); - logTitle.add(priceLabel, BorderLayout.EAST); + logTitle.add(priceLabel); add(logTitle, BorderLayout.NORTH); add(itemContainer, BorderLayout.CENTER); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timers/GameTimer.java b/runelite-client/src/main/java/net/runelite/client/plugins/timers/GameTimer.java index 6e1f787c94..47febc85ec 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timers/GameTimer.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timers/GameTimer.java @@ -50,11 +50,8 @@ enum GameTimer DMM_HALFTB(SpriteID.SPELL_TELE_BLOCK, GameTimerImageType.SPRITE, "Deadman Mode Half Teleblock", 75, ChronoUnit.SECONDS, true), SUPERANTIFIRE(ItemID.SUPER_ANTIFIRE_POTION4, GameTimerImageType.ITEM, "Super antifire", 3, ChronoUnit.MINUTES), BIND(SpriteID.SPELL_BIND, GameTimerImageType.SPRITE, "Bind", GraphicID.BIND, 5, ChronoUnit.SECONDS, true), - HALFBIND(SpriteID.SPELL_BIND, GameTimerImageType.SPRITE, "Half Bind", GraphicID.BIND, 2500, ChronoUnit.MILLIS, true), SNARE(SpriteID.SPELL_SNARE, GameTimerImageType.SPRITE, "Snare", GraphicID.SNARE, 10, ChronoUnit.SECONDS, true), - HALFSNARE(SpriteID.SPELL_SNARE, GameTimerImageType.SPRITE, "Half Snare", GraphicID.SNARE, 5, ChronoUnit.SECONDS, true), ENTANGLE(SpriteID.SPELL_ENTANGLE, GameTimerImageType.SPRITE, "Entangle", GraphicID.ENTANGLE, 15, ChronoUnit.SECONDS, true), - HALFENTANGLE(SpriteID.SPELL_ENTANGLE, GameTimerImageType.SPRITE, "Half Entangle", GraphicID.ENTANGLE, 7500, ChronoUnit.MILLIS, true), ICERUSH(SpriteID.SPELL_ICE_RUSH, GameTimerImageType.SPRITE, "Ice rush", GraphicID.ICE_RUSH, 5, ChronoUnit.SECONDS, true), ICEBURST(SpriteID.SPELL_ICE_BURST, GameTimerImageType.SPRITE, "Ice burst", GraphicID.ICE_BURST, 10, ChronoUnit.SECONDS, true), ICEBLITZ(SpriteID.SPELL_ICE_BLITZ, GameTimerImageType.SPRITE, "Ice blitz", GraphicID.ICE_BLITZ, 15, ChronoUnit.SECONDS, true), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimersPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimersPlugin.java index 26ed8821b0..a05d1154ac 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimersPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimersPlugin.java @@ -47,7 +47,6 @@ import net.runelite.api.ItemID; import net.runelite.api.NPC; import net.runelite.api.NpcID; import net.runelite.api.Player; -import net.runelite.api.Prayer; import net.runelite.api.Skill; import net.runelite.api.SkullIcon; import net.runelite.api.VarPlayer; @@ -368,7 +367,7 @@ public class TimersPlugin extends Plugin removeGameTimer(DIVINE_RANGING); removeGameTimer(DIVINE_MAGIC); } - + if (!this.showCannon) { removeGameTimer(CANNON); @@ -412,11 +411,8 @@ public class TimersPlugin extends Plugin if (!this.showFreezes) { removeGameTimer(BIND); - removeGameTimer(HALFBIND); removeGameTimer(SNARE); - removeGameTimer(HALFSNARE); removeGameTimer(ENTANGLE); - removeGameTimer(HALFENTANGLE); removeGameTimer(ICERUSH); removeGameTimer(ICEBURST); removeGameTimer(ICEBLITZ); @@ -698,6 +694,12 @@ public class TimersPlugin extends Plugin loggedInRace = false; Player player = client.getLocalPlayer(); + + if (player == null) + { + return; + } + WorldPoint currentWorldPoint = player.getWorldLocation(); final boolean isSkulled = player.getSkullIcon() != null && player.getSkullIcon() != SkullIcon.SKULL_FIGHT_PIT; @@ -786,13 +788,15 @@ public class TimersPlugin extends Plugin } } - if (actor != client.getLocalPlayer()) + Player player = client.getLocalPlayer(); + + if (player == null || actor != player) { return; } if (this.showHomeMinigameTeleports - && client.getLocalPlayer().getAnimation() == AnimationID.IDLE + && player.getAnimation() == AnimationID.IDLE && (lastAnimation == AnimationID.BOOK_HOME_TELEPORT_5 || lastAnimation == AnimationID.COW_HOME_TELEPORT_6)) { @@ -811,14 +815,15 @@ public class TimersPlugin extends Plugin createGameTimer(DRAGON_FIRE_SHIELD); } - lastAnimation = client.getLocalPlayer().getAnimation(); + lastAnimation = player.getAnimation(); } private void onSpotAnimationChanged(SpotAnimationChanged event) { Actor actor = event.getActor(); + Player player = client.getLocalPlayer(); - if (actor != client.getLocalPlayer()) + if (player == null || actor != client.getLocalPlayer()) { return; } @@ -832,44 +837,17 @@ public class TimersPlugin extends Plugin { if (actor.getSpotAnimation() == BIND.getGraphicId()) { - if (client.isPrayerActive(Prayer.PROTECT_FROM_MAGIC) - && !client.getWorldType().contains(WorldType.SEASONAL_DEADMAN) - && !client.getWorldType().contains(WorldType.DEADMAN_TOURNAMENT)) - { - createGameTimer(HALFBIND); - } - else - { - createGameTimer(BIND); - } + createGameTimer(BIND); } if (actor.getSpotAnimation() == SNARE.getGraphicId()) { - if (client.isPrayerActive(Prayer.PROTECT_FROM_MAGIC) - && !client.getWorldType().contains(WorldType.SEASONAL_DEADMAN) - && !client.getWorldType().contains(WorldType.DEADMAN_TOURNAMENT)) - { - createGameTimer(HALFSNARE); - } - else - { - createGameTimer(SNARE); - } + createGameTimer(SNARE); } if (actor.getSpotAnimation() == ENTANGLE.getGraphicId()) { - if (client.isPrayerActive(Prayer.PROTECT_FROM_MAGIC) - && !client.getWorldType().contains(WorldType.SEASONAL_DEADMAN) - && !client.getWorldType().contains(WorldType.DEADMAN_TOURNAMENT)) - { - createGameTimer(HALFENTANGLE); - } - else - { - createGameTimer(ENTANGLE); - } + createGameTimer(ENTANGLE); } // downgrade freeze based on graphic, if at the same tick as the freeze message diff --git a/runelite-client/src/main/scripts/BankSearchFilter.rs2asm b/runelite-client/src/main/scripts/BankSearchFilter.rs2asm index fd3f415b5d..5f9db325af 100644 --- a/runelite-client/src/main/scripts/BankSearchFilter.rs2asm +++ b/runelite-client/src/main/scripts/BankSearchFilter.rs2asm @@ -1,7 +1,7 @@ .id 279 .int_stack_count 1 .string_stack_count 0 -.int_var_count 1 +.int_var_count 2 ; +1 for storage of search filter result .string_var_count 2 sconst "" sstore 0 @@ -30,16 +30,7 @@ LABEL19: oc_name lowercase sstore 0 -LABEL1337:; check if the bank tags plugin is active - iconst 1 ; true - iconst 0 ; load active boolean - sconst "bankTagsActive" ; push event name - runelite_callback ; invoke callback - if_icmpeq LABEL1338 ; if the plugin is active then jump to the label that decides if the - ; item should be shown - jump LABEL23 ; if the plugin is not active then jump to the normal label -LABEL1338:; let the bank tag plugin decide if the item should be shown - iconst 0 ; load return value + iconst -1 ; load return value iload 0 ; load item id sload 0 ; load item name sload 1 ; load search string @@ -48,7 +39,13 @@ LABEL1338:; let the bank tag plugin decide if the item should be shown pop_int ; pop item id pop_string ; pop search string pop_string ; pop item name - return ; return value + istore 1 ; store return value for the below comparisons + iload 1 + iconst 0 + if_icmpeq LABEL32 ; return 0 + iload 1 + iconst 1 + if_icmpeq LABEL30 ; return 1 LABEL23: sload 0 sload 1 diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/bank/BankPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/bank/BankPluginTest.java new file mode 100644 index 0000000000..307190aaf7 --- /dev/null +++ b/runelite-client/src/test/java/net/runelite/client/plugins/bank/BankPluginTest.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2019, Ron Young + * Copyright (c) 2019, 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.plugins.bank; + +import com.google.inject.Guice; +import com.google.inject.testing.fieldbinder.Bind; +import com.google.inject.testing.fieldbinder.BoundFieldModule; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.InventoryID; +import net.runelite.api.Item; +import net.runelite.api.ItemContainer; +import net.runelite.api.ItemDefinition; +import net.runelite.api.ItemID; +import net.runelite.client.game.ItemManager; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import org.mockito.runners.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class BankPluginTest +{ + @Mock + @Bind + private Client client; + + @Mock + @Bind + private ItemManager itemManager; + + @Mock + @Bind + private BankConfig bankConfig; + + @Inject + private BankPlugin bankPlugin; + + @Before + public void before() + { + Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); + } + + @Test + public void testValueSearch() + { + int itemId = ItemID.ABYSSAL_WHIP; + + ItemContainer itemContainer = mock(ItemContainer.class); + when(itemContainer.getItems()).thenReturn(new Item[]{new Item(itemId, 30)}); + when(client.getItemContainer(InventoryID.BANK)).thenReturn(itemContainer); + + ItemDefinition comp = mock(ItemDefinition.class); + + // 60k HA price * 30 = 1.8m + when(comp.getPrice()) + .thenReturn(100_000); + + // 400k GE Price * 30 = 12m + when(itemManager.getItemPrice(itemId)) + .thenReturn(400_000); + when(itemManager.getItemDefinition(itemId)) + .thenReturn(comp); + + assertTrue(bankPlugin.valueSearch(itemId, ">500k")); + assertTrue(bankPlugin.valueSearch(itemId, "< 5.5b")); + assertTrue(bankPlugin.valueSearch(itemId, "500k - 20.6m")); + + assertTrue(bankPlugin.valueSearch(itemId, "ha=1.8m")); + assertTrue(bankPlugin.valueSearch(itemId, "ha 500k - 20.6m")); + assertTrue(bankPlugin.valueSearch(itemId, "ha > 940k")); + + assertFalse(bankPlugin.valueSearch(itemId, "<500k")); + assertFalse(bankPlugin.valueSearch(itemId, "ha >2m")); + assertFalse(bankPlugin.valueSearch(itemId, "ge > 0.02b")); + + assertFalse(bankPlugin.valueSearch(itemId, "1000k")); + } +} \ No newline at end of file