loottracker: Track herbiboar loot with an open herb sack

When looting the herbiboar with an open herb sack, instead of receiving
the herbs to your inventory, the herbs are deposited to the sack
directly and the player receives chat messages indicating the herbs they
received. This commit adds support for reading those chat messages when
looting the herbiboar.

This change incidentally fixes an issue which arose when the open herb
sack was introduced to the game where any inventory change after looting
the herbiboar would be tracked as herbiboar loot, such as drinking a
stamina potion.

Closes #10655
Fixes #10718
This commit is contained in:
Deon Zhao
2020-03-24 17:56:48 -07:00
committed by Adam
parent c60c88bb86
commit 65d63cd754
2 changed files with 121 additions and 3 deletions

View File

@@ -24,32 +24,66 @@
*/
package net.runelite.client.plugins.loottracker;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Guice;
import com.google.inject.testing.fieldbinder.Bind;
import com.google.inject.testing.fieldbinder.BoundFieldModule;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;
import javax.inject.Inject;
import net.runelite.api.ChatMessageType;
import net.runelite.api.Client;
import net.runelite.api.ItemID;
import net.runelite.api.IterableHashTable;
import net.runelite.api.MessageNode;
import net.runelite.api.Player;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.events.ChatMessage;
import net.runelite.client.account.SessionManager;
import net.runelite.client.game.ItemManager;
import net.runelite.client.game.ItemStack;
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.loottracker.LootRecordType;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import org.mockito.Mock;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class LootTrackerPluginTest
{
private static final Map<Integer, String> HERB_IDS_TO_NAMES = ImmutableMap.<Integer, String>builder()
.put(ItemID.GRIMY_GUAM_LEAF, "Grimy guam leaf")
.put(ItemID.GRIMY_MARRENTILL, "Grimy marrentill")
.put(ItemID.GRIMY_TARROMIN, "Grimy tarromin")
.put(ItemID.GRIMY_HARRALANDER, "Grimy harralander")
.put(ItemID.GRIMY_RANARR_WEED, "Grimy ranarr weed")
.put(ItemID.GRIMY_IRIT_LEAF, "Grimy irit leaf")
.put(ItemID.GRIMY_AVANTOE, "Grimy avantoe")
.put(ItemID.GRIMY_KWUARM, "Grimy kwuarm")
.put(ItemID.GRIMY_SNAPDRAGON, "Grimy snapdragon")
.put(ItemID.GRIMY_CADANTINE, "Grimy cadantine")
.put(ItemID.GRIMY_LANTADYME, "Grimy lantadyme")
.put(ItemID.GRIMY_DWARF_WEED, "Grimy dwarf weed")
.put(ItemID.GRIMY_TORSTOL, "Grimy torstol")
.build();
@Mock
@Bind
private ScheduledExecutorService scheduledExecutorService;
@@ -77,6 +111,10 @@ public class LootTrackerPluginTest
@Bind
private SessionManager sessionManager;
@Mock
@Bind
private ItemManager itemManager;
@Before
public void setUp()
{
@@ -106,4 +144,49 @@ public class LootTrackerPluginTest
assertEquals("Clue Scroll (Master)", lootTrackerPlugin.eventType);
assertEquals(LootRecordType.EVENT, lootTrackerPlugin.lootRecordType);
}
}
@Test
public void testHerbiboarHerbSack()
{
for (Map.Entry<Integer, String> herb : HERB_IDS_TO_NAMES.entrySet())
{
final int id = herb.getKey();
final String name = herb.getValue();
final String herbMessage = String.format("You put the %s herb into your herb sack.", name);
final String herbFullMessage = String.format("Your herb sack is too full to hold the %s herb.", name);
final ItemPrice herbPrice = new ItemPrice();
herbPrice.setId(id);
herbPrice.setName(name);
when(itemManager.search(name)).thenReturn(Collections.singletonList(herbPrice));
MessageNode node = mock(MessageNode.class);
when(node.getType()).thenReturn(ChatMessageType.SPAM);
when(node.getValue()).thenReturn(herbMessage);
MessageNode nodeFull = mock(MessageNode.class);
when(nodeFull.getType()).thenReturn(ChatMessageType.SPAM);
when(nodeFull.getValue()).thenReturn(herbFullMessage);
IterableHashTable<MessageNode> messageTable = mock(IterableHashTable.class);
Iterator<MessageNode> mockIterator = mock(Iterator.class);
when(mockIterator.hasNext()).thenReturn(true, true, false);
when(mockIterator.next()).thenReturn(node).thenReturn(nodeFull);
when(messageTable.iterator()).thenReturn(mockIterator);
when(client.getMessages()).thenReturn(messageTable);
LootTrackerPlugin lootTrackerPluginSpy = spy(this.lootTrackerPlugin);
doNothing().when(lootTrackerPluginSpy).addLoot(any(), anyInt(), 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(
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);
}
}
}