loot tracker: add view for grouping loot by npc/event

This commit is contained in:
Ruben Amendoeira
2018-09-13 01:03:50 +01:00
committed by Adam
parent 7a99eaf4f7
commit 4dd8322121
8 changed files with 445 additions and 68 deletions

View File

@@ -29,6 +29,10 @@ import com.google.common.base.Strings;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.annotation.Nullable;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
@@ -39,14 +43,26 @@ import net.runelite.client.ui.ColorScheme;
import net.runelite.client.ui.FontManager;
import net.runelite.client.util.StackFormatter;
@Getter
class LootTrackerBox extends JPanel
{
private static final int ITEMS_PER_ROW = 5;
private final long totalPrice;
private final JPanel itemContainer = new JPanel();
private final JLabel priceLabel = new JLabel();
private final JLabel subTitleLabel = new JLabel();
private final ItemManager itemManager;
private final String id;
LootTrackerBox(final ItemManager itemManager, final String title, final String subTitle, final LootTrackerItemEntry[] items)
@Getter
private final List<LootTrackerRecord> records = new ArrayList<>();
@Getter
private long totalPrice;
LootTrackerBox(final ItemManager itemManager, final String id, @Nullable final String subtitle)
{
this.id = id;
this.itemManager = itemManager;
setLayout(new BorderLayout(0, 1));
setBorder(new EmptyBorder(5, 0, 0, 0));
@@ -54,43 +70,140 @@ class LootTrackerBox extends JPanel
logTitle.setBorder(new EmptyBorder(7, 7, 7, 7));
logTitle.setBackground(ColorScheme.DARKER_GRAY_COLOR.darker());
final JLabel titleLabel = new JLabel(title);
final JLabel titleLabel = new JLabel(id);
titleLabel.setFont(FontManager.getRunescapeSmallFont());
titleLabel.setForeground(Color.WHITE);
logTitle.add(titleLabel, BorderLayout.WEST);
// If we have subtitle, add it
if (!Strings.isNullOrEmpty(subTitle))
if (!Strings.isNullOrEmpty(subtitle))
{
final JLabel subTitleLabel = new JLabel(subTitle);
subTitleLabel.setText(subtitle);
subTitleLabel.setFont(FontManager.getRunescapeSmallFont());
subTitleLabel.setForeground(ColorScheme.LIGHT_GRAY_COLOR);
logTitle.add(subTitleLabel, BorderLayout.CENTER);
}
totalPrice = calculatePrice(items);
priceLabel.setFont(FontManager.getRunescapeSmallFont());
priceLabel.setForeground(ColorScheme.LIGHT_GRAY_COLOR);
logTitle.add(priceLabel, BorderLayout.EAST);
if (totalPrice > 0)
add(logTitle, BorderLayout.NORTH);
add(itemContainer, BorderLayout.CENTER);
}
int getTotalKills()
{
return records.size();
}
/**
* Checks if this box matches specified record
* @param record loot record
* @return true if match is made
*/
boolean matches(final LootTrackerRecord record)
{
return record.getTitle().equals(id);
}
/**
* Checks if this box matches specified id
* @param id other record id
* @return true if match is made
*/
boolean matches(final String id)
{
if (id == null)
{
final JLabel priceLabel = new JLabel(StackFormatter.quantityToStackSize(totalPrice) + " gp");
priceLabel.setFont(FontManager.getRunescapeSmallFont());
priceLabel.setForeground(ColorScheme.LIGHT_GRAY_COLOR);
logTitle.add(priceLabel, BorderLayout.EAST);
return true;
}
return this.id.equals(id);
}
/**
* Adds an record's data into a loot box.
* This will add new items to the list, re-calculating price and kill count.
*/
void combine(final LootTrackerRecord record)
{
if (!matches(record))
{
throw new IllegalArgumentException(record.toString());
}
records.add(record);
buildItems();
priceLabel.setText(StackFormatter.quantityToStackSize(totalPrice) + " gp");
if (records.size() > 1)
{
subTitleLabel.setText("x " + records.size());
}
repaint();
}
/**
* This method creates stacked items from the item list, calculates total price and then
* displays all the items in the UI.
*/
private void buildItems()
{
final List<LootTrackerItem> allItems = new ArrayList<>();
final List<LootTrackerItem> items = new ArrayList<>();
totalPrice = 0;
for (LootTrackerRecord records : records)
{
allItems.addAll(Arrays.asList(records.getItems()));
}
for (final LootTrackerItem entry : allItems)
{
totalPrice += entry.getPrice();
int quantity = 0;
for (final LootTrackerItem i : items)
{
if (i.getId() == entry.getId())
{
quantity = i.getQuantity();
items.remove(i);
break;
}
}
if (quantity > 0)
{
int newQuantity = entry.getQuantity() + quantity;
long pricePerItem = entry.getPrice() == 0 ? 0 : (entry.getPrice() / entry.getQuantity());
items.add(new LootTrackerItem(entry.getId(), entry.getName(), newQuantity, pricePerItem * newQuantity));
}
else
{
items.add(entry);
}
}
items.sort((i1, i2) -> Long.compare(i2.getPrice(), i1.getPrice()));
// Calculates how many rows need to be display to fit all items
final int rowSize = ((items.length % ITEMS_PER_ROW == 0) ? 0 : 1) + items.length / ITEMS_PER_ROW;
final JPanel itemContainer = new JPanel(new GridLayout(rowSize, ITEMS_PER_ROW, 1, 1));
final int rowSize = ((items.size() % ITEMS_PER_ROW == 0) ? 0 : 1) + items.size() / ITEMS_PER_ROW;
itemContainer.removeAll();
itemContainer.setLayout(new GridLayout(rowSize, ITEMS_PER_ROW, 1, 1));
for (int i = 0; i < rowSize * ITEMS_PER_ROW; i++)
{
final JPanel slotContainer = new JPanel();
slotContainer.setBackground(ColorScheme.DARKER_GRAY_COLOR);
if (i < items.length)
if (i < items.size())
{
final LootTrackerItemEntry item = items[i];
final LootTrackerItem item = items.get(i);
final JLabel imageLabel = new JLabel();
imageLabel.setToolTipText(buildToolTip(item));
imageLabel.setVerticalAlignment(SwingConstants.CENTER);
@@ -102,26 +215,14 @@ class LootTrackerBox extends JPanel
itemContainer.add(slotContainer);
}
add(logTitle, BorderLayout.NORTH);
add(itemContainer, BorderLayout.CENTER);
itemContainer.repaint();
}
private String buildToolTip(LootTrackerItemEntry item)
private static String buildToolTip(LootTrackerItem item)
{
final String name = item.getName();
final int quantity = item.getQuantity();
final long price = item.getPrice();
return name + " x " + quantity + " (" + StackFormatter.quantityToStackSize(price) + ")";
}
private static long calculatePrice(final LootTrackerItemEntry[] itemStacks)
{
long total = 0;
for (LootTrackerItemEntry itemStack : itemStacks)
{
total += itemStack.getPrice();
}
return total;
}
}

View File

@@ -27,7 +27,7 @@ package net.runelite.client.plugins.loottracker;
import lombok.Value;
@Value
class LootTrackerItemEntry
class LootTrackerItem
{
private final int id;
private final String name;

View File

@@ -26,8 +26,15 @@
package net.runelite.client.plugins.loottracker;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
@@ -41,17 +48,27 @@ import net.runelite.client.ui.FontManager;
import net.runelite.client.ui.PluginPanel;
import net.runelite.client.ui.components.PluginErrorPanel;
import net.runelite.client.util.ColorUtil;
import net.runelite.client.util.ImageUtil;
import net.runelite.client.util.StackFormatter;
class LootTrackerPanel extends PluginPanel
{
private static final ImageIcon SINGLE_LOOT_VIEW;
private static final ImageIcon SINGLE_LOOT_VIEW_FADED;
private static final ImageIcon SINGLE_LOOT_VIEW_HOVER;
private static final ImageIcon GROUPED_LOOT_VIEW;
private static final ImageIcon GROUPED_LOOT_VIEW_FADED;
private static final ImageIcon GROUPED_LOOT_VIEW_HOVER;
private static final ImageIcon BACK_ARROW_ICON;
private static final ImageIcon BACK_ARROW_ICON_HOVER;
private static final String HTML_LABEL_TEMPLATE =
"<html><body style='color:%s'>%s<span style='color:white'>%s</span></body></html>";
// When there is no loot, display this
private final PluginErrorPanel errorPanel = new PluginErrorPanel();
// Handle loot logs
// Handle loot boxes
private final JPanel logsContainer = new JPanel();
// Handle overall session data
@@ -59,9 +76,39 @@ class LootTrackerPanel extends PluginPanel
private final JLabel overallKillsLabel = new JLabel();
private final JLabel overallGpLabel = new JLabel();
private final JLabel overallIcon = new JLabel();
// Details and navigation
private final JPanel actionsContainer = new JPanel();
private final JLabel detailsTitle = new JLabel();
private final JLabel backBtn = new JLabel();
private final JLabel singleLootBtn = new JLabel();
private final JLabel groupedLootBtn = new JLabel();
// Log collection
private final List<LootTrackerRecord> records = new ArrayList<>();
private final List<LootTrackerBox> boxes = new ArrayList<>();
private final ItemManager itemManager;
private int overallKills;
private int overallGp;
private boolean groupLoot;
private String currentView;
static
{
final BufferedImage singleLootImg = ImageUtil.getResourceStreamFromClass(LootTrackerPlugin.class, "single_loot_icon.png");
final BufferedImage groupedLootImg = ImageUtil.getResourceStreamFromClass(LootTrackerPlugin.class, "grouped_loot_icon.png");
final BufferedImage backArrowImg = ImageUtil.getResourceStreamFromClass(LootTrackerPlugin.class, "back_icon.png");
SINGLE_LOOT_VIEW = new ImageIcon(singleLootImg);
SINGLE_LOOT_VIEW_FADED = new ImageIcon(ImageUtil.alphaOffset(singleLootImg, -180));
SINGLE_LOOT_VIEW_HOVER = new ImageIcon(ImageUtil.alphaOffset(singleLootImg, -220));
GROUPED_LOOT_VIEW = new ImageIcon(groupedLootImg);
GROUPED_LOOT_VIEW_FADED = new ImageIcon(ImageUtil.alphaOffset(groupedLootImg, -180));
GROUPED_LOOT_VIEW_HOVER = new ImageIcon(ImageUtil.alphaOffset(groupedLootImg, -220));
BACK_ARROW_ICON = new ImageIcon(backArrowImg);
BACK_ARROW_ICON_HOVER = new ImageIcon(ImageUtil.alphaOffset(backArrowImg, -180));
}
LootTrackerPanel(final ItemManager itemManager)
{
@@ -75,8 +122,104 @@ class LootTrackerPanel extends PluginPanel
layoutPanel.setLayout(new BoxLayout(layoutPanel, BoxLayout.Y_AXIS));
add(layoutPanel, BorderLayout.NORTH);
actionsContainer.setLayout(new BorderLayout());
actionsContainer.setBackground(ColorScheme.DARKER_GRAY_COLOR);
actionsContainer.setPreferredSize(new Dimension(0, 30));
actionsContainer.setBorder(new EmptyBorder(5, 5, 5, 10));
actionsContainer.setVisible(false);
final JPanel viewControls = new JPanel(new GridLayout(1, 2, 10, 0));
viewControls.setBackground(ColorScheme.DARKER_GRAY_COLOR);
singleLootBtn.setIcon(SINGLE_LOOT_VIEW);
singleLootBtn.setToolTipText("Show each kill separately");
singleLootBtn.addMouseListener(new MouseAdapter()
{
@Override
public void mousePressed(MouseEvent mouseEvent)
{
changeGrouping(false);
}
@Override
public void mouseExited(MouseEvent mouseEvent)
{
singleLootBtn.setIcon(groupLoot ? SINGLE_LOOT_VIEW_FADED : SINGLE_LOOT_VIEW);
}
@Override
public void mouseEntered(MouseEvent mouseEvent)
{
singleLootBtn.setIcon(groupLoot ? SINGLE_LOOT_VIEW_HOVER : SINGLE_LOOT_VIEW);
}
});
groupedLootBtn.setIcon(GROUPED_LOOT_VIEW);
groupedLootBtn.setToolTipText("Group loot by source");
groupedLootBtn.addMouseListener(new MouseAdapter()
{
@Override
public void mousePressed(MouseEvent mouseEvent)
{
changeGrouping(true);
}
@Override
public void mouseExited(MouseEvent mouseEvent)
{
groupedLootBtn.setIcon(groupLoot ? GROUPED_LOOT_VIEW : GROUPED_LOOT_VIEW_FADED);
}
@Override
public void mouseEntered(MouseEvent mouseEvent)
{
groupedLootBtn.setIcon(groupLoot ? GROUPED_LOOT_VIEW : GROUPED_LOOT_VIEW_HOVER);
}
});
viewControls.add(groupedLootBtn);
viewControls.add(singleLootBtn);
changeGrouping(true);
final JPanel leftTitleContainer = new JPanel(new BorderLayout(5, 0));
leftTitleContainer.setBackground(ColorScheme.DARKER_GRAY_COLOR);
detailsTitle.setForeground(Color.WHITE);
backBtn.setIcon(BACK_ARROW_ICON);
backBtn.setVisible(false);
backBtn.addMouseListener(new MouseAdapter()
{
@Override
public void mousePressed(MouseEvent mouseEvent)
{
currentView = null;
backBtn.setVisible(false);
detailsTitle.setText("");
rebuild();
}
@Override
public void mouseExited(MouseEvent mouseEvent)
{
backBtn.setIcon(BACK_ARROW_ICON);
}
@Override
public void mouseEntered(MouseEvent mouseEvent)
{
backBtn.setIcon(BACK_ARROW_ICON_HOVER);
}
});
leftTitleContainer.add(backBtn, BorderLayout.WEST);
leftTitleContainer.add(detailsTitle, BorderLayout.CENTER);
actionsContainer.add(leftTitleContainer, BorderLayout.WEST);
actionsContainer.add(viewControls, BorderLayout.EAST);
// Create panel that will contain overall data
overallPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
overallPanel.setBorder(new EmptyBorder(8, 10, 8, 10));
overallPanel.setBackground(ColorScheme.DARKER_GRAY_COLOR);
overallPanel.setLayout(new BorderLayout());
overallPanel.setVisible(false);
@@ -85,7 +228,7 @@ class LootTrackerPanel extends PluginPanel
final JPanel overallInfo = new JPanel();
overallInfo.setBackground(ColorScheme.DARKER_GRAY_COLOR);
overallInfo.setLayout(new GridLayout(2, 1));
overallInfo.setBorder(new EmptyBorder(0, 10, 0, 0));
overallInfo.setBorder(new EmptyBorder(2, 10, 2, 0));
overallKillsLabel.setFont(FontManager.getRunescapeSmallFont());
overallGpLabel.setFont(FontManager.getRunescapeSmallFont());
overallInfo.add(overallKillsLabel);
@@ -97,8 +240,9 @@ class LootTrackerPanel extends PluginPanel
final JMenuItem reset = new JMenuItem("Reset All");
reset.addActionListener(e ->
{
overallKills = 0;
overallGp = 0;
// If not in detailed view, remove all, otherwise only remove for the currently detailed title
records.removeIf(r -> r.matches(currentView));
boxes.removeIf(b -> b.matches(currentView));
updateOverall();
logsContainer.removeAll();
logsContainer.repaint();
@@ -110,8 +254,10 @@ class LootTrackerPanel extends PluginPanel
popupMenu.add(reset);
overallPanel.setComponentPopupMenu(popupMenu);
// Create loot logs wrapper
// Create loot boxes wrapper
logsContainer.setLayout(new BoxLayout(logsContainer, BoxLayout.Y_AXIS));
layoutPanel.add(actionsContainer);
layoutPanel.add(Box.createRigidArea(new Dimension(0, 5)));
layoutPanel.add(overallPanel);
layoutPanel.add(logsContainer);
@@ -125,50 +271,129 @@ class LootTrackerPanel extends PluginPanel
overallIcon.setIcon(new ImageIcon(img));
}
private static String htmlLabel(String key, long value)
/**
* Adds a new entry to the plugin.
* Creates a subtitle, adds a new entry and then passes off to the render methods, that will decide
* how to display this new data.
*/
void add(final String eventName, final int actorLevel, LootTrackerItem[] items)
{
final String valueStr = StackFormatter.quantityToStackSize(value);
return String.format(HTML_LABEL_TEMPLATE, ColorUtil.toHexColor(ColorScheme.LIGHT_GRAY_COLOR), key, valueStr);
final String subTitle = actorLevel > -1 ? "(lvl-" + actorLevel + ")" : "";
final LootTrackerRecord record = new LootTrackerRecord(eventName, subTitle, items, System.currentTimeMillis());
records.add(record);
buildBox(record);
}
void addLog(final String eventName, final int actorLevel, LootTrackerItemEntry[] items)
/**
* Changes grouping mode of panel
* @param group if loot should be grouped or not
*/
private void changeGrouping(boolean group)
{
// Remove error and show overall
groupLoot = group;
rebuild();
groupedLootBtn.setIcon(group ? GROUPED_LOOT_VIEW : GROUPED_LOOT_VIEW_FADED);
singleLootBtn.setIcon(group ? SINGLE_LOOT_VIEW_FADED : SINGLE_LOOT_VIEW);
}
/**
* Rebuilds all the boxes from scratch using existing listed records, depending on the grouping mode.
*/
private void rebuild()
{
logsContainer.removeAll();
boxes.clear();
records.forEach(this::buildBox);
updateOverall();
logsContainer.revalidate();
logsContainer.repaint();
}
/**
* This method decides what to do with a new record, if a similar log exists, it will
* add its items to it, updating the log's overall price and kills. If not, a new log will be created
* to hold this entry's information.
*/
private void buildBox(LootTrackerRecord record)
{
// If this record is not part of current view, return
if (!record.matches(currentView))
{
return;
}
// Group all similar loot together
if (groupLoot)
{
for (LootTrackerBox box : boxes)
{
if (box.matches(record))
{
box.combine(record);
updateOverall();
return;
}
}
}
// Show main view
remove(errorPanel);
actionsContainer.setVisible(true);
overallPanel.setVisible(true);
// Create box
final String subTitle = actorLevel > -1 ? "(lvl-" + actorLevel + ")" : "";
final LootTrackerBox box = new LootTrackerBox(itemManager, eventName, subTitle, items);
logsContainer.add(box, 0);
logsContainer.repaint();
final LootTrackerBox box = new LootTrackerBox(itemManager, record.getTitle(), record.getSubTitle());
box.combine(record);
// Update overall
overallGp += box.getTotalPrice();
overallKills += 1;
updateOverall();
// Create popup menu
final JPopupMenu popupMenu = new JPopupMenu();
popupMenu.setBorder(new EmptyBorder(5, 5, 5, 5));
box.setComponentPopupMenu(popupMenu);
// Create reset menu
final JMenuItem reset = new JMenuItem("Reset");
reset.addActionListener(e ->
{
overallGp -= box.getTotalPrice();
overallKills -= 1;
records.removeAll(box.getRecords());
boxes.remove(box);
updateOverall();
logsContainer.remove(box);
logsContainer.repaint();
});
// Create popup menu
final JPopupMenu popupMenu = new JPopupMenu();
popupMenu.setBorder(new EmptyBorder(5, 5, 5, 5));
popupMenu.add(reset);
box.setComponentPopupMenu(popupMenu);
// Create details menu
final JMenuItem details = new JMenuItem("View details");
details.addActionListener(e ->
{
currentView = record.getTitle();
detailsTitle.setText(currentView);
backBtn.setVisible(true);
rebuild();
});
popupMenu.add(details);
// Add box to panel
boxes.add(box);
logsContainer.add(box, 0);
// Update overall
updateOverall();
}
private void updateOverall()
{
final long overallGp = boxes.stream().mapToLong(LootTrackerBox::getTotalPrice).sum();
final int overallKills = boxes.stream().mapToInt(LootTrackerBox::getTotalKills).sum();
overallKillsLabel.setText(htmlLabel("Total count: ", overallKills));
overallGpLabel.setText(htmlLabel("Total value: ", overallGp));
}
private static String htmlLabel(String key, long value)
{
final String valueStr = StackFormatter.quantityToStackSize(value);
return String.format(HTML_LABEL_TEMPLATE, ColorUtil.toHexColor(ColorScheme.LIGHT_GRAY_COLOR), key, valueStr);
}
}

View File

@@ -150,8 +150,8 @@ public class LootTrackerPlugin extends Plugin
final Collection<ItemStack> items = npcLootReceived.getItems();
final String name = npc.getName();
final int combat = npc.getCombatLevel();
final LootTrackerItemEntry[] entries = buildEntries(stack(items));
SwingUtilities.invokeLater(() -> panel.addLog(name, combat, entries));
final LootTrackerItem[] entries = buildEntries(stack(items));
SwingUtilities.invokeLater(() -> panel.add(name, combat, entries));
}
@Subscribe
@@ -161,8 +161,8 @@ public class LootTrackerPlugin extends Plugin
final Collection<ItemStack> items = playerLootReceived.getItems();
final String name = player.getName();
final int combat = player.getCombatLevel();
final LootTrackerItemEntry[] entries = buildEntries(stack(items));
SwingUtilities.invokeLater(() -> panel.addLog(name, combat, entries));
final LootTrackerItem[] entries = buildEntries(stack(items));
SwingUtilities.invokeLater(() -> panel.add(name, combat, entries));
}
@Subscribe
@@ -209,8 +209,8 @@ public class LootTrackerPlugin extends Plugin
if (!items.isEmpty())
{
final LootTrackerItemEntry[] entries = buildEntries(stack(items));
SwingUtilities.invokeLater(() -> panel.addLog(eventType, -1, entries));
final LootTrackerItem[] entries = buildEntries(stack(items));
SwingUtilities.invokeLater(() -> panel.add(eventType, -1, entries));
}
else
{
@@ -252,19 +252,19 @@ public class LootTrackerPlugin extends Plugin
}
}
private LootTrackerItemEntry[] buildEntries(final Collection<ItemStack> itemStacks)
private LootTrackerItem[] buildEntries(final Collection<ItemStack> itemStacks)
{
return itemStacks.stream().map(itemStack ->
{
final ItemComposition itemComposition = itemManager.getItemComposition(itemStack.getId());
final int realItemId = itemComposition.getNote() != -1 ? itemComposition.getLinkedNoteId() : itemStack.getId();
final long price = (long)itemManager.getItemPrice(realItemId) * (long)itemStack.getQuantity();
final long price = (long) itemManager.getItemPrice(realItemId) * (long) itemStack.getQuantity();
return new LootTrackerItemEntry(
return new LootTrackerItem(
itemStack.getId(),
itemComposition.getName(),
itemStack.getQuantity(),
price);
}).toArray(LootTrackerItemEntry[]::new);
}).toArray(LootTrackerItem[]::new);
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 2018, Psikoi <https://github.com/psikoi>
* 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 LootTrackerRecord
{
private final String title;
private final String subTitle;
private final LootTrackerItem[] items;
private final long timestamp;
/**
* Checks if this record matches specified id
* @param id other record id
* @return true if match is made
*/
boolean matches(final String id)
{
if (id == null)
{
return true;
}
return title.equals(id);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB