Dev Tools - Add Inventory Inspector

This commit is contained in:
TheStonedTurtle
2020-07-22 17:04:00 -07:00
committed by Adam
parent ef86486a82
commit a4025e9270
8 changed files with 779 additions and 0 deletions

View File

@@ -51,6 +51,7 @@ class DevToolsPanel extends PluginPanel
private final WidgetInspector widgetInspector;
private final VarInspector varInspector;
private final ScriptInspector scriptInspector;
private final InventoryInspector inventoryInspector;
private final InfoBoxManager infoBoxManager;
private final ScheduledExecutorService scheduledExecutorService;
@@ -61,6 +62,7 @@ class DevToolsPanel extends PluginPanel
WidgetInspector widgetInspector,
VarInspector varInspector,
ScriptInspector scriptInspector,
InventoryInspector inventoryInspector,
Notifier notifier,
InfoBoxManager infoBoxManager,
ScheduledExecutorService scheduledExecutorService)
@@ -70,6 +72,7 @@ class DevToolsPanel extends PluginPanel
this.plugin = plugin;
this.widgetInspector = widgetInspector;
this.varInspector = varInspector;
this.inventoryInspector = inventoryInspector;
this.scriptInspector = scriptInspector;
this.notifier = notifier;
this.infoBoxManager = infoBoxManager;
@@ -180,6 +183,19 @@ class DevToolsPanel extends PluginPanel
clearInfoboxBtn.addActionListener(e -> infoBoxManager.removeIf(i -> true));
container.add(clearInfoboxBtn);
container.add(plugin.getInventoryInspector());
plugin.getInventoryInspector().addActionListener((ev) ->
{
if (plugin.getInventoryInspector().isActive())
{
inventoryInspector.close();
}
else
{
inventoryInspector.open();
}
});
return container;
}
}

View File

@@ -140,6 +140,7 @@ public class DevToolsPlugin extends Plugin
private DevToolsButton varInspector;
private DevToolsButton soundEffects;
private DevToolsButton scriptInspector;
private DevToolsButton inventoryInspector;
private NavigationButton navButton;
@Provides
@@ -182,6 +183,7 @@ public class DevToolsPlugin extends Plugin
varInspector = new DevToolsButton("Var Inspector");
soundEffects = new DevToolsButton("Sound Effects");
scriptInspector = new DevToolsButton("Script Inspector");
inventoryInspector = new DevToolsButton("Inventory Inspector");
overlayManager.add(overlay);
overlayManager.add(locationOverlay);

View File

