From 14b654c9a5326ce62db427a5081822fe8693e6d9 Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Thu, 2 Aug 2018 01:01:28 +0200 Subject: [PATCH] Account for linked item id, format tooltip - Account for linked item id when getting item price - Format item price tooltip - Create new data structure for loot tracker and precompute it to avoid calling methods that are unsafe outside of client thread Signed-off-by: Tomas Slusny --- .../plugins/loottracker/LootTrackerBox.java | 33 ++++------- .../loottracker/LootTrackerItemEntry.java | 36 ++++++++++++ .../plugins/loottracker/LootTrackerPanel.java | 3 +- .../loottracker/LootTrackerPlugin.java | 55 ++++++++++++++----- 4 files changed, 90 insertions(+), 37 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerItemEntry.java 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 b56781b999..6aaeea1977 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 @@ -34,13 +34,10 @@ import javax.swing.JPanel; import javax.swing.SwingConstants; import javax.swing.border.EmptyBorder; import lombok.Getter; -import net.runelite.api.ItemID; import net.runelite.client.game.ItemManager; -import net.runelite.client.game.ItemStack; import net.runelite.client.ui.ColorScheme; import net.runelite.client.ui.FontManager; import net.runelite.client.util.StackFormatter; -import net.runelite.http.api.item.ItemPrice; @Getter class LootTrackerBox extends JPanel @@ -48,7 +45,7 @@ class LootTrackerBox extends JPanel private static final int ITEMS_PER_ROW = 5; private final long totalPrice; - LootTrackerBox(final ItemManager itemManager, final String title, final String subTitle, final ItemStack[] items) + LootTrackerBox(final ItemManager itemManager, final String title, final String subTitle, final LootTrackerItemEntry[] items) { setLayout(new BorderLayout(0, 1)); setBorder(new EmptyBorder(5, 0, 0, 0)); @@ -72,7 +69,7 @@ class LootTrackerBox extends JPanel logTitle.add(subTitleLabel, BorderLayout.CENTER); } - totalPrice = calculatePrice(itemManager, items); + totalPrice = calculatePrice(items); if (totalPrice > 0) { @@ -93,9 +90,9 @@ class LootTrackerBox extends JPanel if (i < items.length) { - final ItemStack item = items[i]; + final LootTrackerItemEntry item = items[i]; final JLabel imageLabel = new JLabel(); - imageLabel.setToolTipText(buildToolTip(itemManager, item)); + imageLabel.setToolTipText(buildToolTip(item)); imageLabel.setVerticalAlignment(SwingConstants.CENTER); imageLabel.setHorizontalAlignment(SwingConstants.CENTER); itemManager.getImage(item.getId(), item.getQuantity(), item.getQuantity() > 1).addTo(imageLabel); @@ -109,29 +106,21 @@ class LootTrackerBox extends JPanel add(itemContainer, BorderLayout.CENTER); } - private String buildToolTip(ItemManager itemManager, ItemStack item) + private String buildToolTip(LootTrackerItemEntry item) { - final String name = itemManager.getItemComposition(item.getId()).getName(); + final String name = item.getName(); final int quantity = item.getQuantity(); - final long price = calculatePrice(itemManager, new ItemStack[]{item}); + final long price = item.getPrice(); - return name + " x " + quantity + " (" + price + ")"; + return name + " x " + quantity + " (" + StackFormatter.quantityToStackSize(price) + ")"; } - private static long calculatePrice(final ItemManager itemManager, final ItemStack[] itemStacks) + private static long calculatePrice(final LootTrackerItemEntry[] itemStacks) { long total = 0; - for (ItemStack itemStack : itemStacks) + for (LootTrackerItemEntry itemStack : itemStacks) { - ItemPrice itemPrice = itemManager.getItemPrice(itemStack.getId()); - if (itemPrice != null) - { - total += (long) itemPrice.getPrice() * itemStack.getQuantity(); - } - else if (itemStack.getId() == ItemID.COINS_995) - { - total += itemStack.getQuantity(); - } + total += itemStack.getPrice(); } return total; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerItemEntry.java b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerItemEntry.java new file mode 100644 index 0000000000..3d18ce9c0b --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerItemEntry.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018, Tomas Slusny + * 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.loottracker; + +import lombok.Value; + +@Value +class LootTrackerItemEntry +{ + private final int id; + private final String name; + private final int quantity; + private final long price; +} 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 57885dcda6..be6dda7ab3 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 @@ -37,7 +37,6 @@ import javax.swing.JPopupMenu; import javax.swing.border.EmptyBorder; import lombok.extern.slf4j.Slf4j; import net.runelite.client.game.ItemManager; -import net.runelite.client.game.ItemStack; import net.runelite.client.ui.ColorScheme; import net.runelite.client.ui.FontManager; import net.runelite.client.ui.PluginPanel; @@ -134,7 +133,7 @@ class LootTrackerPanel extends PluginPanel return String.format(HTML_LABEL_TEMPLATE, ColorUtil.toHexColor(ColorScheme.LIGHT_GRAY_COLOR), key, valueStr); } - void addLog(final String eventName, final int actorLevel, ItemStack[] items) + void addLog(final String eventName, final int actorLevel, LootTrackerItemEntry[] items) { // Remove error and show overall remove(errorPanel); 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 7773587231..3817e1a67b 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 @@ -33,6 +33,7 @@ import java.util.Collection; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; import javax.imageio.ImageIO; import javax.inject.Inject; import javax.swing.SwingUtilities; @@ -40,7 +41,9 @@ import lombok.extern.slf4j.Slf4j; import net.runelite.api.ChatMessageType; import net.runelite.api.Client; import net.runelite.api.InventoryID; +import net.runelite.api.ItemComposition; import net.runelite.api.ItemContainer; +import net.runelite.api.ItemID; import net.runelite.api.NPC; import net.runelite.api.Player; import net.runelite.api.SpriteID; @@ -57,6 +60,7 @@ import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.ui.ClientToolbar; import net.runelite.client.ui.NavigationButton; import net.runelite.client.util.Text; +import net.runelite.http.api.item.ItemPrice; @PluginDescriptor( name = "Loot Tracker", @@ -150,8 +154,8 @@ public class LootTrackerPlugin extends Plugin final Collection items = npcLootReceived.getItems(); final String name = npc.getName(); final int combat = npc.getCombatLevel(); - final Collection stackedItems = stack(items); - SwingUtilities.invokeLater(() -> panel.addLog(name, combat, stackedItems.toArray(new ItemStack[0]))); + final LootTrackerItemEntry[] entries = buildEntries(stack(items)); + SwingUtilities.invokeLater(() -> panel.addLog(name, combat, entries)); } @Subscribe @@ -161,8 +165,8 @@ public class LootTrackerPlugin extends Plugin final Collection items = playerLootReceived.getItems(); final String name = player.getName(); final int combat = player.getCombatLevel(); - final Collection stackedItems = stack(items); - SwingUtilities.invokeLater(() -> panel.addLog(name, combat, stackedItems.toArray(new ItemStack[0]))); + final LootTrackerItemEntry[] entries = buildEntries(stack(items)); + SwingUtilities.invokeLater(() -> panel.addLog(name, combat, entries)); } @Subscribe @@ -198,18 +202,14 @@ public class LootTrackerPlugin extends Plugin } // Convert container items to array of ItemStack - final ItemStack[] items = Arrays.stream(container.getItems()) + final Collection items = Arrays.stream(container.getItems()) .map(item -> new ItemStack(item.getId(), item.getQuantity())) - .toArray(ItemStack[]::new); + .collect(Collectors.toList()); - if (items.length > 0) + if (!items.isEmpty()) { - log.debug("Loot Received from Event: {}", eventType); - for (ItemStack item : items) - { - log.debug("Item Received: {}x {}", item.getQuantity(), item.getId()); - } - SwingUtilities.invokeLater(() -> panel.addLog(eventType, -1, items)); + final LootTrackerItemEntry[] entries = buildEntries(stack(items)); + SwingUtilities.invokeLater(() -> panel.addLog(eventType, -1, entries)); } else { @@ -250,4 +250,33 @@ public class LootTrackerPlugin extends Plugin } } } + + private LootTrackerItemEntry[] buildEntries(final Collection itemStacks) + { + return itemStacks.stream().map(itemStack -> + { + final ItemComposition itemComposition = itemManager.getItemComposition(itemStack.getId()); + final int realItemId = itemComposition.getNote() != -1 ? itemComposition.getLinkedNoteId() : itemStack.getId(); + final ItemPrice itemPrice = itemManager.getItemPrice(realItemId); + final long price; + if (itemPrice != null) + { + price = (long) itemPrice.getPrice() * itemStack.getQuantity(); + } + else if (realItemId == ItemID.COINS_995) + { + price = itemStack.getQuantity(); + } + else + { + price = 0; + } + + return new LootTrackerItemEntry( + itemStack.getId(), + itemComposition.getName(), + itemStack.getQuantity(), + price); + }).toArray(LootTrackerItemEntry[]::new); + } }