From b697f986bd72f5a1125d35a325bf75b8452fbc30 Mon Sep 17 00:00:00 2001 From: Owain van Brakel Date: Fri, 12 Jul 2019 01:55:25 +0200 Subject: [PATCH 1/3] idlenotifier: Fix checkstyle --- .../idlenotifier/IdleNotifierConfig.java | 162 +++++++++--------- .../idlenotifier/IdleNotifierPlugin.java | 4 +- 2 files changed, 83 insertions(+), 83 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierConfig.java index f8ad288e45..9789fa9d25 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierConfig.java @@ -32,10 +32,10 @@ import net.runelite.client.config.ConfigItem; public interface IdleNotifierConfig extends Config { @ConfigItem( - keyName = "animationidle", - name = "Idle Animation Notifications", - description = "Configures if idle animation notifications are enabled", - position = 1 + keyName = "animationidle", + name = "Idle Animation Notifications", + description = "Configures if idle animation notifications are enabled", + position = 1 ) default boolean animationIdle() { @@ -43,21 +43,21 @@ public interface IdleNotifierConfig extends Config } @ConfigItem( - keyName = "animationidlesound", - name = "Idle Animation Sound", - description = "Plays a custom sound accompanying Idle Animation notifications", - position = 2 + keyName = "animationidlesound", + name = "Idle Animation Sound", + description = "Plays a custom sound accompanying Idle Animation notifications", + position = 2 ) - default boolean animationIdleSound() + default boolean animationIdleSound() { return false; } @ConfigItem( - keyName = "interactionidle", - name = "Idle Interaction Notifications", - description = "Configures if idle interaction notifications are enabled e.g. combat, fishing", - position = 3 + keyName = "interactionidle", + name = "Idle Interaction Notifications", + description = "Configures if idle interaction notifications are enabled e.g. combat, fishing", + position = 3 ) default boolean interactionIdle() { @@ -65,21 +65,21 @@ public interface IdleNotifierConfig extends Config } @ConfigItem( - keyName = "interactionidlesound", - name = "Idle Interaction Sound", - description = "Plays a custom sound accompanying Idle Interaction notifications", - position = 4 + keyName = "interactionidlesound", + name = "Idle Interaction Sound", + description = "Plays a custom sound accompanying Idle Interaction notifications", + position = 4 ) - default boolean interactionIdleSound() + default boolean interactionIdleSound() { return false; } @ConfigItem( - keyName = "logoutidle", - name = "Idle Logout Notifications", - description = "Configures if the idle logout notifications are enabled", - position = 5 + keyName = "logoutidle", + name = "Idle Logout Notifications", + description = "Configures if the idle logout notifications are enabled", + position = 5 ) default boolean logoutIdle() { @@ -87,21 +87,21 @@ public interface IdleNotifierConfig extends Config } @ConfigItem( - keyName = "outofcombatsound", - name = "Out of Combat Sound", - description = "Plays a custom sound whenever you leave combat", - position = 6 + keyName = "outofcombatsound", + name = "Out of Combat Sound", + description = "Plays a custom sound whenever you leave combat", + position = 6 ) - default boolean outOfCombatSound() + default boolean outOfCombatSound() { return false; } @ConfigItem( - position = 7, - keyName = "skullNotification", - name = "Skull Notification", - description = "Receive a notification when you skull." + position = 7, + keyName = "skullNotification", + name = "Skull Notification", + description = "Receive a notification when you skull." ) default boolean showSkullNotification() { @@ -109,10 +109,10 @@ public interface IdleNotifierConfig extends Config } @ConfigItem( - position = 8, - keyName = "unskullNotification", - name = "Unskull Notification", - description = "Receive a notification when you unskull." + position = 8, + keyName = "unskullNotification", + name = "Unskull Notification", + description = "Receive a notification when you unskull." ) default boolean showUnskullNotification() { @@ -120,10 +120,10 @@ public interface IdleNotifierConfig extends Config } @ConfigItem( - keyName = "timeout", - name = "Idle Notification Delay (ms)", - description = "The notification delay after the player is idle", - position = 9 + keyName = "timeout", + name = "Idle Notification Delay (ms)", + description = "The notification delay after the player is idle", + position = 9 ) default int getIdleNotificationDelay() { @@ -131,10 +131,10 @@ public interface IdleNotifierConfig extends Config } @ConfigItem( - keyName = "hitpoints", - name = "Hitpoints Notification Threshold", - description = "The amount of hitpoints to send a notification at. A value of 0 will disable notification.", - position = 10 + keyName = "hitpoints", + name = "Hitpoints Notification Threshold", + description = "The amount of hitpoints to send a notification at. A value of 0 will disable notification.", + position = 10 ) default int getHitpointsThreshold() { @@ -142,21 +142,21 @@ public interface IdleNotifierConfig extends Config } @ConfigItem( - keyName = "playHealthSound", - name = "Play sound for Low Health", - description = "Will play a sound for every Low Health notification sent", - position = 12 + keyName = "playHealthSound", + name = "Play sound for Low Health", + description = "Will play a sound for every Low Health notification sent", + position = 12 ) - default boolean getPlayHealthSound() + default boolean getPlayHealthSound() { return false; } @ConfigItem( - keyName = "prayer", - name = "Prayer Notification Threshold", - description = "The amount of prayer points to send a notification at. A value of 0 will disable notification.", - position = 12 + keyName = "prayer", + name = "Prayer Notification Threshold", + description = "The amount of prayer points to send a notification at. A value of 0 will disable notification.", + position = 12 ) default int getPrayerThreshold() { @@ -164,21 +164,21 @@ public interface IdleNotifierConfig extends Config } @ConfigItem( - keyName = "playPrayerSound", - name = "Play sound for Low Prayer", - description = "Will play a sound for every Low Prayer notification sent", - position = 13 + keyName = "playPrayerSound", + name = "Play sound for Low Prayer", + description = "Will play a sound for every Low Prayer notification sent", + position = 13 ) - default boolean getPlayPrayerSound() + default boolean getPlayPrayerSound() { return false; } @ConfigItem( - keyName = "oxygen", - name = "Oxygen Notification Threshold", - position = 14, - description = "The amount of remaining oxygen to send a notification at. A value of 0 will disable notification." + keyName = "oxygen", + name = "Oxygen Notification Threshold", + position = 14, + description = "The amount of remaining oxygen to send a notification at. A value of 0 will disable notification." ) default int getOxygenThreshold() { @@ -186,10 +186,10 @@ public interface IdleNotifierConfig extends Config } @ConfigItem( - keyName = "spec", - name = "Special Attack Energy Notification Threshold", - position = 15, - description = "The amount of spec energy reached to send a notification at. A value of 0 will disable notification." + keyName = "spec", + name = "Special Attack Energy Notification Threshold", + position = 15, + description = "The amount of spec energy reached to send a notification at. A value of 0 will disable notification." ) default int getSpecEnergyThreshold() { @@ -197,34 +197,34 @@ public interface IdleNotifierConfig extends Config } @ConfigItem( - keyName = "specSound", - name = "Special Attack Energy Sound", - description = "Plays a custom sound accompanying Special Attack energy notifications", - position = 16 + keyName = "specSound", + name = "Special Attack Energy Sound", + description = "Plays a custom sound accompanying Special Attack energy notifications", + position = 16 ) - default boolean getSpecSound() + default boolean getSpecSound() { return false; } @ConfigItem( - keyName = "overspec", - name = "Over Special Energy Notification", - description = "Will repeat notifications for any value over the special energy threshold", - position = 17 + keyName = "overspec", + name = "Over Special Energy Notification", + description = "Will repeat notifications for any value over the special energy threshold", + position = 17 ) - default boolean getOverSpecEnergy() + default boolean getOverSpecEnergy() { return false; } @ConfigItem( - keyName = "pkers", - name = "PKer Notifier", - position = 18, - description = "Notifies if an attackable player based on your level range appears on screen.", - group = "PvP", - warning = "This will not notify you if the player is in your cc or is online on your friends list." + keyName = "pkers", + name = "PKer Notifier", + position = 18, + description = "Notifies if an attackable player based on your level range appears on screen.", + group = "PvP", + warning = "This will not notify you if the player is in your cc or is online on your friends list." ) default boolean notifyPkers() { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java index 3d84a2f099..369f82ec84 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java @@ -236,7 +236,7 @@ public class IdleNotifierPlugin extends Plugin case MINING_3A_PICKAXE: case DENSE_ESSENCE_CHIPPING: case DENSE_ESSENCE_CHISELING: - /* Herblore */ + /* Herblore */ case HERBLORE_PESTLE_AND_MORTAR: case HERBLORE_POTIONMAKING: case HERBLORE_MAKE_TAR: @@ -258,7 +258,7 @@ public class IdleNotifierPlugin extends Plugin case FARMING_HARVEST_FRUIT_TREE: case FARMING_HARVEST_FLOWER: case FARMING_HARVEST_ALLOTMENT: - /* Misc */ + /* Misc */ case PISCARILIUS_CRANE_REPAIR: case HOME_MAKE_TABLET: case SAND_COLLECTION: From 2e0af6122c2a85337928b5867fa0babc70cb5182 Mon Sep 17 00:00:00 2001 From: Owain van Brakel Date: Fri, 12 Jul 2019 02:04:16 +0200 Subject: [PATCH 2/3] idlenotifier: Inventory idle notification --- .../idlenotifier/IdleNotifierConfig.java | 43 +++--- .../idlenotifier/IdleNotifierPlugin.java | 122 ++++++++++++++++++ .../idlenotifier/OutOfItemsMapping.java | 77 +++++++++++ 3 files changed, 226 insertions(+), 16 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/OutOfItemsMapping.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierConfig.java index 9789fa9d25..6e5a9f6974 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierConfig.java @@ -42,11 +42,22 @@ public interface IdleNotifierConfig extends Config return true; } + @ConfigItem( + keyName = "outOfItemsIdle", + name = "Out of Items Idle Notifications", + position = 2, + description = "Configures if notifications for running out of items for another action are enabled." + ) + default boolean outOfItemsIdle() + { + return true; + } + @ConfigItem( keyName = "animationidlesound", name = "Idle Animation Sound", description = "Plays a custom sound accompanying Idle Animation notifications", - position = 2 + position = 3 ) default boolean animationIdleSound() { @@ -57,7 +68,7 @@ public interface IdleNotifierConfig extends Config keyName = "interactionidle", name = "Idle Interaction Notifications", description = "Configures if idle interaction notifications are enabled e.g. combat, fishing", - position = 3 + position = 4 ) default boolean interactionIdle() { @@ -68,7 +79,7 @@ public interface IdleNotifierConfig extends Config keyName = "interactionidlesound", name = "Idle Interaction Sound", description = "Plays a custom sound accompanying Idle Interaction notifications", - position = 4 + position = 5 ) default boolean interactionIdleSound() { @@ -79,7 +90,7 @@ public interface IdleNotifierConfig extends Config keyName = "logoutidle", name = "Idle Logout Notifications", description = "Configures if the idle logout notifications are enabled", - position = 5 + position = 6 ) default boolean logoutIdle() { @@ -90,7 +101,7 @@ public interface IdleNotifierConfig extends Config keyName = "outofcombatsound", name = "Out of Combat Sound", description = "Plays a custom sound whenever you leave combat", - position = 6 + position = 7 ) default boolean outOfCombatSound() { @@ -98,7 +109,7 @@ public interface IdleNotifierConfig extends Config } @ConfigItem( - position = 7, + position = 8, keyName = "skullNotification", name = "Skull Notification", description = "Receive a notification when you skull." @@ -109,7 +120,7 @@ public interface IdleNotifierConfig extends Config } @ConfigItem( - position = 8, + position = 9, keyName = "unskullNotification", name = "Unskull Notification", description = "Receive a notification when you unskull." @@ -123,7 +134,7 @@ public interface IdleNotifierConfig extends Config keyName = "timeout", name = "Idle Notification Delay (ms)", description = "The notification delay after the player is idle", - position = 9 + position = 10 ) default int getIdleNotificationDelay() { @@ -134,7 +145,7 @@ public interface IdleNotifierConfig extends Config keyName = "hitpoints", name = "Hitpoints Notification Threshold", description = "The amount of hitpoints to send a notification at. A value of 0 will disable notification.", - position = 10 + position = 11 ) default int getHitpointsThreshold() { @@ -156,7 +167,7 @@ public interface IdleNotifierConfig extends Config keyName = "prayer", name = "Prayer Notification Threshold", description = "The amount of prayer points to send a notification at. A value of 0 will disable notification.", - position = 12 + position = 13 ) default int getPrayerThreshold() { @@ -167,7 +178,7 @@ public interface IdleNotifierConfig extends Config keyName = "playPrayerSound", name = "Play sound for Low Prayer", description = "Will play a sound for every Low Prayer notification sent", - position = 13 + position = 14 ) default boolean getPlayPrayerSound() { @@ -177,7 +188,7 @@ public interface IdleNotifierConfig extends Config @ConfigItem( keyName = "oxygen", name = "Oxygen Notification Threshold", - position = 14, + position = 15, description = "The amount of remaining oxygen to send a notification at. A value of 0 will disable notification." ) default int getOxygenThreshold() @@ -188,7 +199,7 @@ public interface IdleNotifierConfig extends Config @ConfigItem( keyName = "spec", name = "Special Attack Energy Notification Threshold", - position = 15, + position = 16, description = "The amount of spec energy reached to send a notification at. A value of 0 will disable notification." ) default int getSpecEnergyThreshold() @@ -200,7 +211,7 @@ public interface IdleNotifierConfig extends Config keyName = "specSound", name = "Special Attack Energy Sound", description = "Plays a custom sound accompanying Special Attack energy notifications", - position = 16 + position = 17 ) default boolean getSpecSound() { @@ -211,7 +222,7 @@ public interface IdleNotifierConfig extends Config keyName = "overspec", name = "Over Special Energy Notification", description = "Will repeat notifications for any value over the special energy threshold", - position = 17 + position = 18 ) default boolean getOverSpecEnergy() { @@ -221,7 +232,7 @@ public interface IdleNotifierConfig extends Config @ConfigItem( keyName = "pkers", name = "PKer Notifier", - position = 18, + position = 19, description = "Notifies if an attackable player based on your level range appears on screen.", group = "PvP", warning = "This will not notify you if the player is in your cc or is online on your friends list." diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java index 369f82ec84..5055d1e89b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java @@ -29,6 +29,7 @@ import com.google.inject.Provides; import java.awt.TrayIcon; import java.time.Duration; import java.time.Instant; +import java.util.ArrayList; import java.util.Arrays; import java.util.EnumSet; import java.util.List; @@ -44,6 +45,9 @@ import net.runelite.api.Constants; import net.runelite.api.GameState; import net.runelite.api.GraphicID; import net.runelite.api.Hitsplat; +import net.runelite.api.InventoryID; +import net.runelite.api.Item; +import net.runelite.api.ItemContainer; import net.runelite.api.NPC; import net.runelite.api.NPCDefinition; import net.runelite.api.Player; @@ -58,6 +62,7 @@ import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GameTick; import net.runelite.api.events.HitsplatApplied; import net.runelite.api.events.InteractingChanged; +import net.runelite.api.events.ItemContainerChanged; import net.runelite.api.events.PlayerSpawned; import net.runelite.api.events.SpotAnimationChanged; import net.runelite.client.Notifier; @@ -117,6 +122,10 @@ public class IdleNotifierPlugin extends Plugin private int lastCombatCountdown = 0; private Instant sixHourWarningTime; private boolean ready; + private Instant lastTimeItemsUsedUp; + private List itemIdsPrevious = new ArrayList<>(); + private List itemQuantitiesPrevious = new ArrayList<>(); + private final List itemQuantitiesChange = new ArrayList<>(); private boolean lastInteractWasCombat; private SkullIcon lastTickSkull = null; private boolean isFirstTick = true; @@ -146,6 +155,7 @@ public class IdleNotifierPlugin extends Plugin private boolean getSpecSound; private boolean getOverSpecEnergy; private boolean notifyPkers; + private boolean outOfItemsIdle; @Provides IdleNotifierConfig provideConfig(ConfigManager configManager) @@ -299,6 +309,84 @@ public class IdleNotifierPlugin extends Plugin } } + @Subscribe + public void onItemContainerChanged(ItemContainerChanged event) + { + ItemContainer itemContainer = event.getItemContainer(); + + if (itemContainer != client.getItemContainer(InventoryID.INVENTORY) || !config.outOfItemsIdle()) + { + return; + } + + Item[] items = itemContainer.getItems(); + ArrayList itemQuantities = new ArrayList<>(); + ArrayList itemIds = new ArrayList<>(); + + // Populate list of items in inventory without duplicates + for (Item value : items) + { + int itemId = OutOfItemsMapping.mapFirst(value.getId()); + if (itemIds.indexOf(itemId) == -1) // -1 if item not yet in list + { + itemIds.add(itemId); + } + } + + // Populate quantity of each item in inventory + for (int j = 0; j < itemIds.size(); j++) + { + itemQuantities.add(0); + for (Item item : items) + { + if (itemIds.get(j) == OutOfItemsMapping.mapFirst(item.getId())) + { + itemQuantities.set(j, itemQuantities.get(j) + item.getQuantity()); + } + } + } + + itemQuantitiesChange.clear(); + + // Calculate the quantity of each item consumed by the last action + if (!itemIdsPrevious.isEmpty()) + { + for (int i = 0; i < itemIdsPrevious.size(); i++) + { + int id = itemIdsPrevious.get(i); + int currentIndex = itemIds.indexOf(id); + int currentQuantity; + if (currentIndex != -1) // -1 if item is no longer in inventory + { + currentQuantity = itemQuantities.get(currentIndex); + } + else + { + currentQuantity = 0; + } + itemQuantitiesChange.add(currentQuantity - itemQuantitiesPrevious.get(i)); + } + } + else + { + itemIdsPrevious = itemIds; + itemQuantitiesPrevious = itemQuantities; + return; + } + + // Check we have enough items left for another action. + for (int i = 0; i < itemQuantitiesPrevious.size(); i++) + { + if (-itemQuantitiesChange.get(i) * 2 > itemQuantitiesPrevious.get(i)) + { + lastTimeItemsUsedUp = Instant.now(); + return; + } + } + itemIdsPrevious = itemIds; + itemQuantitiesPrevious = itemQuantities; + } + @Subscribe public void onInteractingChanged(InteractingChanged event) { @@ -432,6 +520,7 @@ public class IdleNotifierPlugin extends Plugin || client.getKeyboardIdleTicks() < 10) { resetTimers(); + resetOutOfItemsIdleChecks(); return; } @@ -445,6 +534,13 @@ public class IdleNotifierPlugin extends Plugin notifier.notify("[" + local.getName() + "] is about to log out from being online for 6 hours!"); } + if (this.outOfItemsIdle && checkOutOfItemsIdle(waitDuration)) + { + notifier.notify("[" + local.getName() + "] has run out of items!"); + // If this triggers, don't also trigger animation idle notification afterwards. + lastAnimation = IDLE; + } + if (this.animationIdle && checkAnimationIdle(waitDuration, local)) { notifier.notify("[" + local.getName() + "] is now idle!"); @@ -713,6 +809,23 @@ public class IdleNotifierPlugin extends Plugin return false; } + private boolean checkOutOfItemsIdle(Duration waitDuration) + { + if (lastTimeItemsUsedUp == null) + { + return false; + } + + if (Instant.now().compareTo(lastTimeItemsUsedUp.plus(waitDuration)) >= 0) + { + resetTimers(); + resetOutOfItemsIdleChecks(); + return true; + } + + return false; + } + private void resetTimers() { final Player local = client.getLocalPlayer(); @@ -732,6 +845,14 @@ public class IdleNotifierPlugin extends Plugin } } + private void resetOutOfItemsIdleChecks() + { + lastTimeItemsUsedUp = null; + itemQuantitiesChange.clear(); + itemIdsPrevious.clear(); + itemQuantitiesPrevious.clear(); + } + private void skullNotifier() { final Player local = client.getLocalPlayer(); @@ -796,5 +917,6 @@ public class IdleNotifierPlugin extends Plugin this.getSpecSound = config.getSpecSound(); this.getOverSpecEnergy = config.getOverSpecEnergy(); this.notifyPkers = config.notifyPkers(); + this.outOfItemsIdle = config.outOfItemsIdle(); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/OutOfItemsMapping.java b/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/OutOfItemsMapping.java new file mode 100644 index 0000000000..10738f1273 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/OutOfItemsMapping.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2019, Twiglet1022 + * 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.plugins.idlenotifier; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; +import java.util.Collection; +import static net.runelite.api.ItemID.*; + +public enum OutOfItemsMapping +{ + AERIAL_FISHING_CUTTING(BLUEGILL, COMMON_TENCH, MOTTLED_EEL, GREATER_SIREN); + + private static final Multimap MAPPINGS = HashMultimap.create(); + private final int groupedItemKey; + private final int[] groupedItemIDs; + + static + { + for (final OutOfItemsMapping item : values()) + { + for (int itemId : item.groupedItemIDs) + { + MAPPINGS.put(itemId, item.groupedItemKey); + } + } + } + + OutOfItemsMapping(int groupedItemKey, int... groupedItemIDs) + { + this.groupedItemKey = groupedItemKey; + this.groupedItemIDs = groupedItemIDs; + } + + /** + * Some actions consume multiple different items. To properly handle these + * cases for the out of items notification the different items must be + * recognised as belonging to a single group. + * + * Map an item that is part of a group of items that are consumed by a single + * action to the first item in that group. + */ + public static int mapFirst(int itemId) + { + final Collection mapping = MAPPINGS.get(itemId); + + if (mapping == null || mapping.isEmpty()) + { + return itemId; + } + + return mapping.iterator().next(); + } + +} \ No newline at end of file From 3897c7e744f06e959a0326881d70c8c7eee4dc43 Mon Sep 17 00:00:00 2001 From: Owain van Brakel Date: Fri, 12 Jul 2019 02:06:54 +0200 Subject: [PATCH 3/3] idlenotifier: allow animations fallback for interacting checks --- .../idlenotifier/IdleNotifierPlugin.java | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java index 5055d1e89b..e2091dd882 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java @@ -127,6 +127,7 @@ public class IdleNotifierPlugin extends Plugin private List itemQuantitiesPrevious = new ArrayList<>(); private final List itemQuantitiesChange = new ArrayList<>(); private boolean lastInteractWasCombat; + private boolean interactingNotified; private SkullIcon lastTickSkull = null; private boolean isFirstTick = true; @@ -232,6 +233,17 @@ public class IdleNotifierPlugin extends Plugin /* Fishing */ case FISHING_CRUSHING_INFERNAL_EELS: case FISHING_CUTTING_SACRED_EELS: + case FISHING_BIG_NET: + case FISHING_NET: + case FISHING_POLE_CAST: + case FISHING_CAGE: + case FISHING_HARPOON: + case FISHING_BARBTAIL_HARPOON: + case FISHING_DRAGON_HARPOON: + case FISHING_INFERNAL_HARPOON: + case FISHING_OILY_ROD: + case FISHING_KARAMBWAN: + case FISHING_BAREHAND: /* Mining(Normal) */ case MINING_BRONZE_PICKAXE: case MINING_IRON_PICKAXE: @@ -275,6 +287,7 @@ public class IdleNotifierPlugin extends Plugin resetTimers(); lastAnimation = animation; lastAnimating = Instant.now(); + interactingNotified = false; break; case MAGIC_LUNAR_SHARED: if (graphic == GraphicID.BAKE_PIE) @@ -282,10 +295,12 @@ public class IdleNotifierPlugin extends Plugin resetTimers(); lastAnimation = animation; lastAnimating = Instant.now(); + interactingNotified = false; break; } case IDLE: lastAnimating = Instant.now(); + interactingNotified = false; break; default: // On unknown animation simply assume the animation is invalid and dont throw notification @@ -541,14 +556,6 @@ public class IdleNotifierPlugin extends Plugin lastAnimation = IDLE; } - if (this.animationIdle && checkAnimationIdle(waitDuration, local)) - { - notifier.notify("[" + local.getName() + "] is now idle!"); - if (this.animationIdleSound) - { - soundManager.playSound(Sound.IDLE); - } - } if (this.interactionIdle && checkInteractionIdle(waitDuration, local)) { if (lastInteractWasCombat) @@ -567,6 +574,16 @@ public class IdleNotifierPlugin extends Plugin soundManager.playSound(Sound.IDLE); } } + interactingNotified = true; + } + + if (this.animationIdle && checkAnimationIdle(waitDuration, local)) + { + notifier.notify("[" + local.getName() + "] is now idle!"); + if (this.animationIdleSound) + { + soundManager.playSound(Sound.IDLE); + } } if (checkLowHitpoints()) @@ -785,7 +802,7 @@ public class IdleNotifierPlugin extends Plugin private boolean checkAnimationIdle(Duration waitDuration, Player local) { - if (lastAnimation == IDLE) + if (lastAnimation == IDLE || interactingNotified) { return false; }