@@ -0,0 +1,223 @@
/*
* Copyright (c) 2020, TheStonedTurtle <https://github.com/TheStonedTurtle>
* 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.devtools;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.text.DecimalFormat;
import javax.annotation.Nullable;
import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Scrollable;
import javax.swing.SwingConstants;
import javax.swing.border.EmptyBorder;
import net.runelite.api.Constants;
import net.runelite.api.Item;
import net.runelite.client.game.ItemManager;
import net.runelite.client.ui.ColorScheme;
import net.runelite.client.ui.FontManager;
class InventoryDeltaPanel extends JPanel implements Scrollable
{
private static final DecimalFormat COMMA_FORMAT = new DecimalFormat("#,###");
private static final Dimension ITEM_SIZE = new Dimension(Constants.ITEM_SPRITE_WIDTH + 4, Constants.ITEM_SPRITE_HEIGHT);
private final ItemManager itemManager;
private final JPanel addedGrid = new JPanel();
private final JPanel removedGrid = new JPanel();
private final JPanel currentGrid = new JPanel();
InventoryDeltaPanel(final ItemManager itemManager)
{
this.itemManager = itemManager;
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
final EmptyBorder border = new EmptyBorder(2, 2, 2, 2);
setBorder(border);
addedGrid.setBorder(border);
removedGrid.setBorder(border);
currentGrid.setBorder(border);
final GridLayout layout = new GridLayout(0, 1, 1, 1);
addedGrid.setLayout(layout);
removedGrid.setLayout(layout);
currentGrid.setLayout(layout);
// Listen for resize events
addComponentListener(new ComponentAdapter()
{
public void componentResized(final ComponentEvent componentEvent)
{
// Account for container and slot padding
final int cols = Math.max((getWidth() - 4) / (ITEM_SIZE.width + 1), 1);
final GridLayout layout = new GridLayout(0, cols, 1, 1);
addedGrid.setLayout(layout);
removedGrid.setLayout(layout);
currentGrid.setLayout(layout);
}
});
}
void clear()
{
addedGrid.removeAll();
removedGrid.removeAll();
currentGrid.removeAll();
removeAll();
revalidate();
repaint();
}
void displayItems(final InventoryItem[] items, @Nullable final InventoryItem[] added, @Nullable final InventoryItem[] removed)
{
clear();
if (added != null && added.length > 0)
{
final JLabel label = new JLabel("Items Added:", JLabel.CENTER);
label.setAlignmentX(JLabel.CENTER_ALIGNMENT);
add(label);
add(addedGrid);
for (final InventoryItem item : added)
{
addItemToPanel(item, addedGrid).setBackground(new Color(0, 100, 0));
}
}
if (removed != null && removed.length > 0)
{
final JLabel label = new JLabel("Items Removed:", JLabel.CENTER);
label.setAlignmentX(JLabel.CENTER_ALIGNMENT);
add(label);
add(removedGrid);
for (final InventoryItem item : removed)
{
addItemToPanel(item, removedGrid).setBackground(new Color(120, 0, 0));
}
}
final JLabel label = new JLabel("Items in Inventory:", JLabel.CENTER);
label.setAlignmentX(JLabel.CENTER_ALIGNMENT);
add(label);
add(currentGrid);
for (final InventoryItem item : items)
{
final JLabel gridItem = addItemToPanel(item, currentGrid);
// Add hover effect
gridItem.addMouseListener(new MouseAdapter()
{
@Override
public void mouseEntered(MouseEvent e)
{
final JLabel label = (JLabel) e.getSource();
label.setBackground(ColorScheme.DARKER_GRAY_HOVER_COLOR);
}
@Override
public void mouseExited(MouseEvent e)
{
final JLabel label = (JLabel) e.getSource();
label.setBackground(ColorScheme.DARKER_GRAY_COLOR);
}
});
gridItem.setToolTipText("<html>Name: " + item.getName()
+ "<br/>Item ID: " + item.getItem().getId()
+ "<br/>Quantity: " + COMMA_FORMAT.format(item.getItem().getQuantity())
+ "<br/>Slot: " + item.getSlot()
+ "</html>");
}
revalidate();
repaint();
}
private JLabel addItemToPanel(final InventoryItem inventoryItem, final JPanel panel)
{
final JLabel gridItem = new JLabel();
gridItem.setOpaque(true);
gridItem.setPreferredSize(ITEM_SIZE);
gridItem.setVerticalAlignment(SwingConstants.CENTER);
gridItem.setHorizontalAlignment(SwingConstants.CENTER);
gridItem.setFont(FontManager.getRunescapeSmallFont());
final Item item = inventoryItem.getItem();
if (item.getId() == -1)
{
gridItem.setText("EMPTY");
}
else
{
itemManager.getImage(item.getId(), item.getQuantity(), item.getQuantity() > 1).addTo(gridItem);
gridItem.setToolTipText("<html>Name: " + inventoryItem.getName()
+ "<br/>Item ID: " + item.getId()
+ "<br/>Quantity: " + COMMA_FORMAT.format(item.getQuantity())
+ "</html>");
}
panel.add(gridItem);
return gridItem;
}
@Override
public Dimension getPreferredScrollableViewportSize()
{
return null;
}
@Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction)
{
return 1 + (orientation == SwingConstants.VERTICAL ? ITEM_SIZE.height : ITEM_SIZE.width);
}
@Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction)
{
return 1 + (orientation == SwingConstants.VERTICAL ? ITEM_SIZE.height : ITEM_SIZE.width);
}
@Override
public boolean getScrollableTracksViewportWidth()
{
return true;
}
@Override
public boolean getScrollableTracksViewportHeight()
{
return false;
}
}

View File

@@ -0,0 +1,361 @@
/*
* Copyright (c) 2020, TheStonedTurtle <https://github.com/TheStonedTurtle>
* 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.devtools;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.InventoryID;
import net.runelite.api.Item;
import net.runelite.api.ItemComposition;
import net.runelite.api.events.ItemContainerChanged;
import net.runelite.client.callback.ClientThread;
import net.runelite.client.eventbus.EventBus;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.game.ItemManager;
import net.runelite.client.ui.ClientUI;
import net.runelite.client.ui.ColorScheme;
@Slf4j
@Singleton
class InventoryInspector extends JFrame
{
private static final int MAX_LOG_ENTRIES = 25;
private final Client client;
private final EventBus eventBus;
private final ItemManager itemManager;
private final Map<Integer, InventoryTreeNode> nodeMap = new HashMap<>();
private final Map<Integer, InventoryLog> logMap = new HashMap<>();
private final DefaultMutableTreeNode trackerRootNode = new DefaultMutableTreeNode();
private final JTree tree = new JTree(trackerRootNode);
private final InventoryDeltaPanel deltaPanel;
@Inject
InventoryInspector(Client client, EventBus eventBus, DevToolsPlugin plugin, ItemManager itemManager, ClientThread clientThread)
{
this.client = client;
this.eventBus = eventBus;
this.itemManager = itemManager;
this.deltaPanel = new InventoryDeltaPanel(itemManager);
setLayout(new BorderLayout());
setTitle("RuneLite Inventory Inspector");
setIconImage(ClientUI.ICON);
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
// Reset highlight on close
addWindowListener(new WindowAdapter()
{
@Override
public void windowClosing(WindowEvent e)
{
close();
plugin.getInventoryInspector().setActive(false);
}
});
tree.setBorder(new EmptyBorder(2, 2, 2, 2));
tree.setRootVisible(false);
tree.setShowsRootHandles(true);
tree.addTreeSelectionListener(e ->
{
if (e.getNewLeadSelectionPath() == null)
{
return;
}
final Object node = e.getNewLeadSelectionPath().getLastPathComponent();
if (node instanceof InventoryLogNode)
{
clientThread.invoke(() -> displayItemSnapshot((InventoryLogNode) node));
}
});
tree.setModel(new DefaultTreeModel(trackerRootNode));
final JPanel leftSide = new JPanel();
leftSide.setLayout(new BorderLayout());
final JScrollPane trackerScroller = new JScrollPane(tree);
trackerScroller.setPreferredSize(new Dimension(200, 400));
final JScrollBar vertical = trackerScroller.getVerticalScrollBar();
vertical.addAdjustmentListener(new AdjustmentListener()
{
int lastMaximum = actualMax();
private int actualMax()
{
return vertical.getMaximum() - vertical.getModel().getExtent();
}
@Override
public void adjustmentValueChanged(AdjustmentEvent e)
{
if (vertical.getValue() >= lastMaximum)
{
vertical.setValue(actualMax());
}
lastMaximum = actualMax();
}
});
leftSide.add(trackerScroller, BorderLayout.CENTER);
final JButton refreshBtn = new JButton("Refresh");
refreshBtn.setFocusable(false);
refreshBtn.addActionListener(e -> refreshTracker());
final JButton clearBtn = new JButton("Clear");
clearBtn.setFocusable(false);
clearBtn.addActionListener(e -> clearTracker());
final JPanel bottomRow = new JPanel();
bottomRow.add(refreshBtn);
bottomRow.add(clearBtn);
leftSide.add(bottomRow, BorderLayout.SOUTH);
final JScrollPane gridScroller = new JScrollPane(deltaPanel);
gridScroller.getViewport().setBackground(ColorScheme.DARK_GRAY_COLOR);
gridScroller.setPreferredSize(new Dimension(200, 400));
final JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftSide, gridScroller);
add(split, BorderLayout.CENTER);
pack();
}
public void open()
{
eventBus.register(this);
setVisible(true);
toFront();
repaint();
}
public void close()
{
eventBus.unregister(this);
clearTracker();
setVisible(false);
}
@Subscribe
public void onItemContainerChanged(ItemContainerChanged event)
{
final int id = event.getContainerId();
final InventoryLog log = new InventoryLog(id, getNameForInventoryID(id), event.getItemContainer().getItems(), client.getTickCount());
// Delay updates until refresh button is pressed
logMap.put(id, log);
}
private void addLog(final InventoryLog invLog)
{
final InventoryTreeNode node = nodeMap.computeIfAbsent(invLog.getContainerId(), (k) -> new InventoryTreeNode(invLog.getContainerId(), invLog.getContainerName()));
node.add(new InventoryLogNode(invLog));
// Cull very old stuff
for (; node.getChildCount() > MAX_LOG_ENTRIES; )
{
node.remove(0);
}
}
private void clearTracker()
{
logMap.clear();
nodeMap.clear();
deltaPanel.clear();
trackerRootNode.removeAllChildren();
tree.setModel(new DefaultTreeModel(trackerRootNode));
}
private void refreshTracker()
{
deltaPanel.clear();
if (logMap.size() > 0)
{
logMap.values().forEach(this::addLog);
logMap.clear();
}
SwingUtilities.invokeLater(() ->
{
trackerRootNode.removeAllChildren();
nodeMap.values().forEach(trackerRootNode::add);
tree.setModel(new DefaultTreeModel(trackerRootNode));
});
}
private void displayItemSnapshot(final InventoryLogNode logNode)
{
final InventoryTreeNode treeNode = nodeMap.get(logNode.getLog().getContainerId());
if (treeNode == null)
{
log.warn("Clicked on a JTree node that doesn't map anywhere: {}", logNode);
return;
}
final Item[] curItems = logNode.getLog().getItems();
final InventoryItem[] curInventory = convertToInventoryItems(curItems);
InventoryItem[][] deltas = null;
// Compare against previous snapshot
if (treeNode.getIndex(logNode) > 0)
{
final TreeNode prevNode = treeNode.getChildBefore(logNode);
if (prevNode instanceof InventoryLogNode)
{
final InventoryLogNode prevLogNode = (InventoryLogNode) prevNode;
deltas = compareItemSnapshots(prevLogNode.getLog().getItems(), curItems);
}
}
final InventoryItem[] added = deltas == null ? null : deltas[0];
final InventoryItem[] removed = deltas == null ? null : deltas[1];
SwingUtilities.invokeLater(() -> deltaPanel.displayItems(curInventory, added, removed));
}
private InventoryItem[] convertToInventoryItems(final Item[] items)
{
final InventoryItem[] out = new InventoryItem[items.length];
for (int i = 0; i < items.length; i++)
{
final Item item = items[i];
final ItemComposition c = itemManager.getItemComposition(item.getId());
out[i] = new InventoryItem(i, item, c.getName(), c.isStackable());
}
return out;
}
/**
* Compares the current inventory to the old one returning the InventoryItems that were added and removed.
* @param previous old snapshot
* @param current new snapshot
* @return The first InventoryItem[] contains the items that were added and the second contains the items that were removed
*/
private InventoryItem[][] compareItemSnapshots(final Item[] previous, final Item[] current)
{
final Map<Integer, Integer> qtyMap = new HashMap<>();
// ItemContainers shouldn't become smaller over time, but just in case
final int maxSlots = Math.max(previous.length, current.length);
for (int i = 0; i < maxSlots; i++)
{
final Item prev = previous.length > i ? previous[i] : null;
final Item cur = current.length > i ? current[i] : null;
if (prev != null)
{
qtyMap.merge(prev.getId(), -1 * prev.getQuantity(), Integer::sum);
}
if (cur != null)
{
qtyMap.merge(cur.getId(), cur.getQuantity(), Integer::sum);
}
}
final Map<Boolean, List<InventoryItem>> result = qtyMap.entrySet().stream()
.filter(e -> e.getValue() != 0)
.flatMap(e ->
{
final int id = e.getKey();
final int qty = e.getValue();
final ItemComposition c = itemManager.getItemComposition(e.getKey());
InventoryItem[] items = new InventoryItem[]{
new InventoryItem(-1, new Item(id, qty), c.getName(), c.isStackable())
};
if (!c.isStackable() && (qty > 1 || qty < -1))
{
items = new InventoryItem[Math.abs(qty)];
for (int i = 0; i < Math.abs(qty); i++)
{
final Item item = new Item(id, Integer.signum(qty));
items[i] = new InventoryItem(-1, item, c.getName(), c.isStackable());
}
}
return Arrays.stream(items);
})
.collect(Collectors.partitioningBy(item -> item.getItem().getQuantity() > 0));
final InventoryItem[] added = result.get(true).toArray(new InventoryItem[0]);
final InventoryItem[] removed = result.get(false).stream()
// Make quantities positive now that its been sorted.
.peek(i -> i.setItem(new Item(i.getItem().getId(), -i.getItem().getQuantity())))
.toArray(InventoryItem[]::new);
return new InventoryItem[][]{
added, removed
};
}
@Nullable
private static String getNameForInventoryID(final int id)
{
for (final InventoryID inv : InventoryID.values())
{
if (inv.getId() == id)
{
return inv.name();
}
}
return null;
}
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright (c) 2020, TheStonedTurtle <https://github.com/TheStonedTurtle>
* 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.devtools;
import lombok.AllArgsConstructor;
import lombok.Data;
import net.runelite.api.Item;
@Data
@AllArgsConstructor
class InventoryItem
{
private final int slot;
private Item item;
private final String name;
private final boolean stackable;
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright (c) 2020, TheStonedTurtle <https://github.com/TheStonedTurtle>
* 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.devtools;
import javax.annotation.Nullable;
import lombok.Value;
import net.runelite.api.Item;
@Value
class InventoryLog
{
int containerId;
@Nullable
String containerName;
Item[] items;
int tick;
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 2020, TheStonedTurtle <https://github.com/TheStonedTurtle>
* 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.devtools;
import javax.swing.tree.DefaultMutableTreeNode;
import lombok.Getter;
@Getter
class InventoryLogNode extends DefaultMutableTreeNode
{
private final InventoryLog log;
InventoryLogNode(final InventoryLog log)
{
super();
this.log = log;
}
@Override
public String toString()
{
return "Tick: " + log.getTick();
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 2020, TheStonedTurtle <https://github.com/TheStonedTurtle>
* 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.devtools;
import javax.annotation.Nullable;
import javax.swing.tree.DefaultMutableTreeNode;
import lombok.Getter;
@Getter
class InventoryTreeNode extends DefaultMutableTreeNode
{
final int id;
@Nullable
final String name;
InventoryTreeNode(final int id, @Nullable final String name)
{
super();
this.id = id;
this.name = name;
}
@Override
public String toString()
{
return id + (name == null ? "" : " - " + name);
}
}