diff --git a/runelite-client/src/main/java/net/runelite/client/game/LootManager.java b/runelite-client/src/main/java/net/runelite/client/game/LootManager.java index ddd8157502..e44c5d7572 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/LootManager.java +++ b/runelite-client/src/main/java/net/runelite/client/game/LootManager.java @@ -29,6 +29,7 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ListMultimap; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -403,4 +404,25 @@ public class LootManager return new WorldPoint(x, y, worldLocation.getPlane()); } + + /** + * Get the list of items present at the provided WorldPoint that spawned this tick. + * + * @param worldPoint the location in question + * @return the list of item stacks + */ + public Collection getItemSpawns(WorldPoint worldPoint) + { + LocalPoint localPoint = LocalPoint.fromWorld(client, worldPoint); + if (localPoint == null) + { + return Collections.emptyList(); + } + + final int sceneX = localPoint.getSceneX(); + final int sceneY = localPoint.getSceneY(); + final int packed = sceneX << 8 | sceneY; + final List itemStacks = itemSpawns.get(packed); + return Collections.unmodifiableList(itemStacks); + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java index 9fd849ac61..c2dd8508cf 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java @@ -69,6 +69,7 @@ import net.runelite.api.ItemContainer; import net.runelite.api.ItemID; import net.runelite.api.MessageNode; import net.runelite.api.NPC; +import net.runelite.api.ObjectID; import net.runelite.api.Player; import net.runelite.api.SpriteID; import net.runelite.api.coords.WorldPoint; @@ -96,6 +97,7 @@ import net.runelite.client.events.SessionClose; import net.runelite.client.events.SessionOpen; import net.runelite.client.game.ItemManager; import net.runelite.client.game.ItemStack; +import net.runelite.client.game.LootManager; import net.runelite.client.game.SpriteManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; @@ -152,6 +154,31 @@ public class LootTrackerPlugin extends Plugin put(13151, "Elven Crystal Chest"). build(); + // Shade chest loot handling + private static final Pattern SHADE_CHEST_NO_KEY_PATTERN = Pattern.compile("You need a [a-z]+ key with a [a-z]+ trim to open this chest .*"); + private static final Map SHADE_CHEST_OBJECTS = new ImmutableMap.Builder(). + put(ObjectID.BRONZE_CHEST, "Bronze key red"). + put(ObjectID.BRONZE_CHEST_4112, "Bronze key brown"). + put(ObjectID.BRONZE_CHEST_4113, "Bronze key crimson"). + put(ObjectID.BRONZE_CHEST_4114, "Bronze key black"). + put(ObjectID.BRONZE_CHEST_4115, "Bronze key purple"). + put(ObjectID.STEEL_CHEST, "Steel key red"). + put(ObjectID.STEEL_CHEST_4117, "Steel key brown"). + put(ObjectID.STEEL_CHEST_4118, "Steel key crimson"). + put(ObjectID.STEEL_CHEST_4119, "Steel key black"). + put(ObjectID.STEEL_CHEST_4120, "Steel key purple"). + put(ObjectID.BLACK_CHEST, "Black key red"). + put(ObjectID.BLACK_CHEST_4122, "Black key brown"). + put(ObjectID.BLACK_CHEST_4123, "Black key crimson"). + put(ObjectID.BLACK_CHEST_4124, "Black key black"). + put(ObjectID.BLACK_CHEST_4125, "Black key purple"). + put(ObjectID.SILVER_CHEST, "Silver key red"). + put(ObjectID.SILVER_CHEST_4127, "Silver key brown"). + put(ObjectID.SILVER_CHEST_4128, "Silver key crimson"). + put(ObjectID.SILVER_CHEST_4129, "Silver key black"). + put(ObjectID.SILVER_CHEST_4130, "Silver key purple"). + build(); + // Last man standing map regions private static final Set LAST_MAN_STANDING_REGIONS = ImmutableSet.of(13658, 13659, 13914, 13915, 13916); @@ -199,6 +226,9 @@ public class LootTrackerPlugin extends Plugin @Inject private ChatMessageManager chatMessageManager; + @Inject + private LootManager lootManager; + private LootTrackerPanel panel; private NavigationButton navButton; @VisibleForTesting @@ -596,29 +626,36 @@ public class LootTrackerPlugin extends Plugin case "beginner": eventType = "Clue Scroll (Beginner)"; lootRecordType = LootRecordType.EVENT; - break; + return; case "easy": eventType = "Clue Scroll (Easy)"; lootRecordType = LootRecordType.EVENT; - break; + return; case "medium": eventType = "Clue Scroll (Medium)"; lootRecordType = LootRecordType.EVENT; - break; + return; case "hard": eventType = "Clue Scroll (Hard)"; lootRecordType = LootRecordType.EVENT; - break; + return; case "elite": eventType = "Clue Scroll (Elite)"; lootRecordType = LootRecordType.EVENT; - break; + return; case "master": eventType = "Clue Scroll (Master)"; lootRecordType = LootRecordType.EVENT; - break; + return; } } + + if (SHADE_CHEST_NO_KEY_PATTERN.matcher(message).matches()) + { + // Player didn't have the key they needed. + eventType = null; + lootRecordType = null; + } } @Subscribe @@ -630,12 +667,16 @@ public class LootTrackerPlugin extends Plugin } if (CHEST_EVENT_TYPES.containsValue(eventType) + || SHADE_CHEST_OBJECTS.containsValue(eventType) || HERBIBOAR_EVENT.equals(eventType) || HESPORI_EVENT.equals(eventType) || SEEDPACK_EVENT.equals(eventType) || lootRecordType == LootRecordType.PICKPOCKET) { - processInventoryLoot(eventType, lootRecordType, event.getItemContainer()); + WorldPoint playerLocation = client.getLocalPlayer().getWorldLocation(); + Collection groundItems = lootManager.getItemSpawns(playerLocation); + + processInventoryLoot(eventType, lootRecordType, event.getItemContainer(), groundItems); eventType = null; lootRecordType = null; } @@ -657,6 +698,13 @@ public class LootTrackerPlugin extends Plugin lootRecordType = LootRecordType.EVENT; takeInventorySnapshot(); } + + if (event.getMenuOption().equals("Open") && SHADE_CHEST_OBJECTS.containsKey(event.getId())) + { + eventType = SHADE_CHEST_OBJECTS.get(event.getId()); + lootRecordType = LootRecordType.EVENT; + takeInventorySnapshot(); + } } @Schedule( @@ -702,11 +750,11 @@ public class LootTrackerPlugin extends Plugin { inventorySnapshot = HashMultiset.create(); 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, ItemContainer inventoryContainer) + private void processInventoryLoot(String event, LootRecordType lootRecordType, ItemContainer inventoryContainer, Collection groundItems) { if (inventorySnapshot != null) { @@ -714,6 +762,9 @@ public class LootTrackerPlugin extends Plugin Arrays.stream(inventoryContainer.getItems()) .forEach(item -> currentInventory.add(item.getId(), item.getQuantity())); + groundItems.stream() + .forEach(item -> currentInventory.add(item.getId(), item.getQuantity())); + final Multiset diff = Multisets.difference(currentInventory, inventorySnapshot); List items = diff.entrySet().stream()