Skip to content

Commit 0208195

Browse files
committed
fix(loottracker): Track automated bird nest searching (runelite#19975)
- Added support for tracking the loot received from the next searched bird nest that's automated by the game itself - Modified LootTrackerPlugin#onItemContainerChanged to see if a bird nest was searched by the game and whether or not to keep processing inventory changes while there are searchable bird nests remaining - Added new test case LootTrackerPluginTest#testBirdNests
1 parent 636a5dc commit 0208195

2 files changed

Lines changed: 81 additions & 2 deletions

File tree

runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1221,12 +1221,29 @@ public void onItemContainerChanged(ItemContainerChanged event)
12211221

12221222
log.debug("Inv change: {} Ground items: {}", items, groundItems);
12231223

1224+
final Set<Integer> removedItemIDs = diffr.entrySet().stream().map(Multiset.Entry::getElement).collect(Collectors.toSet());
1225+
final Set<Integer> currentInventoryItemIDs = currentInventory.entrySet().stream().map(Multiset.Entry::getElement).collect(Collectors.toSet());
1226+
// Determines whether to ignore #resetEvent or not due to the game possibly continuing to modify the players inventory without any interaction
1227+
// An example of this would be searching bird nests, as after searching one nest, the game will continue to search the rest of the nests in the inventory until interrupted
1228+
boolean ignoreReset = false;
1229+
if (removedItemIDs.stream().anyMatch(BIRDNEST_IDS::contains))
1230+
{
1231+
onInvChange(collectInvItems(LootRecordType.EVENT, BIRDNEST_EVENT));
1232+
if (currentInventoryItemIDs.stream().anyMatch(BIRDNEST_IDS::contains))
1233+
{
1234+
ignoreReset = true;
1235+
}
1236+
}
1237+
12241238
if (inventorySnapshotCb != null)
12251239
{
12261240
inventorySnapshotCb.accept(items, groundItems, diffr);
12271241
}
12281242

1229-
resetEvent();
1243+
if (!ignoreReset)
1244+
{
1245+
resetEvent();
1246+
}
12301247
}
12311248

12321249
@Subscribe

runelite-client/src/test/java/net/runelite/client/plugins/loottracker/LootTrackerPluginTest.java

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import net.runelite.api.ItemComposition;
4444
import net.runelite.api.ItemContainer;
4545
import net.runelite.api.IterableHashTable;
46+
import net.runelite.api.MenuAction;
4647
import net.runelite.api.MessageNode;
4748
import net.runelite.api.Player;
4849
import net.runelite.api.Skill;
@@ -52,6 +53,7 @@
5253
import net.runelite.api.events.ChatMessage;
5354
import net.runelite.api.events.GameStateChanged;
5455
import net.runelite.api.events.ItemContainerChanged;
56+
import net.runelite.api.events.MenuOptionClicked;
5557
import net.runelite.api.events.WidgetLoaded;
5658
import net.runelite.api.gameval.InterfaceID;
5759
import net.runelite.api.gameval.InventoryID;
@@ -583,7 +585,7 @@ public void testWintertodtRewardCart()
583585
when(client.getLocalPlayer()).thenReturn(player);
584586
when(client.getBoostedSkillLevel(Skill.FIREMAKING)).thenReturn(99);
585587

586-
doNothing().when(lootTrackerPlugin).addLoot(any(), anyInt(), any(), any(), anyCollection());
588+
doNothing().when(lootTrackerPlugin).addLoot(any(), anyInt(), any(), any(), any(Collection.class));
587589

588590
ItemContainer itemContainer = mock(ItemContainer.class);
589591
when(itemContainer.getItems()).thenReturn(new Item[]{
@@ -686,4 +688,64 @@ public void testLargeSalvage()
686688

687689
verify(lootTrackerPlugin).addLoot("Large salvage", -1, LootRecordType.EVENT, null, Collections.singletonList(new ItemStack(ItemID.NAILS, 4)));
688690
}
691+
692+
@Test
693+
public void testBirdNests()
694+
{
695+
List<ItemStack> initialItems = Collections.singletonList(
696+
new ItemStack(ItemID.BIRD_NEST_SEEDS_JAN2019, 2)
697+
);
698+
sendInvChange(InventoryID.INV, initialItems);
699+
700+
MenuOptionClicked searchBirdNest = mock(MenuOptionClicked.class);
701+
when(searchBirdNest.getMenuAction()).thenReturn(MenuAction.CC_OP);
702+
when(searchBirdNest.isItemOp()).thenReturn(true);
703+
when(searchBirdNest.getMenuOption()).thenReturn("Search");
704+
when(searchBirdNest.getItemId()).thenReturn(ItemID.BIRD_NEST_SEEDS_JAN2019);
705+
lootTrackerPlugin.onMenuOptionClicked(searchBirdNest);
706+
707+
List<ItemStack> itemsAfterOneSearch = Arrays.asList(
708+
new ItemStack(ItemID.BIRD_NEST_EMPTY, 1),
709+
new ItemStack(ItemID.BIRD_NEST_SEEDS_JAN2019, 1),
710+
new ItemStack(ItemID.ACORN, 1)
711+
);
712+
ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", "You take an acorn out of the bird's nest.", "", 0);
713+
lootTrackerPlugin.onChatMessage(chatMessage);
714+
sendInvChange(InventoryID.INV, itemsAfterOneSearch);
715+
verify(lootTrackerPlugin).addLoot("Bird nest", -1, LootRecordType.EVENT, null, Arrays.asList(
716+
new ItemStack(ItemID.ACORN, 1),
717+
new ItemStack(ItemID.BIRD_NEST_EMPTY, 1)
718+
));
719+
720+
lootTrackerPlugin.onMenuOptionClicked(searchBirdNest);
721+
722+
List<ItemStack> itemsAfterTwoSearches = Arrays.asList(
723+
new ItemStack(ItemID.BIRD_NEST_EMPTY, 2),
724+
new ItemStack(ItemID.ACORN, 1),
725+
new ItemStack(ItemID.CELASTRUS_TREE_SEED, 1)
726+
);
727+
chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", "You take a celastrus tree seed out of the bird's nest.", "", 0);
728+
lootTrackerPlugin.onChatMessage(chatMessage);
729+
sendInvChange(InventoryID.INV, itemsAfterTwoSearches);
730+
verify(lootTrackerPlugin).addLoot("Bird nest", -1, LootRecordType.EVENT, null, Arrays.asList(
731+
new ItemStack(ItemID.BIRD_NEST_EMPTY, 1),
732+
new ItemStack(ItemID.CELASTRUS_TREE_SEED, 1)
733+
));
734+
735+
// Additional test to make sure ignoring reset didn't break anything
736+
List<ItemStack> itemsPostBirdNestTest = Arrays.asList(
737+
new ItemStack(ItemID.SAILING_LARGE_SHIPWRECK_SALVAGE, 1)
738+
);
739+
740+
sendInvChange(InventoryID.INV, itemsPostBirdNestTest);
741+
742+
chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", "You sort through the large salvage and find: 4 x Steel nails.", "", 0);
743+
lootTrackerPlugin.onChatMessage(chatMessage);
744+
745+
sendInvChange(InventoryID.INV, Collections.singletonList(
746+
new ItemStack(ItemID.NAILS, 4)
747+
));
748+
749+
verify(lootTrackerPlugin).addLoot("Large salvage", -1, LootRecordType.EVENT, null, Collections.singletonList(new ItemStack(ItemID.NAILS, 4)));
750+
}
689751
}

0 commit comments

Comments
 (0)