loot tracker: add metadata field to loot record

This is for tracking miscellaneous data with the loot records, such as
npc id and skill levels, for the wiki drop log project.

Co-authored-by: Adam <Adam@sigterm.info>
This commit is contained in:
leejt
2020-08-07 14:26:37 -04:00
committed by Adam
parent 7affadcf50
commit 18087ca9cc
3 changed files with 69 additions and 62 deletions

View File

@@ -37,6 +37,7 @@ public class LootRecord
{
private String eventId;
private LootRecordType type;
private Object metadata;
private Collection<GameItem> drops;
private Instant time;
}

View File

@@ -70,6 +70,7 @@ import net.runelite.api.MessageNode;
import net.runelite.api.NPC;
import net.runelite.api.ObjectID;
import net.runelite.api.Player;
import net.runelite.api.Skill;
import net.runelite.api.SpriteID;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.events.ChatMessage;
@@ -256,6 +257,7 @@ public class LootTrackerPlugin extends Plugin
String eventType;
@VisibleForTesting
LootRecordType lootRecordType;
private Object metadata;
private boolean chestLooted;
private String lastPickpocketTarget;
@@ -427,14 +429,14 @@ public class LootTrackerPlugin extends Plugin
}
}
void addLoot(@NonNull String name, int combatLevel, LootRecordType type, Collection<ItemStack> items)
void addLoot(@NonNull String name, int combatLevel, LootRecordType type, Object metadata, Collection<ItemStack> items)
{
final LootTrackerItem[] entries = buildEntries(stack(items));
SwingUtilities.invokeLater(() -> panel.add(name, type, combatLevel, entries));
if (config.saveLoot())
{
LootRecord lootRecord = new LootRecord(name, type, toGameItems(items), Instant.now());
LootRecord lootRecord = new LootRecord(name, type, metadata, toGameItems(items), Instant.now());
synchronized (queuedLoots)
{
queuedLoots.add(lootRecord);
@@ -452,7 +454,7 @@ public class LootTrackerPlugin extends Plugin
final String name = npc.getName();
final int combat = npc.getCombatLevel();
addLoot(name, combat, LootRecordType.NPC, items);
addLoot(name, combat, LootRecordType.NPC, npc.getId(), items);
if (config.npcKillChatMessage())
{
@@ -478,7 +480,7 @@ public class LootTrackerPlugin extends Plugin
final String name = player.getName();
final int combat = player.getCombatLevel();
addLoot(name, combat, LootRecordType.PLAYER, items);
addLoot(name, combat, LootRecordType.PLAYER, null, items);
if (config.pvpKillChatMessage())
{
@@ -489,12 +491,12 @@ public class LootTrackerPlugin extends Plugin
@Subscribe
public void onWidgetLoaded(WidgetLoaded widgetLoaded)
{
final String event;
final ItemContainer container;
switch (widgetLoaded.getGroupId())
{
case (WidgetID.BARROWS_REWARD_GROUP_ID):
event = "Barrows";
setEvent(LootRecordType.EVENT, "Barrows");
container = client.getItemContainer(InventoryID.BARROWS_REWARD);
break;
case (WidgetID.CHAMBERS_OF_XERIC_REWARD_GROUP_ID):
@@ -502,7 +504,7 @@ public class LootTrackerPlugin extends Plugin
{
return;
}
event = "Chambers of Xeric";
setEvent(LootRecordType.EVENT, "Chambers of Xeric");
container = client.getItemContainer(InventoryID.CHAMBERS_OF_XERIC_CHEST);
chestLooted = true;
break;
@@ -516,32 +518,31 @@ public class LootTrackerPlugin extends Plugin
{
return;
}
event = "Theatre of Blood";
setEvent(LootRecordType.EVENT, "Theatre of Blood");
container = client.getItemContainer(InventoryID.THEATRE_OF_BLOOD_CHEST);
chestLooted = true;
break;
case (WidgetID.CLUE_SCROLL_REWARD_GROUP_ID):
// event type should be set via ChatMessage for clue scrolls.
// Clue Scrolls use same InventoryID as Barrows
event = eventType;
container = client.getItemContainer(InventoryID.BARROWS_REWARD);
if (event == null)
if (eventType == null)
{
log.debug("Clue scroll reward interface with no event!");
return;
}
break;
case (WidgetID.KINGDOM_GROUP_ID):
event = "Kingdom of Miscellania";
setEvent(LootRecordType.EVENT, "Kingdom of Miscellania");
container = client.getItemContainer(InventoryID.KINGDOM_OF_MISCELLANIA);
break;
case (WidgetID.FISHING_TRAWLER_REWARD_GROUP_ID):
event = "Fishing Trawler";
setEvent(LootRecordType.EVENT, "Fishing Trawler", client.getBoostedSkillLevel(Skill.FISHING));
container = client.getItemContainer(InventoryID.FISHING_TRAWLER_REWARD);
break;
case (WidgetID.DRIFT_NET_FISHING_REWARD_GROUP_ID):
event = "Drift Net";
setEvent(LootRecordType.EVENT, "Drift Net", client.getBoostedSkillLevel(Skill.FISHING));
container = client.getItemContainer(InventoryID.DRIFT_NET_FISHING_REWARD);
break;
default:
@@ -559,7 +560,7 @@ public class LootTrackerPlugin extends Plugin
.map(item -> new ItemStack(item.getId(), item.getQuantity(), client.getLocalPlayer().getLocalLocation()))
.collect(Collectors.toList());
if (config.showRaidsLootValue() && (event.equals("Theatre of Blood") || event.equals("Chambers of Xeric")))
if (config.showRaidsLootValue() && (eventType.equals("Theatre of Blood") || eventType.equals("Chambers of Xeric")))
{
long totalValue = items.stream()
.filter(item -> item.getId() > -1)
@@ -585,11 +586,11 @@ public class LootTrackerPlugin extends Plugin
if (items.isEmpty())
{
log.debug("No items to find for Event: {} | Container: {}", event, container);
log.debug("No items to find for Event: {} | Container: {}", eventType, container);
return;
}
addLoot(event, -1, LootRecordType.EVENT, items);
addLoot(eventType, -1, lootRecordType, metadata, items);
}
@Subscribe
@@ -612,8 +613,7 @@ public class LootTrackerPlugin extends Plugin
return;
}
eventType = CHEST_EVENT_TYPES.get(regionID);
lootRecordType = LootRecordType.EVENT;
setEvent(LootRecordType.EVENT, CHEST_EVENT_TYPES.get(regionID));
takeInventorySnapshot();
return;
@@ -622,8 +622,7 @@ public class LootTrackerPlugin extends Plugin
if (message.equals(COFFIN_LOOTED_MESSAGE) &&
isPlayerWithinMapRegion(HALLOWED_SEPULCHRE_MAP_REGIONS))
{
eventType = HALLOWED_SEPULCHRE_COFFIN_EVENT;
lootRecordType = LootRecordType.EVENT;
setEvent(LootRecordType.EVENT, HALLOWED_SEPULCHRE_COFFIN_EVENT);
takeInventorySnapshot();
return;
}
@@ -635,8 +634,7 @@ public class LootTrackerPlugin extends Plugin
return;
}
eventType = HERBIBOAR_EVENT;
lootRecordType = LootRecordType.EVENT;
setEvent(LootRecordType.EVENT, HERBIBOAR_EVENT, client.getBoostedSkillLevel(Skill.HERBLORE));
takeInventorySnapshot();
return;
}
@@ -644,8 +642,7 @@ public class LootTrackerPlugin extends Plugin
final int regionID = client.getLocalPlayer().getWorldLocation().getRegionID();
if (HESPORI_REGION == regionID && message.equals(HESPORI_LOOTED_MESSAGE))
{
eventType = HESPORI_EVENT;
lootRecordType = LootRecordType.EVENT;
setEvent(LootRecordType.EVENT, HESPORI_EVENT);
takeInventorySnapshot();
return;
}
@@ -654,8 +651,7 @@ public class LootTrackerPlugin extends Plugin
if (hamStoreroomMatcher.matches() && regionID == HAM_STOREROOM_REGION)
{
String keyType = hamStoreroomMatcher.group("key");
eventType = String.format("H.A.M. chest (%s)", keyType);
lootRecordType = LootRecordType.EVENT;
setEvent(LootRecordType.EVENT, String.format("H.A.M. chest (%s)", keyType));
takeInventorySnapshot();
return;
}
@@ -669,13 +665,11 @@ public class LootTrackerPlugin extends Plugin
// Occasional edge case where the pickpocket message doesn't list the correct name of the NPC (e.g. H.A.M. Members)
if (PICKPOCKET_DISAMBIGUATION_MAP.get(lastPickpocketTarget).contains(pickpocketTarget))
{
eventType = lastPickpocketTarget;
lootRecordType = LootRecordType.PICKPOCKET;
setEvent(LootRecordType.PICKPOCKET, lastPickpocketTarget);
}
else
{
eventType = pickpocketTarget;
lootRecordType = LootRecordType.PICKPOCKET;
setEvent(LootRecordType.PICKPOCKET, pickpocketTarget);
}
takeInventorySnapshot();
@@ -690,28 +684,22 @@ public class LootTrackerPlugin extends Plugin
switch (type)
{
case "beginner":
eventType = "Clue Scroll (Beginner)";
lootRecordType = LootRecordType.EVENT;
setEvent(LootRecordType.EVENT, "Clue Scroll (Beginner)");
return;
case "easy":
eventType = "Clue Scroll (Easy)";
lootRecordType = LootRecordType.EVENT;
setEvent(LootRecordType.EVENT, "Clue Scroll (Easy)");
return;
case "medium":
eventType = "Clue Scroll (Medium)";
lootRecordType = LootRecordType.EVENT;
setEvent(LootRecordType.EVENT, "Clue Scroll (Medium)");
return;
case "hard":
eventType = "Clue Scroll (Hard)";
lootRecordType = LootRecordType.EVENT;
setEvent(LootRecordType.EVENT, "Clue Scroll (Hard)");
return;
case "elite":
eventType = "Clue Scroll (Elite)";
lootRecordType = LootRecordType.EVENT;
setEvent(LootRecordType.EVENT, "Clue Scroll (Elite)");
return;
case "master":
eventType = "Clue Scroll (Master)";
lootRecordType = LootRecordType.EVENT;
setEvent(LootRecordType.EVENT, "Clue Scroll (Master)");
return;
}
}
@@ -719,8 +707,7 @@ public class LootTrackerPlugin extends Plugin
if (SHADE_CHEST_NO_KEY_PATTERN.matcher(message).matches())
{
// Player didn't have the key they needed.
eventType = null;
lootRecordType = null;
resetEvent();
}
}
@@ -747,9 +734,8 @@ public class LootTrackerPlugin extends Plugin
WorldPoint playerLocation = client.getLocalPlayer().getWorldLocation();
Collection<ItemStack> groundItems = lootManager.getItemSpawns(playerLocation);
processInventoryLoot(eventType, lootRecordType, event.getItemContainer(), groundItems);
eventType = null;
lootRecordType = null;
processInventoryLoot(eventType, lootRecordType, metadata, event.getItemContainer(), groundItems);
resetEvent();
}
}
@@ -765,29 +751,25 @@ public class LootTrackerPlugin extends Plugin
if (event.getMenuOption().equals("Take") && event.getId() == ItemID.SEED_PACK)
{
eventType = SEEDPACK_EVENT;
lootRecordType = LootRecordType.EVENT;
setEvent(LootRecordType.EVENT, SEEDPACK_EVENT);
takeInventorySnapshot();
}
if (event.getMenuOption().equals("Open") && SHADE_CHEST_OBJECTS.containsKey(event.getId()))
{
eventType = SHADE_CHEST_OBJECTS.get(event.getId());
lootRecordType = LootRecordType.EVENT;
setEvent(LootRecordType.EVENT, SHADE_CHEST_OBJECTS.get(event.getId()));
takeInventorySnapshot();
}
if (event.getMenuOption().equals("Search") && BIRDNEST_IDS.contains(event.getId()))
{
eventType = BIRDNEST_EVENT;
lootRecordType = LootRecordType.EVENT;
setEvent(LootRecordType.EVENT, BIRDNEST_EVENT);
takeInventorySnapshot();
}
if (event.getMenuOption().equals("Open") && event.getId() == ItemID.CASKET)
{
eventType = CASKET_EVENT;
lootRecordType = LootRecordType.EVENT;
setEvent(LootRecordType.EVENT, CASKET_EVENT);
takeInventorySnapshot();
}
}
@@ -828,6 +810,25 @@ public class LootTrackerPlugin extends Plugin
return future;
}
private void setEvent(LootRecordType lootRecordType, String eventType, Object metadata)
{
this.lootRecordType = lootRecordType;
this.eventType = eventType;
this.metadata = metadata;
}
private void setEvent(LootRecordType lootRecordType, String eventType)
{
setEvent(lootRecordType, eventType, null);
}
private void resetEvent()
{
lootRecordType = null;
eventType = null;
metadata = null;
}
private void takeInventorySnapshot()
{
final ItemContainer itemContainer = client.getItemContainer(InventoryID.INVENTORY);
@@ -839,7 +840,7 @@ public class LootTrackerPlugin extends Plugin
}
}
private void processInventoryLoot(String event, LootRecordType lootRecordType, ItemContainer inventoryContainer, Collection<ItemStack> groundItems)
private void processInventoryLoot(String event, LootRecordType lootRecordType, Object metadata, ItemContainer inventoryContainer, Collection<ItemStack> groundItems)
{
if (inventorySnapshot != null)
{
@@ -856,7 +857,7 @@ public class LootTrackerPlugin extends Plugin
.map(e -> new ItemStack(e.getElement(), e.getCount(), client.getLocalPlayer().getLocalLocation()))
.collect(Collectors.toList());
addLoot(event, -1, lootRecordType, items);
addLoot(event, -1, lootRecordType, metadata, items);
inventorySnapshot = null;
}
@@ -886,7 +887,8 @@ public class LootTrackerPlugin extends Plugin
return false;
}
addLoot(HERBIBOAR_EVENT, -1, LootRecordType.EVENT, herbs);
int herbloreLevel = client.getBoostedSkillLevel(Skill.HERBLORE);
addLoot(HERBIBOAR_EVENT, -1, LootRecordType.EVENT, herbloreLevel, herbs);
return true;
}

