chore: init
This commit is contained in:
@@ -0,0 +1,284 @@
|
||||
package com.example.essentialsplus.loot.ui;
|
||||
|
||||
import com.example.essentialsplus.loot.LootRecord;
|
||||
import com.example.essentialsplus.loot.droptable.DropTable;
|
||||
import com.example.essentialsplus.ui.Ui;
|
||||
import com.example.essentialsplus.wiki.WikiApi;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.http.api.item.ItemPrice;
|
||||
|
||||
/** Drops of the current target: the player's recorded loot (opens the loot view) and the wiki drop table. */
|
||||
@Slf4j
|
||||
class DropsSection extends JPanel
|
||||
{
|
||||
private static final Map<String, DropTable> TABLES = new ConcurrentHashMap<>();
|
||||
/** item name (lower case) -> item id, -1 if not found */
|
||||
private static final Map<String, Integer> IDS = new ConcurrentHashMap<>();
|
||||
|
||||
private final WikiApi api;
|
||||
private final ExecutorService executor;
|
||||
private final ItemManager itemManager;
|
||||
private final Function<String, LootRecord> records;
|
||||
private final Consumer<LootRecord> openLoot;
|
||||
private final Consumer<String> openWiki;
|
||||
|
||||
private String name;
|
||||
private long recordStamp = -1;
|
||||
private int variant;
|
||||
private boolean loading;
|
||||
private String error;
|
||||
|
||||
DropsSection(WikiApi api, ExecutorService executor, ItemManager itemManager, Function<String, LootRecord> records,
|
||||
Consumer<LootRecord> openLoot, Consumer<String> openWiki)
|
||||
{
|
||||
this.openWiki = openWiki;
|
||||
this.api = api;
|
||||
this.executor = executor;
|
||||
this.itemManager = itemManager;
|
||||
this.records = records;
|
||||
this.openLoot = openLoot;
|
||||
setLayout(new VerticalLayout(3));
|
||||
setOpaque(false);
|
||||
render();
|
||||
}
|
||||
|
||||
/** Target name; rebuilds only when it or the recorded loot changes. */
|
||||
void setTarget(String target)
|
||||
{
|
||||
LootRecord r = target == null ? null : records.apply(target);
|
||||
long stamp = r == null ? 0 : r.getLastSeen() + r.getKills();
|
||||
if (java.util.Objects.equals(target, name) && stamp == recordStamp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!java.util.Objects.equals(target, name))
|
||||
{
|
||||
variant = 0;
|
||||
error = null;
|
||||
}
|
||||
name = target;
|
||||
recordStamp = stamp;
|
||||
render();
|
||||
}
|
||||
|
||||
private void render()
|
||||
{
|
||||
removeAll();
|
||||
if (name == null)
|
||||
{
|
||||
add(note("Attack a monster to see what it drops."));
|
||||
refreshLayout();
|
||||
return;
|
||||
}
|
||||
|
||||
add(LiveFightCard.sectionLabel("YOUR LOOT"));
|
||||
LootRecord record = records.apply(name);
|
||||
if (record != null && record.getKills() + record.getItems().size() > 0)
|
||||
{
|
||||
add(new LootTargetRow(record, record.getTotalValue(), itemManager, openLoot));
|
||||
}
|
||||
else
|
||||
{
|
||||
add(note("No kills recorded yet."));
|
||||
}
|
||||
|
||||
DropTable table = TABLES.get(name);
|
||||
add(LiveFightCard.sectionLabel("DROP TABLE (WIKI)"));
|
||||
if (table == null)
|
||||
{
|
||||
if (error != null)
|
||||
{
|
||||
add(note("Could not load drop table: " + error));
|
||||
}
|
||||
else
|
||||
{
|
||||
add(note("Loading..."));
|
||||
load(name);
|
||||
}
|
||||
}
|
||||
else if (table.isEmpty())
|
||||
{
|
||||
add(note("The wiki has no drop table for " + name + "."));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (table.variants.size() > 1)
|
||||
{
|
||||
JComboBox<DropTable.Variant> box = new JComboBox<>(table.variants.toArray(new DropTable.Variant[0]));
|
||||
box.setSelectedIndex(Math.min(variant, table.variants.size() - 1));
|
||||
box.setFocusable(false);
|
||||
box.addActionListener(e ->
|
||||
{
|
||||
variant = box.getSelectedIndex();
|
||||
render();
|
||||
});
|
||||
add(box);
|
||||
}
|
||||
DropTable.Variant v = table.variants.get(Math.min(variant, table.variants.size() - 1));
|
||||
for (DropTable.Rate rate : DropTable.rates(v).values())
|
||||
{
|
||||
add(row(rate));
|
||||
}
|
||||
}
|
||||
refreshLayout();
|
||||
}
|
||||
|
||||
private void refreshLayout()
|
||||
{
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
|
||||
private JPanel row(DropTable.Rate rate)
|
||||
{
|
||||
JPanel row = new JPanel(new BorderLayout(6, 0))
|
||||
{
|
||||
@Override
|
||||
protected void paintComponent(java.awt.Graphics g0)
|
||||
{
|
||||
java.awt.Graphics2D g = Ui.prepare(g0);
|
||||
g.setColor(Ui.CARD);
|
||||
g.fillRoundRect(0, 0, getWidth(), getHeight(), 6, 6);
|
||||
g.dispose();
|
||||
}
|
||||
};
|
||||
row.setOpaque(false);
|
||||
row.setBorder(BorderFactory.createEmptyBorder(1, 3, 1, 7));
|
||||
row.setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.HAND_CURSOR));
|
||||
row.setToolTipText(rate.item + " · click to open the wiki");
|
||||
row.addMouseListener(new java.awt.event.MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mousePressed(java.awt.event.MouseEvent e)
|
||||
{
|
||||
if (SwingUtilities.isLeftMouseButton(e))
|
||||
{
|
||||
openWiki.accept(rate.item);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
JLabel icon = new JLabel();
|
||||
icon.setPreferredSize(new Dimension(32, 28));
|
||||
icon.setHorizontalAlignment(JLabel.CENTER);
|
||||
Integer id = IDS.get(DropTable.key(rate.item));
|
||||
if (id != null && id > 0)
|
||||
{
|
||||
itemManager.getImage(id).addTo(icon);
|
||||
}
|
||||
row.add(icon, BorderLayout.WEST);
|
||||
|
||||
JLabel label = new JLabel(rate.item);
|
||||
label.setFont(net.runelite.client.ui.FontManager.getRunescapeSmallFont());
|
||||
label.setForeground(Ui.TEXT);
|
||||
row.add(label, BorderLayout.CENTER);
|
||||
|
||||
JLabel chance = new JLabel(rate.text);
|
||||
chance.setFont(net.runelite.client.ui.FontManager.getRunescapeSmallFont());
|
||||
chance.setForeground(rarityColor(rate.perKill));
|
||||
row.add(chance, BorderLayout.EAST);
|
||||
return row;
|
||||
}
|
||||
|
||||
private static java.awt.Color rarityColor(double perKill)
|
||||
{
|
||||
if (Double.isNaN(perKill))
|
||||
{
|
||||
return Ui.MUTED;
|
||||
}
|
||||
if (perKill >= 1)
|
||||
{
|
||||
return Ui.TEXT;
|
||||
}
|
||||
if (perKill >= 1 / 100.0)
|
||||
{
|
||||
return Ui.UP;
|
||||
}
|
||||
if (perKill >= 1 / 1000.0)
|
||||
{
|
||||
return Ui.GOLD;
|
||||
}
|
||||
return Ui.DOWN;
|
||||
}
|
||||
|
||||
private void load(String target)
|
||||
{
|
||||
if (loading || api == null || executor == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
loading = true;
|
||||
executor.execute(() ->
|
||||
{
|
||||
String err = null;
|
||||
try
|
||||
{
|
||||
DropTable table = api.fetchDropTable(target);
|
||||
// icons: item ids by name (tradeable items only)
|
||||
for (DropTable.Variant v : table.variants)
|
||||
{
|
||||
for (DropTable.Rate r : DropTable.rates(v).values())
|
||||
{
|
||||
IDS.computeIfAbsent(DropTable.key(r.item), k -> findId(r.item));
|
||||
}
|
||||
}
|
||||
TABLES.put(target, table);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.debug("drop table for {} failed", target, e);
|
||||
err = e.getMessage() == null ? "wiki not reachable" : e.getMessage();
|
||||
}
|
||||
String failure = err;
|
||||
SwingUtilities.invokeLater(() ->
|
||||
{
|
||||
loading = false;
|
||||
if (target.equals(name))
|
||||
{
|
||||
error = failure;
|
||||
render();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private int findId(String item)
|
||||
{
|
||||
try
|
||||
{
|
||||
for (ItemPrice p : itemManager.search(item))
|
||||
{
|
||||
if (p.getName().equalsIgnoreCase(item))
|
||||
{
|
||||
return p.getId();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
log.debug("item search for {} failed", item, e);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static JLabel note(String text)
|
||||
{
|
||||
JLabel l = new JLabel("<html><body style='width:180px'>" + text.replace("&", "&").replace("<", "<") + "</html>");
|
||||
l.setFont(net.runelite.client.ui.FontManager.getRunescapeSmallFont());
|
||||
l.setForeground(Ui.FAINT);
|
||||
return l;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user