loottracker: refactor inv change events

Instead of having logic to set the event type and then pick it up again in the inv change event, store a callback to be called on inv change
This commit is contained in:
Adam
2022-03-13 00:25:34 -05:00
parent eabaa9cab4
commit 28d4ceb2b5
2 changed files with 183 additions and 195 deletions

View File

@@ -306,24 +306,23 @@ public class LootTrackerPlugin extends Plugin
@Inject @Inject
private Gson gson; private Gson gson;
@Getter(AccessLevel.PACKAGE)
@Inject
private LootTrackerClient lootTrackerClient;
private LootTrackerPanel panel; private LootTrackerPanel panel;
private NavigationButton navButton; private NavigationButton navButton;
@VisibleForTesting
String eventType;
@VisibleForTesting
LootRecordType lootRecordType;
private Object metadata;
private boolean chestLooted; private boolean chestLooted;
private String lastPickpocketTarget; private String lastPickpocketTarget;
private List<String> ignoredItems = new ArrayList<>(); private List<String> ignoredItems = new ArrayList<>();
private List<String> ignoredEvents = new ArrayList<>(); private List<String> ignoredEvents = new ArrayList<>();
private InventoryID inventoryId;
private Multiset<Integer> inventorySnapshot; private Multiset<Integer> inventorySnapshot;
private InvChangeCallback inventorySnapshotCb;
@Getter(AccessLevel.PACKAGE)
@Inject
private LootTrackerClient lootTrackerClient;
private final List<LootRecord> queuedLoots = new ArrayList<>(); private final List<LootRecord> queuedLoots = new ArrayList<>();
private String profileKey; private String profileKey;
private Instant lastLootImport = Instant.now().minus(1, ChronoUnit.MINUTES); private Instant lastLootImport = Instant.now().minus(1, ChronoUnit.MINUTES);
@@ -620,12 +619,14 @@ public class LootTrackerPlugin extends Plugin
@Subscribe @Subscribe
public void onWidgetLoaded(WidgetLoaded widgetLoaded) public void onWidgetLoaded(WidgetLoaded widgetLoaded)
{ {
String event;
Object metadata = null;
final ItemContainer container; final ItemContainer container;
switch (widgetLoaded.getGroupId()) switch (widgetLoaded.getGroupId())
{ {
case (WidgetID.BARROWS_REWARD_GROUP_ID): case (WidgetID.BARROWS_REWARD_GROUP_ID):
setEvent(LootRecordType.EVENT, "Barrows"); event = "Barrows";
container = client.getItemContainer(InventoryID.BARROWS_REWARD); container = client.getItemContainer(InventoryID.BARROWS_REWARD);
break; break;
case (WidgetID.CHAMBERS_OF_XERIC_REWARD_GROUP_ID): case (WidgetID.CHAMBERS_OF_XERIC_REWARD_GROUP_ID):
@@ -633,7 +634,7 @@ public class LootTrackerPlugin extends Plugin
{ {
return; return;
} }
setEvent(LootRecordType.EVENT, "Chambers of Xeric"); event = "Chambers of Xeric";
container = client.getItemContainer(InventoryID.CHAMBERS_OF_XERIC_CHEST); container = client.getItemContainer(InventoryID.CHAMBERS_OF_XERIC_CHEST);
chestLooted = true; chestLooted = true;
break; break;
@@ -647,31 +648,22 @@ public class LootTrackerPlugin extends Plugin
{ {
return; return;
} }
setEvent(LootRecordType.EVENT, "Theatre of Blood"); event = "Theatre of Blood";
container = client.getItemContainer(InventoryID.THEATRE_OF_BLOOD_CHEST); container = client.getItemContainer(InventoryID.THEATRE_OF_BLOOD_CHEST);
chestLooted = true; chestLooted = true;
break; 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
container = client.getItemContainer(InventoryID.BARROWS_REWARD);
if (eventType == null)
{
log.debug("Clue scroll reward interface with no event!");
return;
}
break;
case (WidgetID.KINGDOM_GROUP_ID): case (WidgetID.KINGDOM_GROUP_ID):
setEvent(LootRecordType.EVENT, "Kingdom of Miscellania"); event = "Kingdom of Miscellania";
container = client.getItemContainer(InventoryID.KINGDOM_OF_MISCELLANIA); container = client.getItemContainer(InventoryID.KINGDOM_OF_MISCELLANIA);
break; break;
case (WidgetID.FISHING_TRAWLER_REWARD_GROUP_ID): case (WidgetID.FISHING_TRAWLER_REWARD_GROUP_ID):
setEvent(LootRecordType.EVENT, "Fishing Trawler", client.getBoostedSkillLevel(Skill.FISHING)); event = "Fishing Trawler";
metadata = client.getBoostedSkillLevel(Skill.FISHING);
container = client.getItemContainer(InventoryID.FISHING_TRAWLER_REWARD); container = client.getItemContainer(InventoryID.FISHING_TRAWLER_REWARD);
break; break;
case (WidgetID.DRIFT_NET_FISHING_REWARD_GROUP_ID): case (WidgetID.DRIFT_NET_FISHING_REWARD_GROUP_ID):
setEvent(LootRecordType.EVENT, "Drift Net", client.getBoostedSkillLevel(Skill.FISHING)); event = "Drift Net";
metadata = client.getBoostedSkillLevel(Skill.FISHING);
container = client.getItemContainer(InventoryID.DRIFT_NET_FISHING_REWARD); container = client.getItemContainer(InventoryID.DRIFT_NET_FISHING_REWARD);
break; break;
default: default:
@@ -689,13 +681,13 @@ public class LootTrackerPlugin extends Plugin
.map(item -> new ItemStack(item.getId(), item.getQuantity(), client.getLocalPlayer().getLocalLocation())) .map(item -> new ItemStack(item.getId(), item.getQuantity(), client.getLocalPlayer().getLocalLocation()))
.collect(Collectors.toList()); .collect(Collectors.toList());
if (config.showRaidsLootValue() && (eventType.equals("Theatre of Blood") || eventType.equals("Chambers of Xeric"))) if (config.showRaidsLootValue() && (event.equals("Theatre of Blood") || event.equals("Chambers of Xeric")))
{ {
long totalValue = items.stream() long totalValue = items.stream()
.filter(item -> item.getId() > -1) .filter(item -> item.getId() > -1)
.mapToLong(item -> (long) (config.priceType() == LootTrackerPriceType.GRAND_EXCHANGE ? .mapToLong(item -> config.priceType() == LootTrackerPriceType.GRAND_EXCHANGE ?
itemManager.getItemPrice(item.getId()) * item.getQuantity() : (long) itemManager.getItemPrice(item.getId()) * item.getQuantity() :
itemManager.getItemComposition(item.getId()).getHaPrice() * item.getQuantity())) (long) itemManager.getItemComposition(item.getId()).getHaPrice() * item.getQuantity())
.sum(); .sum();
String chatMessage = new ChatMessageBuilder() String chatMessage = new ChatMessageBuilder()
@@ -715,11 +707,11 @@ public class LootTrackerPlugin extends Plugin
if (items.isEmpty()) if (items.isEmpty())
{ {
log.debug("No items to find for Event: {} | Container: {}", eventType, container); log.debug("No items to find for Event: {} | Container: {}", event, container);
return; return;
} }
addLoot(eventType, -1, lootRecordType, metadata, items); addLoot(event, -1, LootRecordType.EVENT, metadata, items);
} }
@Subscribe @Subscribe
@@ -742,17 +734,14 @@ public class LootTrackerPlugin extends Plugin
return; return;
} }
setEvent(LootRecordType.EVENT, CHEST_EVENT_TYPES.get(regionID)); onInvChange(collectInvAndGroundItems(LootRecordType.EVENT, CHEST_EVENT_TYPES.get(regionID)));
takeInventorySnapshot();
return; return;
} }
if (message.equals(COFFIN_LOOTED_MESSAGE) && if (message.equals(COFFIN_LOOTED_MESSAGE) &&
isPlayerWithinMapRegion(HALLOWED_SEPULCHRE_MAP_REGIONS)) isPlayerWithinMapRegion(HALLOWED_SEPULCHRE_MAP_REGIONS))
{ {
setEvent(LootRecordType.EVENT, HALLOWED_SEPULCHRE_COFFIN_EVENT); onInvChange(collectInvAndGroundItems(LootRecordType.EVENT, HALLOWED_SEPULCHRE_COFFIN_EVENT));
takeInventorySnapshot();
return; return;
} }
@@ -763,16 +752,14 @@ public class LootTrackerPlugin extends Plugin
return; return;
} }
setEvent(LootRecordType.EVENT, HERBIBOAR_EVENT, client.getBoostedSkillLevel(Skill.HERBLORE)); onInvChange(collectInvAndGroundItems(LootRecordType.EVENT, HERBIBOAR_EVENT, client.getBoostedSkillLevel(Skill.HERBLORE)));
takeInventorySnapshot();
return; return;
} }
final int regionID = client.getLocalPlayer().getWorldLocation().getRegionID(); final int regionID = client.getLocalPlayer().getWorldLocation().getRegionID();
if (HESPORI_REGION == regionID && message.equals(HESPORI_LOOTED_MESSAGE)) if (HESPORI_REGION == regionID && message.equals(HESPORI_LOOTED_MESSAGE))
{ {
setEvent(LootRecordType.EVENT, HESPORI_EVENT); onInvChange(collectInvAndGroundItems(LootRecordType.EVENT, HESPORI_EVENT));
takeInventorySnapshot();
return; return;
} }
@@ -780,8 +767,7 @@ public class LootTrackerPlugin extends Plugin
if (hamStoreroomMatcher.matches() && regionID == HAM_STOREROOM_REGION) if (hamStoreroomMatcher.matches() && regionID == HAM_STOREROOM_REGION)
{ {
String keyType = hamStoreroomMatcher.group("key"); String keyType = hamStoreroomMatcher.group("key");
setEvent(LootRecordType.EVENT, String.format("H.A.M. chest (%s)", keyType)); onInvChange(collectInvAndGroundItems(LootRecordType.EVENT, String.format("H.A.M. chest (%s)", keyType)));
takeInventorySnapshot();
return; return;
} }
@@ -794,14 +780,10 @@ 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) // 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)) if (PICKPOCKET_DISAMBIGUATION_MAP.get(lastPickpocketTarget).contains(pickpocketTarget))
{ {
setEvent(LootRecordType.PICKPOCKET, lastPickpocketTarget); pickpocketTarget = lastPickpocketTarget;
}
else
{
setEvent(LootRecordType.PICKPOCKET, pickpocketTarget);
} }
takeInventorySnapshot(); onInvChange(collectInvAndGroundItems(LootRecordType.PICKPOCKET, pickpocketTarget));
return; return;
} }
@@ -810,27 +792,36 @@ public class LootTrackerPlugin extends Plugin
if (m.find()) if (m.find())
{ {
final String type = m.group(1).toLowerCase(); final String type = m.group(1).toLowerCase();
String eventType;
switch (type) switch (type)
{ {
case "beginner": case "beginner":
setEvent(LootRecordType.EVENT, "Clue Scroll (Beginner)"); eventType = "Clue Scroll (Beginner)";
return; break;
case "easy": case "easy":
setEvent(LootRecordType.EVENT, "Clue Scroll (Easy)"); eventType = "Clue Scroll (Easy)";
return; break;
case "medium": case "medium":
setEvent(LootRecordType.EVENT, "Clue Scroll (Medium)"); eventType = "Clue Scroll (Medium)";
return; break;
case "hard": case "hard":
setEvent(LootRecordType.EVENT, "Clue Scroll (Hard)"); eventType = "Clue Scroll (Hard)";
return; break;
case "elite": case "elite":
setEvent(LootRecordType.EVENT, "Clue Scroll (Elite)"); eventType = "Clue Scroll (Elite)";
return; break;
case "master": case "master":
setEvent(LootRecordType.EVENT, "Clue Scroll (Master)"); eventType = "Clue Scroll (Master)";
break;
default:
log.debug("Unrecognized clue type: {}", type);
return; return;
} }
// Clue Scrolls use same InventoryID as Barrows
onInvChange(InventoryID.BARROWS_REWARD, collectInvItems(LootRecordType.EVENT, eventType));
return;
} }
if (SHADE_CHEST_NO_KEY_PATTERN.matcher(message).matches()) if (SHADE_CHEST_NO_KEY_PATTERN.matcher(message).matches())
@@ -852,56 +843,47 @@ public class LootTrackerPlugin extends Plugin
return; return;
} }
setEvent(LootRecordType.EVENT, type, client.getBoostedSkillLevel(Skill.HUNTER)); onInvChange(collectInvAndGroundItems(LootRecordType.EVENT, type, client.getBoostedSkillLevel(Skill.HUNTER)));
takeInventorySnapshot();
} }
if (regionID == TEMPOROSS_REGION && message.startsWith(TEMPOROSS_LOOT_STRING)) if (regionID == TEMPOROSS_REGION && message.startsWith(TEMPOROSS_LOOT_STRING))
{ {
setEvent(LootRecordType.EVENT, TEMPOROSS_EVENT, client.getBoostedSkillLevel(Skill.FISHING)); onInvChange(collectInvItems(LootRecordType.EVENT, TEMPOROSS_EVENT, client.getBoostedSkillLevel(Skill.FISHING)));
takeInventorySnapshot();
} }
} }
@Subscribe @Subscribe
public void onItemContainerChanged(ItemContainerChanged event) public void onItemContainerChanged(ItemContainerChanged event)
{ {
if (event.getContainerId() != InventoryID.INVENTORY.getId() if (inventoryId == null || event.getContainerId() != inventoryId.getId())
|| eventType == null)
{ {
return; return;
} }
if (CHEST_EVENT_TYPES.containsValue(eventType) final ItemContainer inventoryContainer = event.getItemContainer();
|| SHADE_CHEST_OBJECTS.containsValue(eventType) Multiset<Integer> currentInventory = HashMultiset.create();
|| HALLOWED_SEPULCHRE_COFFIN_EVENT.equals(eventType) Arrays.stream(inventoryContainer.getItems())
|| HALLOWED_SACK_EVENT.equals(eventType) .forEach(item -> currentInventory.add(item.getId(), item.getQuantity()));
|| HERBIBOAR_EVENT.equals(eventType)
|| HESPORI_EVENT.equals(eventType)
|| WINTERTODT_SUPPLY_CRATE_EVENT.equals(eventType)
|| eventType.endsWith("Bird House")
|| eventType.startsWith("H.A.M. chest")
|| lootRecordType == LootRecordType.PICKPOCKET
|| eventType.endsWith("lockbox"))
{
WorldPoint playerLocation = client.getLocalPlayer().getWorldLocation();
Collection<ItemStack> groundItems = lootManager.getItemSpawns(playerLocation);
processInventoryLoot(eventType, lootRecordType, metadata, event.getItemContainer(), groundItems); WorldPoint playerLocation = client.getLocalPlayer().getWorldLocation();
resetEvent(); final Collection<ItemStack> groundItems = lootManager.getItemSpawns(playerLocation);
}
// Events that do not produce ground items final Multiset<Integer> diff = Multisets.difference(currentInventory, inventorySnapshot);
else if (SEEDPACK_EVENT.equals(eventType)
|| CASKET_EVENT.equals(eventType) final List<ItemStack> items = diff.entrySet().stream()
|| BIRDNEST_EVENT.equals(eventType) .map(e -> new ItemStack(e.getElement(), e.getCount(), client.getLocalPlayer().getLocalLocation()))
|| SPOILS_OF_WAR_EVENT.equals(eventType) .collect(Collectors.toList());
|| TEMPOROSS_EVENT.equals(eventType)
|| TEMPOROSS_CASKET_EVENT.equals(eventType) log.debug("Inv change: {} Ground items: {}", items, groundItems);
|| MAHOGANY_CRATE_EVENT.equals(eventType))
if (inventorySnapshotCb != null)
{ {
processInventoryLoot(eventType, lootRecordType, metadata, event.getItemContainer(), Collections.emptyList()); inventorySnapshotCb.accept(items, groundItems);
resetEvent();
} }
inventoryId = null;
inventorySnapshot = null;
inventorySnapshotCb = null;
} }
@Subscribe @Subscribe
@@ -915,55 +897,45 @@ public class LootTrackerPlugin extends Plugin
} }
else if (isObjectOp(event.getMenuAction()) && event.getMenuOption().equals("Open") && SHADE_CHEST_OBJECTS.containsKey(event.getId())) else if (isObjectOp(event.getMenuAction()) && event.getMenuOption().equals("Open") && SHADE_CHEST_OBJECTS.containsKey(event.getId()))
{ {
setEvent(LootRecordType.EVENT, SHADE_CHEST_OBJECTS.get(event.getId())); onInvChange(collectInvAndGroundItems(LootRecordType.EVENT, SHADE_CHEST_OBJECTS.get(event.getId())));
takeInventorySnapshot();
} }
else if (isItemOp(event.getMenuAction())) else if (isItemOp(event.getMenuAction()))
{ {
if (event.getMenuOption().equals("Take") && event.getId() == ItemID.SEED_PACK) if (event.getMenuOption().equals("Take") && event.getId() == ItemID.SEED_PACK)
{ {
setEvent(LootRecordType.EVENT, SEEDPACK_EVENT); onInvChange(collectInvItems(LootRecordType.EVENT, SEEDPACK_EVENT));
takeInventorySnapshot();
} }
else if (event.getMenuOption().equals("Search") && BIRDNEST_IDS.contains(event.getId())) else if (event.getMenuOption().equals("Search") && BIRDNEST_IDS.contains(event.getId()))
{ {
setEvent(LootRecordType.EVENT, BIRDNEST_EVENT, event.getId()); onInvChange(collectInvItems(LootRecordType.EVENT, BIRDNEST_EVENT));
takeInventorySnapshot();
} }
else if (event.getMenuOption().equals("Open")) else if (event.getMenuOption().equals("Open"))
{ {
switch (event.getId()) switch (event.getId())
{ {
case ItemID.CASKET: case ItemID.CASKET:
setEvent(LootRecordType.EVENT, CASKET_EVENT); onInvChange(collectInvItems(LootRecordType.EVENT, CASKET_EVENT));
takeInventorySnapshot();
break; break;
case ItemID.SUPPLY_CRATE: case ItemID.SUPPLY_CRATE:
case ItemID.EXTRA_SUPPLY_CRATE: case ItemID.EXTRA_SUPPLY_CRATE:
setEvent(LootRecordType.EVENT, WINTERTODT_SUPPLY_CRATE_EVENT); onInvChange(collectInvAndGroundItems(LootRecordType.EVENT, WINTERTODT_SUPPLY_CRATE_EVENT));
takeInventorySnapshot();
break; break;
case ItemID.SPOILS_OF_WAR: case ItemID.SPOILS_OF_WAR:
setEvent(LootRecordType.EVENT, SPOILS_OF_WAR_EVENT); onInvChange(collectInvItems(LootRecordType.EVENT, SPOILS_OF_WAR_EVENT));
takeInventorySnapshot();
break; break;
case ItemID.CASKET_25590: case ItemID.CASKET_25590:
setEvent(LootRecordType.EVENT, TEMPOROSS_CASKET_EVENT); onInvChange(collectInvAndGroundItems(LootRecordType.EVENT, TEMPOROSS_CASKET_EVENT));
takeInventorySnapshot();
break; break;
case ItemID.SIMPLE_LOCKBOX_25647: case ItemID.SIMPLE_LOCKBOX_25647:
case ItemID.ELABORATE_LOCKBOX_25649: case ItemID.ELABORATE_LOCKBOX_25649:
case ItemID.ORNATE_LOCKBOX_25651: case ItemID.ORNATE_LOCKBOX_25651:
setEvent(LootRecordType.EVENT, itemManager.getItemComposition(event.getId()).getName()); onInvChange(collectInvAndGroundItems(LootRecordType.EVENT, itemManager.getItemComposition(event.getId()).getName()));
takeInventorySnapshot();
break; break;
case ItemID.SUPPLY_CRATE_24884: case ItemID.SUPPLY_CRATE_24884:
setEvent(LootRecordType.EVENT, MAHOGANY_CRATE_EVENT, client.getBoostedSkillLevel(Skill.CONSTRUCTION)); onInvChange(collectInvItems(LootRecordType.EVENT, MAHOGANY_CRATE_EVENT, client.getBoostedSkillLevel(Skill.CONSTRUCTION)));
takeInventorySnapshot();
break; break;
case ItemID.HALLOWED_SACK: case ItemID.HALLOWED_SACK:
setEvent(LootRecordType.EVENT, HALLOWED_SACK_EVENT); onInvChange(collectInvAndGroundItems(LootRecordType.EVENT, HALLOWED_SACK_EVENT));
takeInventorySnapshot();
break; break;
} }
} }
@@ -1061,59 +1033,65 @@ public class LootTrackerPlugin extends Plugin
} }
} }
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() private void resetEvent()
{ {
lootRecordType = null; inventoryId = null;
eventType = null; inventorySnapshot = null;
metadata = null; inventorySnapshotCb = null;
} }
private void takeInventorySnapshot() @FunctionalInterface
interface InvChangeCallback
{ {
final ItemContainer itemContainer = client.getItemContainer(InventoryID.INVENTORY); void accept(Collection<ItemStack> invItems, Collection<ItemStack> groundItems);
}
private InvChangeCallback collectInvItems(LootRecordType type, String event)
{
return collectInvItems(type, event, null);
}
private InvChangeCallback collectInvItems(LootRecordType type, String event, Object metadata)
{
return (invItems, groundItems) ->
addLoot(event, -1, type, metadata, invItems);
}
private InvChangeCallback collectInvAndGroundItems(LootRecordType type, String event)
{
return collectInvAndGroundItems(type, event, null);
}
private InvChangeCallback collectInvAndGroundItems(LootRecordType type, String event, Object metadata)
{
return (invItems, groundItems) ->
{
List<ItemStack> combined = new ArrayList<>();
combined.addAll(invItems);
combined.addAll(groundItems);
addLoot(event, -1, type, metadata, combined);
};
}
private void onInvChange(InvChangeCallback cb)
{
onInvChange(InventoryID.INVENTORY, cb);
}
private void onInvChange(InventoryID inv, InvChangeCallback cb)
{
inventoryId = inv;
inventorySnapshot = HashMultiset.create();
inventorySnapshotCb = cb;
final ItemContainer itemContainer = client.getItemContainer(inv);
if (itemContainer != null) if (itemContainer != null)
{ {
inventorySnapshot = HashMultiset.create();
Arrays.stream(itemContainer.getItems()) Arrays.stream(itemContainer.getItems())
.forEach(item -> inventorySnapshot.add(item.getId(), item.getQuantity())); .forEach(item -> inventorySnapshot.add(item.getId(), item.getQuantity()));
} }
} }
private void processInventoryLoot(String event, LootRecordType lootRecordType, Object metadata, ItemContainer inventoryContainer, Collection<ItemStack> groundItems)
{
if (inventorySnapshot != null)
{
Multiset<Integer> currentInventory = HashMultiset.create();
Arrays.stream(inventoryContainer.getItems())
.forEach(item -> currentInventory.add(item.getId(), item.getQuantity()));
groundItems.stream()
.forEach(item -> currentInventory.add(item.getId(), item.getQuantity()));
final Multiset<Integer> diff = Multisets.difference(currentInventory, inventorySnapshot);
List<ItemStack> items = diff.entrySet().stream()
.map(e -> new ItemStack(e.getElement(), e.getCount(), client.getLocalPlayer().getLocalLocation()))
.collect(Collectors.toList());
addLoot(event, -1, lootRecordType, metadata, items);
inventorySnapshot = null;
}
}
private boolean processHerbiboarHerbSackLoot(int timestamp) private boolean processHerbiboarHerbSackLoot(int timestamp)
{ {
List<ItemStack> herbs = new ArrayList<>(); List<ItemStack> herbs = new ArrayList<>();

View File

@@ -32,6 +32,7 @@ import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import javax.inject.Inject; import javax.inject.Inject;
@@ -59,11 +60,9 @@ import net.runelite.client.config.ConfigManager;
import net.runelite.client.game.ItemManager; import net.runelite.client.game.ItemManager;
import net.runelite.client.game.ItemStack; import net.runelite.client.game.ItemStack;
import net.runelite.client.game.SpriteManager; import net.runelite.client.game.SpriteManager;
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
import net.runelite.http.api.item.ItemPrice; import net.runelite.http.api.item.ItemPrice;
import net.runelite.http.api.loottracker.LootRecordType; import net.runelite.http.api.loottracker.LootRecordType;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@@ -113,10 +112,6 @@ public class LootTrackerPluginTest
@Bind @Bind
private SpriteManager spriteManager; private SpriteManager spriteManager;
@Mock
@Bind
private InfoBoxManager infoBoxManager;
@Inject @Inject
private LootTrackerPlugin lootTrackerPlugin; private LootTrackerPlugin lootTrackerPlugin;
@@ -152,6 +147,21 @@ public class LootTrackerPluginTest
Player player = mock(Player.class); Player player = mock(Player.class);
when(player.getWorldLocation()).thenReturn(new WorldPoint(0, 0, 0)); when(player.getWorldLocation()).thenReturn(new WorldPoint(0, 0, 0));
when(client.getLocalPlayer()).thenReturn(player); when(client.getLocalPlayer()).thenReturn(player);
lootTrackerPlugin = spy(lootTrackerPlugin);
doNothing().when(lootTrackerPlugin).addLoot(any(), anyInt(), any(), any(), any(Collection.class));
}
private void sendInvChange(InventoryID inv, Collection<ItemStack> items)
{
ItemContainer itemContainer = mock(ItemContainer.class);
when(itemContainer.getItems()).thenReturn(items.stream()
.map(is -> new Item(is.getId(), is.getQuantity()))
.toArray(Item[]::new));
when(client.getItemContainer(inv)).thenReturn(itemContainer);
ItemContainerChanged event = new ItemContainerChanged(inv.getId(), itemContainer);
lootTrackerPlugin.onItemContainerChanged(event);
} }
@Test @Test
@@ -160,8 +170,12 @@ public class LootTrackerPluginTest
ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "You pick the hero's pocket.", "", 0); ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "You pick the hero's pocket.", "", 0);
lootTrackerPlugin.onChatMessage(chatMessage); lootTrackerPlugin.onChatMessage(chatMessage);
assertEquals("Hero", lootTrackerPlugin.eventType); List<ItemStack> items = Collections.singletonList(
assertEquals(LootRecordType.PICKPOCKET, lootTrackerPlugin.lootRecordType); new ItemStack(ItemID.COINS_995, 1, null)
);
sendInvChange(InventoryID.INVENTORY, items);
verify(lootTrackerPlugin).addLoot("Hero", -1, LootRecordType.PICKPOCKET, null, items);
} }
@Test @Test
@@ -170,15 +184,12 @@ public class LootTrackerPluginTest
ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", "You have completed 1 master Treasure Trail.", "", 0); ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", "You have completed 1 master Treasure Trail.", "", 0);
lootTrackerPlugin.onChatMessage(chatMessage); lootTrackerPlugin.onChatMessage(chatMessage);
assertEquals("Clue Scroll (Master)", lootTrackerPlugin.eventType); List<ItemStack> items = Collections.singletonList(
assertEquals(LootRecordType.EVENT, lootTrackerPlugin.lootRecordType); new ItemStack(ItemID.COINS_995, 1, null)
} );
sendInvChange(InventoryID.BARROWS_REWARD, items);
private static ItemComposition mockItem(String name) verify(lootTrackerPlugin).addLoot("Clue Scroll (Master)", -1, LootRecordType.EVENT, null, items);
{
ItemComposition itemComposition = mock(ItemComposition.class);
when(itemComposition.getName()).thenReturn(name);
return itemComposition;
} }
@Test @Test
@@ -213,18 +224,13 @@ public class LootTrackerPluginTest
when(messageTable.iterator()).thenReturn(mockIterator); when(messageTable.iterator()).thenReturn(mockIterator);
when(client.getMessages()).thenReturn(messageTable); when(client.getMessages()).thenReturn(messageTable);
LootTrackerPlugin lootTrackerPluginSpy = spy(this.lootTrackerPlugin);
doNothing().when(lootTrackerPluginSpy).addLoot(any(), anyInt(), any(), any(), any(Collection.class));
ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", LootTrackerPlugin.HERBIBOAR_LOOTED_MESSAGE, "", 0); ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", LootTrackerPlugin.HERBIBOAR_LOOTED_MESSAGE, "", 0);
lootTrackerPluginSpy.onChatMessage(chatMessage); lootTrackerPlugin.onChatMessage(chatMessage);
verify(lootTrackerPluginSpy).addLoot("Herbiboar", -1, LootRecordType.EVENT, 42, Arrays.asList( verify(lootTrackerPlugin).addLoot("Herbiboar", -1, LootRecordType.EVENT, 42, Arrays.asList(
new ItemStack(id, 1, null), new ItemStack(id, 1, null),
new ItemStack(id, 1, null) new ItemStack(id, 1, null)
)); ));
// Check the event type is null, which means the plugin isn't waiting on an inventory change event
assertNull(lootTrackerPlugin.eventType);
} }
} }
@@ -234,10 +240,6 @@ public class LootTrackerPluginTest
when(lootTrackerConfig.showRaidsLootValue()).thenReturn(true); when(lootTrackerConfig.showRaidsLootValue()).thenReturn(true);
when(lootTrackerConfig.priceType()).thenReturn(LootTrackerPriceType.GRAND_EXCHANGE); when(lootTrackerConfig.priceType()).thenReturn(LootTrackerPriceType.GRAND_EXCHANGE);
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), isNull(), anyCollection());
ItemContainer itemContainer = mock(ItemContainer.class); ItemContainer itemContainer = mock(ItemContainer.class);
when(itemContainer.getItems()).thenReturn(new Item[]{ when(itemContainer.getItems()).thenReturn(new Item[]{
new Item(ItemID.TWISTED_BOW, 1), new Item(ItemID.TWISTED_BOW, 1),
@@ -250,7 +252,7 @@ public class LootTrackerPluginTest
WidgetLoaded widgetLoaded = new WidgetLoaded(); WidgetLoaded widgetLoaded = new WidgetLoaded();
widgetLoaded.setGroupId(WidgetID.CHAMBERS_OF_XERIC_REWARD_GROUP_ID); widgetLoaded.setGroupId(WidgetID.CHAMBERS_OF_XERIC_REWARD_GROUP_ID);
spyPlugin.onWidgetLoaded(widgetLoaded); lootTrackerPlugin.onWidgetLoaded(widgetLoaded);
ArgumentCaptor<QueuedMessage> captor = ArgumentCaptor.forClass(QueuedMessage.class); ArgumentCaptor<QueuedMessage> captor = ArgumentCaptor.forClass(QueuedMessage.class);
verify(chatMessageManager).queue(captor.capture()); verify(chatMessageManager).queue(captor.capture());
@@ -303,26 +305,35 @@ public class LootTrackerPluginTest
@Test @Test
public void testBirdhouses() public void testBirdhouses()
{ {
when(client.getBoostedSkillLevel(Skill.HUNTER)).thenReturn(42);
List<ItemStack> items = Collections.singletonList(
new ItemStack(ItemID.BIRD_NEST, 42, null)
);
// No bird nests // No bird nests
ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "You dismantle and discard the trap, retrieving 10 dead birds, 30 feathers and 1140 Hunter XP.", "", 0); ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "You dismantle and discard the trap, retrieving 10 dead birds, 30 feathers and 1140 Hunter XP.", "", 0);
lootTrackerPlugin.onChatMessage(chatMessage); lootTrackerPlugin.onChatMessage(chatMessage);
assertEquals("Magic Bird House", lootTrackerPlugin.eventType); sendInvChange(InventoryID.INVENTORY, items);
assertEquals(LootRecordType.EVENT, lootTrackerPlugin.lootRecordType); verify(lootTrackerPlugin).addLoot("Magic Bird House", -1, LootRecordType.EVENT, 42, items);
when(client.getItemContainer(InventoryID.INVENTORY)).thenReturn(null);
// Single bird nest // Single bird nest
chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "You dismantle and discard the trap, retrieving a nest, 10 dead birds, 50 feathers and 700 Hunter XP.", "", 0); chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "You dismantle and discard the trap, retrieving a nest, 10 dead birds, 50 feathers and 700 Hunter XP.", "", 0);
lootTrackerPlugin.onChatMessage(chatMessage); lootTrackerPlugin.onChatMessage(chatMessage);
assertEquals("Teak Bird House", lootTrackerPlugin.eventType); sendInvChange(InventoryID.INVENTORY, items);
assertEquals(LootRecordType.EVENT, lootTrackerPlugin.lootRecordType); verify(lootTrackerPlugin).addLoot("Teak Bird House", -1, LootRecordType.EVENT, 42, items);
when(client.getItemContainer(InventoryID.INVENTORY)).thenReturn(null);
// Multiple nests // Multiple nests
chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "You dismantle and discard the trap, retrieving 2 nests, 10 dead birds, 40 feathers and 280 Hunter XP.", "", 0); chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "You dismantle and discard the trap, retrieving 2 nests, 10 dead birds, 40 feathers and 280 Hunter XP.", "", 0);
lootTrackerPlugin.onChatMessage(chatMessage); lootTrackerPlugin.onChatMessage(chatMessage);
assertEquals("Regular Bird House", lootTrackerPlugin.eventType); sendInvChange(InventoryID.INVENTORY, items);
assertEquals(LootRecordType.EVENT, lootTrackerPlugin.lootRecordType); verify(lootTrackerPlugin).addLoot("Regular Bird House", -1, LootRecordType.EVENT, 42, items);
} }
@Test @Test
@@ -372,8 +383,7 @@ public class LootTrackerPluginTest
when(client.getLocalPlayer().getWorldLocation()).thenReturn(new WorldPoint(3153, 2833, 0)); when(client.getLocalPlayer().getWorldLocation()).thenReturn(new WorldPoint(3153, 2833, 0));
when(client.getBoostedSkillLevel(Skill.FISHING)).thenReturn(69); when(client.getBoostedSkillLevel(Skill.FISHING)).thenReturn(69);
LootTrackerPlugin lootTrackerPluginSpy = spy(this.lootTrackerPlugin); doNothing().when(lootTrackerPlugin).addLoot(any(), anyInt(), any(), any(), any(Collection.class));
doNothing().when(lootTrackerPluginSpy).addLoot(any(), anyInt(), any(), any(), any(Collection.class));
ItemContainer itemContainer = mock(ItemContainer.class); ItemContainer itemContainer = mock(ItemContainer.class);
when(itemContainer.getItems()).thenReturn(new Item[]{ when(itemContainer.getItems()).thenReturn(new Item[]{
@@ -383,21 +393,21 @@ public class LootTrackerPluginTest
when(client.getItemContainer(InventoryID.INVENTORY)).thenReturn(itemContainer); when(client.getItemContainer(InventoryID.INVENTORY)).thenReturn(itemContainer);
ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "You found some loot: 30 x Raw tuna", "", 0); ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "You found some loot: 30 x Raw tuna", "", 0);
lootTrackerPluginSpy.onChatMessage(chatMessage); lootTrackerPlugin.onChatMessage(chatMessage);
when(itemContainer.getItems()).thenReturn(new Item[]{ when(itemContainer.getItems()).thenReturn(new Item[]{
new Item(ItemID.BUCKET_OF_WATER, 1), new Item(ItemID.BUCKET_OF_WATER, 1),
new Item(ItemID.ROPE, 1), new Item(ItemID.ROPE, 1),
new Item(ItemID.RAW_TUNA, 30) new Item(ItemID.RAW_TUNA, 30)
}); });
lootTrackerPluginSpy.onItemContainerChanged(new ItemContainerChanged(InventoryID.INVENTORY.getId(), itemContainer)); lootTrackerPlugin.onItemContainerChanged(new ItemContainerChanged(InventoryID.INVENTORY.getId(), itemContainer));
verify(lootTrackerPluginSpy).addLoot("Reward pool (Tempoross)", -1, LootRecordType.EVENT, 69, Arrays.asList( verify(lootTrackerPlugin).addLoot("Reward pool (Tempoross)", -1, LootRecordType.EVENT, 69, Arrays.asList(
new ItemStack(ItemID.RAW_TUNA, 30, null) new ItemStack(ItemID.RAW_TUNA, 30, null)
)); ));
chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "You found some loot: <col=ef1020>Tome of water (empty)</col>", "", 0); chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "You found some loot: <col=ef1020>Tome of water (empty)</col>", "", 0);
lootTrackerPluginSpy.onChatMessage(chatMessage); lootTrackerPlugin.onChatMessage(chatMessage);
when(itemContainer.getItems()).thenReturn(new Item[]{ when(itemContainer.getItems()).thenReturn(new Item[]{
new Item(ItemID.BUCKET_OF_WATER, 1), new Item(ItemID.BUCKET_OF_WATER, 1),
@@ -405,9 +415,9 @@ public class LootTrackerPluginTest
new Item(ItemID.RAW_TUNA, 30), new Item(ItemID.RAW_TUNA, 30),
new Item(ItemID.TOME_OF_WATER_EMPTY, 1) new Item(ItemID.TOME_OF_WATER_EMPTY, 1)
}); });
lootTrackerPluginSpy.onItemContainerChanged(new ItemContainerChanged(InventoryID.INVENTORY.getId(), itemContainer)); lootTrackerPlugin.onItemContainerChanged(new ItemContainerChanged(InventoryID.INVENTORY.getId(), itemContainer));
verify(lootTrackerPluginSpy).addLoot("Reward pool (Tempoross)", -1, LootRecordType.EVENT, 69, Arrays.asList( verify(lootTrackerPlugin).addLoot("Reward pool (Tempoross)", -1, LootRecordType.EVENT, 69, Arrays.asList(
new ItemStack(ItemID.TOME_OF_WATER_EMPTY, 1, null) new ItemStack(ItemID.TOME_OF_WATER_EMPTY, 1, null)
)); ));
} }