View File

@@ -45,6 +45,7 @@ import net.runelite.api.ItemID;
import net.runelite.api.IterableHashTable;
import net.runelite.api.MessageNode;
import net.runelite.api.Player;
import net.runelite.api.Skill;
import net.runelite.api.coords.LocalPoint;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.events.ChatMessage;
@@ -69,6 +70,7 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyCollection;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.isNull;
import org.mockito.Mock;
import org.mockito.Mockito;
import static org.mockito.Mockito.doNothing;
@@ -172,6 +174,8 @@ public class LootTrackerPluginTest
@Test
public void testHerbiboarHerbSack()
{
when(client.getBoostedSkillLevel(Skill.HERBLORE)).thenReturn(42);
for (Map.Entry<Integer, String> herb : HERB_IDS_TO_NAMES.entrySet())
{
final int id = herb.getKey();
@@ -200,12 +204,12 @@ public class LootTrackerPluginTest
when(client.getMessages()).thenReturn(messageTable);
LootTrackerPlugin lootTrackerPluginSpy = spy(this.lootTrackerPlugin);
doNothing().when(lootTrackerPluginSpy).addLoot(any(), anyInt(), any(), any(Collection.class));
doNothing().when(lootTrackerPluginSpy).addLoot(any(), anyInt(), any(), any(), any(Collection.class));
ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", LootTrackerPlugin.HERBIBOAR_LOOTED_MESSAGE, "", 0);
lootTrackerPluginSpy.onChatMessage(chatMessage);
verify(lootTrackerPluginSpy).addLoot("Herbiboar", -1, LootRecordType.EVENT, Arrays.asList(
verify(lootTrackerPluginSpy).addLoot("Herbiboar", -1, LootRecordType.EVENT, 42, Arrays.asList(
new ItemStack(id, 1, null),
new ItemStack(id, 1, null)
));
@@ -222,7 +226,7 @@ public class LootTrackerPluginTest
LootTrackerPlugin spyPlugin = Mockito.spy(lootTrackerPlugin);
// Make sure we don't execute addLoot, so we don't have to mock LootTrackerPanel and everything else also
doNothing().when(spyPlugin).addLoot(anyString(), anyInt(), any(LootRecordType.class), anyCollection());
doNothing().when(spyPlugin).addLoot(anyString(), anyInt(), any(LootRecordType.class), isNull(), anyCollection());
ItemContainer itemContainer = mock(ItemContainer.class);
when(itemContainer.getItems()).thenReturn(new Item[]{
@@ -253,7 +257,7 @@ public class LootTrackerPluginTest
LootTrackerPlugin spyPlugin = Mockito.spy(lootTrackerPlugin);
// Make sure we don't execute addLoot, so we don't have to mock LootTrackerPanel and everything else also
doNothing().when(spyPlugin).addLoot(anyString(), anyInt(), any(LootRecordType.class), anyCollection());
doNothing().when(spyPlugin).addLoot(anyString(), anyInt(), any(LootRecordType.class), isNull(), anyCollection());
ItemContainer itemContainer = mock(ItemContainer.class);
when(itemContainer.getItems()).thenReturn(new Item[]{