From b32ea38d479409d8d7bdda46e5c39e7c51443e7f Mon Sep 17 00:00:00 2001 From: TheStonedTurtle <29030969+TheStonedTurtle@users.noreply.github.com> Date: Fri, 15 Feb 2019 21:54:47 -0800 Subject: [PATCH 1/3] Add ItemUtil w/ Tests --- .../net/runelite/client/util/ItemUtil.java | 200 ++++++++++++++++++ .../runelite/client/util/ItemUtilTest.java | 137 ++++++++++++ 2 files changed, 337 insertions(+) create mode 100644 runelite-client/src/main/java/net/runelite/client/util/ItemUtil.java create mode 100644 runelite-client/src/test/java/net/runelite/client/util/ItemUtilTest.java diff --git a/runelite-client/src/main/java/net/runelite/client/util/ItemUtil.java b/runelite-client/src/main/java/net/runelite/client/util/ItemUtil.java new file mode 100644 index 0000000000..1a29922ff5 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/util/ItemUtil.java @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2018, TheStonedTurtle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.util; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; +import net.runelite.api.Item; +import net.runelite.http.api.loottracker.GameItem; + +/** + * Utility class for Item arrays. + */ +public class ItemUtil +{ + /** + * Converts itemArray into a GameItem collection limited to the passed ids + * Consolidates all matching Item's qty, by id + * @param itemArray item array to work on + * @param ids item ids to include in result + * @return Map of GameItem by item id + */ + public static Map toGameItemMap(Item[] itemArray, @Nullable Set ids) + { + final Map map = new HashMap<>(); + for (Item i : itemArray) + { + final int id = i.getId(); + if (ids == null || ids.contains(id)) + { + int qty = i.getQuantity(); + if (map.containsKey(id)) + { + qty += map.get(id).getQty(); + } + map.put(id, new GameItem(id, qty)); + } + } + + return map; + } + + /** + * Converts itemArray into a GameItem collection + * Consolidates all matching Item's qty, by id + * @param itemArray item array to work on + * @return Map of GameItem by item id + */ + public static Map toGameItemMap(Item[] itemArray) + { + return toGameItemMap(itemArray, null); + } + + /** + * Checks that the itemArray contains the all of the requested ids + * @param itemArray item array to work on + * @param ids item ids to check for + * @return true if itemArray contains all requested item ids + */ + public static boolean containsAllItemIds(Item[] itemArray, Set ids) + { + return toGameItemMap(itemArray, ids).size() == ids.size(); + } + + /** + * Checks if itemArray contains any item id that also exists in ids + * @param itemArray item array to work on + * @param ids item ids to check for + * @return true if any item in itemArray contains any id from ids + */ + public static boolean containsAnyItemId(Item[] itemArray, Set ids) + { + for (Item i : itemArray) + { + final int id = i.getId(); + if (ids.contains(id)) + { + return true; + } + } + + return false; + } + + /** + * Checks if any item id in itemArray matches itemID + * @param itemArray item array to work on + * @param itemID item id to check for + * @return true if any item in itemArray matches itemID + */ + public static boolean containsItemId(Item[] itemArray, int itemID) + { + for (Item i : itemArray) + { + if (i.getId() == itemID) + { + return true; + } + } + + return false; + } + + /** + * Returns null if index is bigger than array otherwise array content. + * @param itemArray item array to check + * @param index index to grab + * @return null if index is bigger than array otherwise array content + */ + public static Item safeGetItemAtIndex(Item[] itemArray, int index) + { + if (itemArray.length <= index) + { + return null; + } + + return itemArray[index]; + } + + /** + * Returns -1 if index is bigger than array otherwise array contents `id` value + * @param itemArray item array to check + * @param index index to grab + * @return -1 if index is bigger than array otherwise array contents `id` value + */ + public static Integer safeGetItemIdAtIndex(Item[] itemArray, int index) + { + if (itemArray.length <= index) + { + return -1; + } + + return itemArray[index].getId(); + } + + /** + * Checks that the itemArray contains all requestedItems. Must contain >= the requested qty for each id + * Uses GameItem to represent the requestedItems since we can't easily create Item instances + * @param itemArray item array to check against + * @param requestedItems Collection of GameItems which contain the item id & minimum qty + * @return true if contains all requestedItems + */ + public static boolean containsAllGameItems(Item[] itemArray, Collection requestedItems) + { + final Map map = toGameItemMap(itemArray, null); + for (GameItem i : requestedItems) + { + final int id = i.getId(); + GameItem item = map.get(id); + if (item == null) + { + return false; + } + + if (item.getQty() < i.getQty()) + { + return false; + } + } + + return true; + } + + /** + * Checks that the itemArray contains all requestedItems. Must contain >= the requested qty for each id + * Uses GameItem to represent the requestedItems since we can't easily create Item instances + * @param itemArray item array to check against + * @param requestedItems GameItem(s) to request + * @return true if contains all requestedItems + */ + public static boolean containsAllGameItems(Item[] itemArray, GameItem... requestedItems) + { + return containsAllGameItems(itemArray, Arrays.asList(requestedItems)); + } +} diff --git a/runelite-client/src/test/java/net/runelite/client/util/ItemUtilTest.java b/runelite-client/src/test/java/net/runelite/client/util/ItemUtilTest.java new file mode 100644 index 0000000000..f69238896d --- /dev/null +++ b/runelite-client/src/test/java/net/runelite/client/util/ItemUtilTest.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2018, TheStonedTurtle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.util; + +import com.google.common.collect.ImmutableSet; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import net.runelite.api.Item; +import net.runelite.api.ItemID; +import net.runelite.http.api.loottracker.GameItem; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; +import org.junit.Test; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class ItemUtilTest +{ + private static final Set SOME_IDS = ImmutableSet.of(ItemID.MITHRIL_BAR, ItemID.DRAGON_BONES); + private static final Set WRONG_IDS = ImmutableSet.of(ItemID.SCYTHE_OF_VITUR, ItemID.TWISTED_BOW); + private static final Set MIX_IDS = ImmutableSet.of( + ItemID.MITHRIL_BAR, ItemID.DRAGON_BONES, + ItemID.SCYTHE_OF_VITUR, ItemID.TWISTED_BOW + ); + + private static final Map SOME_MAP = new HashMap<>(); + private static final Map ALL_MAP = new HashMap<>(); + + private static final Item[] items = new Item[6]; + + static + { + SOME_MAP.put(ItemID.MITHRIL_BAR, new GameItem(ItemID.MITHRIL_BAR, 6)); + SOME_MAP.put(ItemID.DRAGON_BONES, new GameItem(ItemID.DRAGON_BONES, 2)); + + ALL_MAP.putAll(SOME_MAP); + ALL_MAP.put(ItemID.COINS_995, new GameItem(ItemID.COINS_995, 1000)); + ALL_MAP.put(ItemID.CHEWED_BONES, new GameItem(ItemID.CHEWED_BONES, 1)); + + items[0] = createItem(ItemID.MITHRIL_BAR, 3); + items[1] = createItem(ItemID.DRAGON_BONES, 1); + items[2] = createItem(ItemID.COINS_995, 1000); + + items[3] = createItem(ItemID.MITHRIL_BAR, 3); + items[4] = createItem(ItemID.DRAGON_BONES, 1); + items[5] = createItem(ItemID.CHEWED_BONES, 1); + } + + private static Item createItem(int id, int qty) + { + Item i = mock(Item.class); + when(i.getId()) + .thenReturn(id); + when(i.getQuantity()) + .thenReturn(qty); + + return i; + } + + @Test + public void toGameItemMap() + { + Map itemMap = ItemUtil.toGameItemMap(items, SOME_IDS); + assertEquals(SOME_MAP, itemMap); + assertNotEquals(ALL_MAP, itemMap); + + Map itemMap2 = ItemUtil.toGameItemMap(items); + assertNotEquals(SOME_MAP, itemMap2); + assertEquals(ALL_MAP, itemMap2); + } + + @Test + public void containsAllItemIds() + { + assertTrue(ItemUtil.containsAllItemIds(items, SOME_IDS)); + assertFalse(ItemUtil.containsAllItemIds(items, WRONG_IDS)); + assertFalse(ItemUtil.containsAllItemIds(items, MIX_IDS)); + } + + @Test + public void containsAnyItemId() + { + assertTrue(ItemUtil.containsAnyItemId(items, SOME_IDS)); + assertFalse(ItemUtil.containsAnyItemId(items, WRONG_IDS)); + assertTrue(ItemUtil.containsAnyItemId(items, MIX_IDS)); + } + + @Test + public void containsItemId() + { + assertTrue(ItemUtil.containsItemId(items, ItemID.COINS_995)); + assertFalse(ItemUtil.containsItemId(items, ItemID.TWISTED_BOW)); + } + + @Test + public void containsAllGameItems() + { + assertTrue(ItemUtil.containsAllGameItems(items, SOME_MAP.values())); + assertTrue(ItemUtil.containsAllGameItems(items, ALL_MAP.values())); + + Collection wrongItems = new ArrayList<>(SOME_MAP.values()); + wrongItems.add(new GameItem(ItemID.TWISTED_BOW, 1)); + assertFalse(ItemUtil.containsAllGameItems(items, wrongItems)); + + assertFalse(ItemUtil.containsAllGameItems(items, new GameItem(ItemID.MITHRIL_BAR, 7))); + assertTrue(ItemUtil.containsAllGameItems(items, new GameItem(ItemID.MITHRIL_BAR, 6))); + assertTrue(ItemUtil.containsAllGameItems(items, new GameItem(ItemID.MITHRIL_BAR, 5))); + assertFalse(ItemUtil.containsAllGameItems(items, new GameItem(ItemID.MITHRIL_BAR, 5), new GameItem(ItemID.TWISTED_BOW, 1))); + } +} From dbb659c7392e7ea707c4fb1dbc00d72977fbf47a Mon Sep 17 00:00:00 2001 From: TheStonedTurtle <29030969+TheStonedTurtle@users.noreply.github.com> Date: Fri, 15 Feb 2019 22:02:23 -0800 Subject: [PATCH 2/3] Implement ItemUtil for plugins --- .../client/plugins/cannon/CannonPlugin.java | 47 +++---------------- .../plugins/cluescrolls/ClueScrollPlugin.java | 7 +-- .../clues/ThreeStepCrypticClue.java | 16 +++---- .../client/plugins/fishing/FishingPlugin.java | 46 +++++------------- .../itemstats/potions/PrayerPotion.java | 42 +++++------------ .../plugins/roguesden/RoguesDenPlugin.java | 12 +---- 6 files changed, 41 insertions(+), 129 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonPlugin.java index 2d96d26e4c..f57097360a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonPlugin.java @@ -24,6 +24,7 @@ */ package net.runelite.client.plugins.cannon; +import com.google.common.collect.ImmutableSet; import com.google.inject.Provides; import java.awt.Color; import java.time.temporal.ChronoUnit; @@ -38,7 +39,6 @@ import net.runelite.api.ChatMessageType; import net.runelite.api.Client; import net.runelite.api.GameObject; import net.runelite.api.InventoryID; -import net.runelite.api.Item; import net.runelite.api.ItemID; import static net.runelite.api.ObjectID.CANNON_BASE; import net.runelite.api.Player; @@ -62,6 +62,7 @@ import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.task.Schedule; import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.ui.overlay.infobox.InfoBoxManager; +import net.runelite.client.util.ItemUtil; @PluginDescriptor( name = "Cannon", @@ -72,6 +73,9 @@ public class CannonPlugin extends Plugin { private static final Pattern NUMBER_PATTERN = Pattern.compile("([0-9]+)"); private static final int MAX_CBALLS = 30; + private static final ImmutableSet CANNON_PARTS = ImmutableSet.of( + ItemID.CANNON_BASE, ItemID.CANNON_STAND, ItemID.CANNON_BARRELS, ItemID.CANNON_FURNACE + ); private CannonCounter counter; private boolean skipProjectileCheckThisTick; @@ -153,46 +157,7 @@ public class CannonPlugin extends Plugin return; } - boolean hasBase = false; - boolean hasStand = false; - boolean hasBarrels = false; - boolean hasFurnace = false; - boolean hasAll = false; - - if (!cannonPlaced) - { - for (Item item : event.getItemContainer().getItems()) - { - if (item == null) - { - continue; - } - - switch (item.getId()) - { - case ItemID.CANNON_BASE: - hasBase = true; - break; - case ItemID.CANNON_STAND: - hasStand = true; - break; - case ItemID.CANNON_BARRELS: - hasBarrels = true; - break; - case ItemID.CANNON_FURNACE: - hasFurnace = true; - break; - } - - if (hasBase && hasStand && hasBarrels && hasFurnace) - { - hasAll = true; - break; - } - } - } - - cannonSpotOverlay.setHidden(!hasAll); + cannonSpotOverlay.setHidden(!ItemUtil.containsAllItemIds(event.getItemContainer().getItems(), CANNON_PARTS)); } @Subscribe diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/ClueScrollPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/ClueScrollPlugin.java index 8a24153854..768553e7f3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/ClueScrollPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/ClueScrollPlugin.java @@ -31,10 +31,8 @@ import com.google.inject.Provides; import java.awt.image.BufferedImage; import java.time.Duration; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Objects; -import java.util.stream.Stream; import javax.inject.Inject; import lombok.Getter; import lombok.extern.slf4j.Slf4j; @@ -86,6 +84,7 @@ import net.runelite.client.plugins.cluescrolls.clues.ThreeStepCrypticClue; import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.ui.overlay.worldmap.WorldMapPointManager; import net.runelite.client.util.ImageUtil; +import net.runelite.client.util.ItemUtil; import net.runelite.client.util.Text; @PluginDescriptor( @@ -234,10 +233,8 @@ public class ClueScrollPlugin extends Plugin // Check if item was removed from inventory if (clue != null && clueItemId != null) { - final Stream items = Arrays.stream(event.getItemContainer().getItems()); - // Check if clue was removed from inventory - if (items.noneMatch(item -> itemManager.getItemComposition(item.getId()).getId() == clueItemId)) + if (!ItemUtil.containsItemId(event.getItemContainer().getItems(), clueItemId)) { resetClue(true); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/ThreeStepCrypticClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/ThreeStepCrypticClue.java index 995c6b90e0..34d036ae5a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/ThreeStepCrypticClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/ThreeStepCrypticClue.java @@ -28,15 +28,12 @@ import java.awt.Dimension; import java.awt.Graphics2D; import java.util.AbstractMap; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Map; -import java.util.stream.Stream; import lombok.Getter; import lombok.RequiredArgsConstructor; import net.runelite.api.Client; import net.runelite.api.InventoryID; -import net.runelite.api.Item; import static net.runelite.api.ItemID.TORN_CLUE_SCROLL_PART_1; import static net.runelite.api.ItemID.TORN_CLUE_SCROLL_PART_2; import static net.runelite.api.ItemID.TORN_CLUE_SCROLL_PART_3; @@ -48,6 +45,7 @@ import net.runelite.client.plugins.cluescrolls.ClueScrollPlugin; import net.runelite.client.ui.overlay.components.LineComponent; import net.runelite.client.ui.overlay.components.PanelComponent; import net.runelite.client.ui.overlay.components.TitleComponent; +import net.runelite.client.util.ItemUtil; import net.runelite.client.util.Text; @Getter @@ -127,21 +125,19 @@ public class ThreeStepCrypticClue extends ClueScroll implements TextClueScroll, if (event.getItemContainer() == client.getItemContainer(InventoryID.INVENTORY)) { boolean success = false; - success |= checkForPart(event, itemManager, TORN_CLUE_SCROLL_PART_1, 0); - success |= checkForPart(event, itemManager, TORN_CLUE_SCROLL_PART_2, 1); - success |= checkForPart(event, itemManager, TORN_CLUE_SCROLL_PART_3, 2); + success |= checkForPart(event, TORN_CLUE_SCROLL_PART_1, 0); + success |= checkForPart(event, TORN_CLUE_SCROLL_PART_2, 1); + success |= checkForPart(event, TORN_CLUE_SCROLL_PART_3, 2); return success; } return false; } - private boolean checkForPart(final ItemContainerChanged event, ItemManager itemManager, int clueScrollPart, int index) + private boolean checkForPart(final ItemContainerChanged event, int clueScrollPart, int index) { - final Stream items = Arrays.stream(event.getItemContainer().getItems()); - // If we have the part then that step is done - if (items.anyMatch(item -> itemManager.getItemComposition(item.getId()).getId() == clueScrollPart)) + if (ItemUtil.containsItemId(event.getItemContainer().getItems(), clueScrollPart)) { final Map.Entry entry = clueSteps.get(index); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingPlugin.java index 07977334e4..aae5c0f00b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingPlugin.java @@ -25,6 +25,7 @@ */ package net.runelite.client.plugins.fishing; +import com.google.common.collect.ImmutableSet; import com.google.inject.Provides; import java.time.Duration; import java.time.Instant; @@ -43,7 +44,6 @@ import net.runelite.api.ChatMessageType; import net.runelite.api.Client; import net.runelite.api.GameState; import net.runelite.api.InventoryID; -import net.runelite.api.Item; import net.runelite.api.ItemContainer; import net.runelite.api.ItemID; import net.runelite.api.NPC; @@ -65,6 +65,7 @@ import net.runelite.client.plugins.PluginDependency; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.xptracker.XpTrackerPlugin; import net.runelite.client.ui.overlay.OverlayManager; +import net.runelite.client.util.ItemUtil; @PluginDescriptor( name = "Fishing", @@ -81,6 +82,15 @@ public class FishingPlugin extends Plugin private static final int TRAWLER_ACTIVITY_THRESHOLD = Math.round(0.15f * 255); + private static final ImmutableSet FISHING_TOOLS = ImmutableSet.of( + ItemID.DRAGON_HARPOON, ItemID.INFERNAL_HARPOON, ItemID.INFERNAL_HARPOON_UNCHARGED, ItemID.HARPOON, + ItemID.BARBTAIL_HARPOON, ItemID.BIG_FISHING_NET, ItemID.SMALL_FISHING_NET, ItemID.SMALL_FISHING_NET_6209, + ItemID.FISHING_ROD, ItemID.FLY_FISHING_ROD, ItemID.BARBARIAN_ROD, ItemID.OILY_FISHING_ROD, + ItemID.LOBSTER_POT, ItemID.KARAMBWAN_VESSEL, ItemID.KARAMBWAN_VESSEL_3159, + ItemID.CORMORANTS_GLOVE, ItemID.CORMORANTS_GLOVE_22817, + ItemID.PEARL_FISHING_ROD, ItemID.PEARL_FLY_FISHING_ROD, ItemID.PEARL_BARBARIAN_ROD + ); + @Getter(AccessLevel.PACKAGE) private final FishingSession session = new FishingSession(); @@ -226,39 +236,7 @@ public class FishingPlugin extends Plugin return false; } - for (Item item : itemContainer.getItems()) - { - if (item == null) - { - continue; - } - switch (item.getId()) - { - case ItemID.DRAGON_HARPOON: - case ItemID.INFERNAL_HARPOON: - case ItemID.INFERNAL_HARPOON_UNCHARGED: - case ItemID.HARPOON: - case ItemID.BARBTAIL_HARPOON: - case ItemID.BIG_FISHING_NET: - case ItemID.SMALL_FISHING_NET: - case ItemID.SMALL_FISHING_NET_6209: - case ItemID.FISHING_ROD: - case ItemID.FLY_FISHING_ROD: - case ItemID.PEARL_BARBARIAN_ROD: - case ItemID.PEARL_FISHING_ROD: - case ItemID.PEARL_FLY_FISHING_ROD: - case ItemID.BARBARIAN_ROD: - case ItemID.OILY_FISHING_ROD: - case ItemID.LOBSTER_POT: - case ItemID.KARAMBWAN_VESSEL: - case ItemID.KARAMBWAN_VESSEL_3159: - case ItemID.CORMORANTS_GLOVE: - case ItemID.CORMORANTS_GLOVE_22817: - return true; - } - } - - return false; + return ItemUtil.containsAnyItemId(itemContainer.getItems(), FISHING_TOOLS); } @Subscribe diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/potions/PrayerPotion.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/potions/PrayerPotion.java index 4c0bfff6a1..bd2fbfa4b6 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/potions/PrayerPotion.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/potions/PrayerPotion.java @@ -24,13 +24,16 @@ */ package net.runelite.client.plugins.itemstats.potions; +import com.google.common.collect.ImmutableSet; import net.runelite.api.Client; +import net.runelite.api.EquipmentInventorySlot; import net.runelite.api.InventoryID; import net.runelite.api.Item; import net.runelite.api.ItemContainer; import net.runelite.api.ItemID; import net.runelite.client.plugins.itemstats.StatBoost; import static net.runelite.client.plugins.itemstats.stats.Stats.PRAYER; +import net.runelite.client.util.ItemUtil; public class PrayerPotion extends StatBoost { @@ -42,8 +45,11 @@ public class PrayerPotion extends StatBoost this.delta = delta; } - private static final int RING_SLOT = 12; - private static final int CAPE_SLOT = 1; + private static final ImmutableSet HOLY_WRENCH_IDS = ImmutableSet.of( + ItemID.HOLY_WRENCH, ItemID.PRAYER_CAPE, ItemID.PRAYER_CAPET, ItemID.MAX_CAPE, ItemID.MAX_CAPE_13342, + // No idea what these are + ItemID.PRAYER_CAPE_10643, ItemID.MAX_CAPE_13282 + ); @Override public int heals(Client client) @@ -54,40 +60,18 @@ public class PrayerPotion extends StatBoost if (equipContainer != null) { Item[] equip = equipContainer.getItems(); + final int ring = ItemUtil.safeGetItemIdAtIndex(equip, EquipmentInventorySlot.RING.getSlotIdx()); + final int cape = ItemUtil.safeGetItemIdAtIndex(equip, EquipmentInventorySlot.CAPE.getSlotIdx()); - hasHolyWrench |= equip.length > RING_SLOT && equip[RING_SLOT].getId() == ItemID.RING_OF_THE_GODS_I; - if (equip.length > CAPE_SLOT) - { - int cape = equip[CAPE_SLOT].getId(); - hasHolyWrench |= cape == ItemID.PRAYER_CAPE; - hasHolyWrench |= cape == ItemID.PRAYER_CAPET; - hasHolyWrench |= cape == ItemID.PRAYER_CAPE_10643; // No idea what this is - hasHolyWrench |= cape == ItemID.MAX_CAPE; - hasHolyWrench |= cape == ItemID.MAX_CAPE_13282; // Or these - hasHolyWrench |= cape == ItemID.MAX_CAPE_13342; - } + hasHolyWrench |= ring == ItemID.RING_OF_THE_GODS_I; + hasHolyWrench |= HOLY_WRENCH_IDS.contains(cape); } if (!hasHolyWrench) { ItemContainer invContainer = client.getItemContainer(InventoryID.INVENTORY); if (invContainer != null) { - for (Item itemStack : invContainer.getItems()) - { - int item = itemStack.getId(); - hasHolyWrench |= item == ItemID.HOLY_WRENCH; - hasHolyWrench |= item == ItemID.PRAYER_CAPE; - hasHolyWrench |= item == ItemID.PRAYER_CAPET; - hasHolyWrench |= item == ItemID.PRAYER_CAPE_10643; - hasHolyWrench |= item == ItemID.MAX_CAPE; - hasHolyWrench |= item == ItemID.MAX_CAPE_13282; - hasHolyWrench |= item == ItemID.MAX_CAPE_13342; - - if (hasHolyWrench) - { - break; - } - } + hasHolyWrench = ItemUtil.containsAnyItemId(invContainer.getItems(), HOLY_WRENCH_IDS); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/roguesden/RoguesDenPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/roguesden/RoguesDenPlugin.java index b7e8b682b0..b0c4eaee5e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/roguesden/RoguesDenPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/roguesden/RoguesDenPlugin.java @@ -32,7 +32,6 @@ import lombok.Getter; import net.runelite.api.Client; import net.runelite.api.GameState; import net.runelite.api.InventoryID; -import net.runelite.api.Item; import net.runelite.api.ItemContainer; import static net.runelite.api.ItemID.MYSTIC_JEWEL; import net.runelite.api.Tile; @@ -49,6 +48,7 @@ import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.task.Schedule; import net.runelite.client.ui.overlay.OverlayManager; +import net.runelite.client.util.ItemUtil; @PluginDescriptor( name = "Rogues' Den", @@ -104,15 +104,7 @@ public class RoguesDenPlugin extends Plugin return false; } - for (Item item : container.getItems()) - { - if (item.getId() == MYSTIC_JEWEL) - { - return true; - } - } - - return false; + return ItemUtil.containsItemId(container.getItems(), MYSTIC_JEWEL); } @Subscribe From 2776ef847b529fb2785099af9ad02cf950143210 Mon Sep 17 00:00:00 2001 From: TheStonedTurtle <29030969+TheStonedTurtle@users.noreply.github.com> Date: Fri, 15 Feb 2019 22:50:47 -0800 Subject: [PATCH 3/3] Optimize containsAllItemIds --- .../net/runelite/client/util/ItemUtil.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/util/ItemUtil.java b/runelite-client/src/main/java/net/runelite/client/util/ItemUtil.java index 1a29922ff5..c3cfeb599e 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/ItemUtil.java +++ b/runelite-client/src/main/java/net/runelite/client/util/ItemUtil.java @@ -27,6 +27,7 @@ package net.runelite.client.util; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Set; import javax.annotation.Nullable; @@ -84,7 +85,23 @@ public class ItemUtil */ public static boolean containsAllItemIds(Item[] itemArray, Set ids) { - return toGameItemMap(itemArray, ids).size() == ids.size(); + final Set found = new HashSet<>(); + for (Item i : itemArray) + { + final int id = i.getId(); + if (ids.contains(id)) + { + found.add(id); + // Early break if possible + if (found.size() == ids.size()) + { + return true; + } + } + + } + + return found.size() == ids.size(); } /**